blob: 0b93f8d2d6f07a32e4ca4c877c2eaea13bbdc38e [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Ramu Gottipatifa5be522021-12-28 19:18:21 +05302 * Copyright (c) 2013-2022, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070039#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041/*#define VERY_VERY_VERBOSE_LOGGING*/
42#ifdef VERY_VERY_VERBOSE_LOGGING
43#define ALOGVV ALOGV
44#else
45#define ALOGVV(a...) do { } while(0)
46#endif
George Gao3018ede2019-10-23 13:23:00 -070047#include <limits.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080048#include <errno.h>
49#include <pthread.h>
50#include <stdint.h>
51#include <sys/time.h>
52#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070054#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include <sys/resource.h>
56#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
Aalique Grahame22e49102018-12-18 14:23:57 -080058#include <log/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070059#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080060#include <cutils/str_parms.h>
61#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062#include <cutils/atomic.h>
63#include <cutils/sched_policy.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070064#include <hardware/audio_effect.h>
Haynes Mathew George484e8d22017-07-31 18:55:17 -070065#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070066#include <system/thread_defs.h>
Haynes Mathew George16081042017-05-31 17:16:49 -070067#include <tinyalsa/asoundlib.h>
Andy Hunga1f48fa2019-07-01 18:14:53 -070068#include <utils/Timers.h> // systemTime
Eric Laurentb23d5282013-05-14 15:27:20 -070069#include <audio_effects/effect_aec.h>
70#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053071#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080072#include "audio_hw.h"
Wei Wangf7ca6c92017-11-21 14:51:20 -080073#include "audio_perf.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070074#include "platform_api.h"
75#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070076#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080077#include "voice_extn.h"
Ashish Jaind5694242017-09-05 20:09:06 +053078#include "ip_hdlr_intf.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080079
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070080#include "sound/compress_params.h"
Xiaojun Sang782e5b12020-06-29 21:13:06 +080081
82#ifdef AUDIO_GKI_ENABLED
83#include "sound/audio_compressed_formats.h"
84#endif
85
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080086#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080087
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053088#ifdef DYNAMIC_LOG_ENABLED
89#include <log_xml_parser.h>
90#define LOG_MASK HAL_MOD_FILE_AUDIO_HW
91#include <log_utils.h>
92#endif
93
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070094#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053095/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
96#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070097#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Vikram Panduranga93f080e2017-06-07 18:16:14 -070098#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Arun Mirpuri5d170872019-03-26 13:21:31 -070099#define MMAP_PLAYBACK_VOLUME_MAX 0x2000
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530100#define PCM_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530101#define DSD_VOLUME_MIN_DB (-110)
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700102#define INVALID_OUT_VOLUME -1
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700103#define AUDIO_IO_PORTS_MAX 32
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700104
Zhou Songbaddf9f2020-11-20 13:57:39 +0800105#define PLAYBACK_GAIN_MAX 1.0f
Aalique Grahame22e49102018-12-18 14:23:57 -0800106#define RECORD_GAIN_MIN 0.0f
107#define RECORD_GAIN_MAX 1.0f
108#define RECORD_VOLUME_CTL_MAX 0x2000
109
110/* treat as unsigned Q1.13 */
111#define APP_TYPE_GAIN_DEFAULT 0x2000
112
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700113#define PROXY_OPEN_RETRY_COUNT 100
114#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800115
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800116#define GET_USECASE_AUDIO_PLAYBACK_PRIMARY(db) \
117 (db)? USECASE_AUDIO_PLAYBACK_DEEP_BUFFER : \
118 USECASE_AUDIO_PLAYBACK_LOW_LATENCY
119#define GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(db) \
120 (db)? pcm_config_deep_buffer : pcm_config_low_latency
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800121
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700122#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700123#define DEFAULT_VOIP_BUF_DURATION_MS 20
124#define DEFAULT_VOIP_BIT_DEPTH_BYTE sizeof(int16_t)
125#define DEFAULT_VOIP_SAMP_RATE 48000
126
127#define VOIP_IO_BUF_SIZE(SR, DURATION_MS, BIT_DEPTH) (SR)/1000 * DURATION_MS * BIT_DEPTH
128
129struct pcm_config default_pcm_config_voip_copp = {
130 .channels = 1,
131 .rate = DEFAULT_VOIP_SAMP_RATE, /* changed when the stream is opened */
132 .period_size = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
133 .period_count = 2,
134 .format = PCM_FORMAT_S16_LE,
kunleiz95b597a2017-10-23 17:07:33 +0800135 .avail_min = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
136 .stop_threshold = INT_MAX,
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700137};
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700138
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700139#define MIN_CHANNEL_COUNT 1
140#define DEFAULT_CHANNEL_COUNT 2
141#define MAX_HIFI_CHANNEL_COUNT 8
142
Aalique Grahame22e49102018-12-18 14:23:57 -0800143#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
144#define MAX_CHANNEL_COUNT 1
145#else
146#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
147#define XSTR(x) STR(x)
148#define STR(x) #x
149#endif
150
Dechen Chai22768452021-07-30 09:29:16 +0530151#ifdef LINUX_ENABLED
152static inline int64_t audio_utils_ns_from_timespec(const struct timespec *ts)
153{
154 return ts->tv_sec * 1000000000LL + ts->tv_nsec;
155}
156#endif
157
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700158static unsigned int configured_low_latency_capture_period_size =
159 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
160
Haynes Mathew George16081042017-05-31 17:16:49 -0700161#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
162#define MMAP_PERIOD_COUNT_MIN 32
163#define MMAP_PERIOD_COUNT_MAX 512
164#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
165
Aalique Grahame22e49102018-12-18 14:23:57 -0800166/* This constant enables extended precision handling.
167 * TODO The flag is off until more testing is done.
168 */
169static const bool k_enable_extended_precision = false;
Arun Mirpurie008ed22019-03-21 11:21:04 -0700170extern int AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Aalique Grahame22e49102018-12-18 14:23:57 -0800171
Eric Laurentb23d5282013-05-14 15:27:20 -0700172struct pcm_config pcm_config_deep_buffer = {
173 .channels = 2,
174 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
175 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
176 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
177 .format = PCM_FORMAT_S16_LE,
178 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
179 .stop_threshold = INT_MAX,
180 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
181};
182
183struct pcm_config pcm_config_low_latency = {
184 .channels = 2,
185 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
186 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
187 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
188 .format = PCM_FORMAT_S16_LE,
189 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
190 .stop_threshold = INT_MAX,
191 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
192};
193
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800194struct pcm_config pcm_config_haptics_audio = {
195 .channels = 1,
196 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
197 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
198 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
199 .format = PCM_FORMAT_S16_LE,
200 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
201 .stop_threshold = INT_MAX,
202 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
203};
204
205struct pcm_config pcm_config_haptics = {
206 .channels = 1,
207 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
208 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
209 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
210 .format = PCM_FORMAT_S16_LE,
211 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
212 .stop_threshold = INT_MAX,
213 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
214};
215
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700216static int af_period_multiplier = 4;
217struct pcm_config pcm_config_rt = {
218 .channels = 2,
219 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
220 .period_size = ULL_PERIOD_SIZE, //1 ms
221 .period_count = 512, //=> buffer size is 512ms
222 .format = PCM_FORMAT_S16_LE,
223 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
224 .stop_threshold = INT_MAX,
225 .silence_threshold = 0,
226 .silence_size = 0,
227 .avail_min = ULL_PERIOD_SIZE, //1 ms
228};
229
Eric Laurentb23d5282013-05-14 15:27:20 -0700230struct pcm_config pcm_config_hdmi_multi = {
231 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
232 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
233 .period_size = HDMI_MULTI_PERIOD_SIZE,
234 .period_count = HDMI_MULTI_PERIOD_COUNT,
235 .format = PCM_FORMAT_S16_LE,
236 .start_threshold = 0,
237 .stop_threshold = INT_MAX,
238 .avail_min = 0,
239};
240
Haynes Mathew George16081042017-05-31 17:16:49 -0700241struct pcm_config pcm_config_mmap_playback = {
242 .channels = 2,
243 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
244 .period_size = MMAP_PERIOD_SIZE,
245 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
246 .format = PCM_FORMAT_S16_LE,
247 .start_threshold = MMAP_PERIOD_SIZE*8,
248 .stop_threshold = INT32_MAX,
249 .silence_threshold = 0,
250 .silence_size = 0,
251 .avail_min = MMAP_PERIOD_SIZE, //1 ms
252};
253
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700254struct pcm_config pcm_config_hifi = {
255 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
256 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
257 .period_size = HIFI_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
258 .period_count = HIFI_BUFFER_OUTPUT_PERIOD_COUNT,
259 .format = PCM_FORMAT_S24_3LE,
260 .start_threshold = 0,
261 .stop_threshold = INT_MAX,
262 .avail_min = 0,
263};
264
Eric Laurentb23d5282013-05-14 15:27:20 -0700265struct pcm_config pcm_config_audio_capture = {
266 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700267 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
268 .format = PCM_FORMAT_S16_LE,
269};
270
Haynes Mathew George16081042017-05-31 17:16:49 -0700271struct pcm_config pcm_config_mmap_capture = {
272 .channels = 2,
273 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
274 .period_size = MMAP_PERIOD_SIZE,
275 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
276 .format = PCM_FORMAT_S16_LE,
277 .start_threshold = 0,
278 .stop_threshold = INT_MAX,
279 .silence_threshold = 0,
280 .silence_size = 0,
281 .avail_min = MMAP_PERIOD_SIZE, //1 ms
282};
283
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700284#define AFE_PROXY_CHANNEL_COUNT 2
285#define AFE_PROXY_SAMPLING_RATE 48000
286
287#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
288#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
289
290struct pcm_config pcm_config_afe_proxy_playback = {
291 .channels = AFE_PROXY_CHANNEL_COUNT,
292 .rate = AFE_PROXY_SAMPLING_RATE,
293 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
294 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
295 .format = PCM_FORMAT_S16_LE,
296 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
297 .stop_threshold = INT_MAX,
298 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
299};
300
301#define AFE_PROXY_RECORD_PERIOD_SIZE 768
302#define AFE_PROXY_RECORD_PERIOD_COUNT 4
303
Aalique Grahame22e49102018-12-18 14:23:57 -0800304struct pcm_config pcm_config_audio_capture_rt = {
305 .channels = 2,
306 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
307 .period_size = ULL_PERIOD_SIZE,
308 .period_count = 512,
309 .format = PCM_FORMAT_S16_LE,
310 .start_threshold = 0,
311 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
312 .silence_threshold = 0,
313 .silence_size = 0,
314 .avail_min = ULL_PERIOD_SIZE, //1 ms
315};
316
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +0530317struct pcm_config pcm_config_audio_capture_rt_48KHz = {
318 .channels = 2,
319 .rate = 48000,
320 .period_size = 48,
321 .period_count = 512,
322 .format = PCM_FORMAT_S16_LE,
323 .start_threshold = 0,
324 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
325 .silence_threshold = 0,
326 .silence_size = 0,
327 .avail_min = 48, //1 ms
328};
329struct pcm_config pcm_config_audio_capture_rt_32KHz = {
330 .channels = 2,
331 .rate = 32000,
332 .period_size = 32,
333 .period_count = 512,
334 .format = PCM_FORMAT_S16_LE,
335 .start_threshold = 0,
336 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
337 .silence_threshold = 0,
338 .silence_size = 0,
339 .avail_min = 32, //1 ms
340};
341struct pcm_config pcm_config_audio_capture_rt_24KHz = {
342 .channels = 2,
343 .rate = 24000,
344 .period_size = 24,
345 .period_count = 512,
346 .format = PCM_FORMAT_S16_LE,
347 .start_threshold = 0,
348 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
349 .silence_threshold = 0,
350 .silence_size = 0,
351 .avail_min = 24, //1 ms
352};
353struct pcm_config pcm_config_audio_capture_rt_16KHz = {
354 .channels = 2,
355 .rate = 16000,
356 .period_size = 16,
357 .period_count = 512,
358 .format = PCM_FORMAT_S16_LE,
359 .start_threshold = 0,
360 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
361 .silence_threshold = 0,
362 .silence_size = 0,
363 .avail_min = 16, //1 ms
364};
365struct pcm_config pcm_config_audio_capture_rt_8KHz = {
366 .channels = 2,
367 .rate = 8000,
368 .period_size = 8,
369 .period_count = 512,
370 .format = PCM_FORMAT_S16_LE,
371 .start_threshold = 0,
372 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
373 .silence_threshold = 0,
374 .silence_size = 0,
375 .avail_min = 8, //1 ms
376};
377
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700378struct pcm_config pcm_config_afe_proxy_record = {
379 .channels = AFE_PROXY_CHANNEL_COUNT,
380 .rate = AFE_PROXY_SAMPLING_RATE,
381 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
382 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
383 .format = PCM_FORMAT_S16_LE,
384 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
385 .stop_threshold = INT_MAX,
386 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
387};
388
Ashish Jainf1eaa582016-05-23 20:54:24 +0530389#define AUDIO_MAX_PCM_FORMATS 7
390
391const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
392 [AUDIO_FORMAT_DEFAULT] = 0,
393 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
394 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
395 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
396 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
397 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
398 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
399};
400
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800401const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700402 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
403 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800404 [USECASE_AUDIO_PLAYBACK_WITH_HAPTICS] = "audio-with-haptics-playback",
Meng Wang51d8c2a2020-04-27 15:23:21 +0800405 [USECASE_AUDIO_PLAYBACK_HAPTICS] = "haptics-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700406 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
407 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700408 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700409 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700410 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
411 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
412 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
413 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
414 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
415 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
416 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
417 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
Haynes Mathew George16081042017-05-31 17:16:49 -0700418 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
419 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700420 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Aalique Grahame22e49102018-12-18 14:23:57 -0800421 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
vivek mehta0ea887a2015-08-26 14:01:20 -0700422
Eric Laurentb23d5282013-05-14 15:27:20 -0700423 [USECASE_AUDIO_RECORD] = "audio-record",
Krishna Kishor Jha0f4d8482022-02-18 10:56:05 +0530424 [USECASE_AUDIO_RECORD2] = "audio-record2",
425 [USECASE_AUDIO_RECORD3] = "audio-record3",
Mingming Yine62d7842013-10-25 16:26:03 -0700426 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530427 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
428 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
429 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Dhananjay Kumar376e38b2017-09-28 22:26:23 +0530430 [USECASE_AUDIO_RECORD_COMPRESS5] = "audio-record-compress5",
431 [USECASE_AUDIO_RECORD_COMPRESS6] = "audio-record-compress6",
Eric Laurentb23d5282013-05-14 15:27:20 -0700432 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700433 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700434 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700435 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700436
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800437 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800438 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Derek Chenf7092792017-05-23 12:23:53 -0400439 [USECASE_AUDIO_HFP_SCO_DOWNLINK] = "hfp-sco-downlink",
440 [USECASE_AUDIO_HFP_SCO_WB_DOWNLINK] = "hfp-sco-wb-downlink",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700441
Derek Chenf7092792017-05-23 12:23:53 -0400442 [USECASE_VOICE_CALL] = "voice-call",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700443 [USECASE_VOICE2_CALL] = "voice2-call",
444 [USECASE_VOLTE_CALL] = "volte-call",
445 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800446 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800447 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
448 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800449 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700450 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
451 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
452 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800453 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
454 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
455 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
456
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700457 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
458 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700459 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
460 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700461
462 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
463 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Zhou Song62ea0282020-03-22 19:53:01 +0800464 [USECASE_AUDIO_RECORD_AFE_PROXY2] = "afe-proxy-record2",
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +0530465 [USECASE_AUDIO_PLAYBACK_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700466
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530467 /* Transcode loopback cases */
Surendar Karka93cd25a2018-08-28 14:21:37 +0530468 [USECASE_AUDIO_TRANSCODE_LOOPBACK_RX] = "audio-transcode-loopback-rx",
469 [USECASE_AUDIO_TRANSCODE_LOOPBACK_TX] = "audio-transcode-loopback-tx",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700470
471 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
472 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Revathi Uddarajud9f23d92020-07-27 10:55:06 +0530473 [USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY] = "audio-record-voip-low-latency",
Varun Balaraje49253e2017-07-06 19:48:56 +0530474 /* For Interactive Audio Streams */
475 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
476 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
477 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
478 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
479 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
480 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
481 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
482 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700483
Aniket Kumar Lata7fd86e12018-02-20 19:26:10 -0800484 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture",
485
Derek Chenf6318be2017-06-12 17:16:24 -0400486 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
487
488 [USECASE_AUDIO_PLAYBACK_MEDIA] = "media-playback",
489 [USECASE_AUDIO_PLAYBACK_SYS_NOTIFICATION] = "sys-notification-playback",
490 [USECASE_AUDIO_PLAYBACK_NAV_GUIDANCE] = "nav-guidance-playback",
491 [USECASE_AUDIO_PLAYBACK_PHONE] = "phone-playback",
Derek Chen1bcdc6b2020-02-06 22:44:53 -0800492 [USECASE_AUDIO_PLAYBACK_FRONT_PASSENGER] = "front-passenger-playback",
Derek Chendf05eea2019-08-01 13:57:49 -0700493 [USECASE_AUDIO_PLAYBACK_REAR_SEAT] = "rear-seat-playback",
Rahul Sharma99770982019-03-06 17:05:26 +0530494 [USECASE_AUDIO_FM_TUNER_EXT] = "fm-tuner-ext",
Derek Chena30a5f42019-12-03 11:17:09 -0500495 [USECASE_ICC_CALL] = "icc-call",
Huicheng Liu1404ba12020-09-11 01:03:25 -0400496
497 [USECASE_AUDIO_RECORD_BUS] = "audio-record",
498 [USECASE_AUDIO_RECORD_BUS_FRONT_PASSENGER] = "front-passenger-record",
499 [USECASE_AUDIO_RECORD_BUS_REAR_SEAT] = "rear-seat-record",
Fei Tongaffdf732020-02-20 20:39:05 +0800500 [USECASE_AUDIO_PLAYBACK_SYNTHESIZER] = "synth-loopback",
Susan Wange3959562021-03-11 11:50:26 -0500501 [USECASE_AUDIO_RECORD_ECHO_REF_EXT] = "echo-reference-external",
Eric Laurentb23d5282013-05-14 15:27:20 -0700502};
503
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700504static const audio_usecase_t offload_usecases[] = {
505 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700506 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
507 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
508 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
509 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
510 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
511 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
512 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
513 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700514};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800515
Varun Balaraje49253e2017-07-06 19:48:56 +0530516static const audio_usecase_t interactive_usecases[] = {
517 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
518 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
519 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
520 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
521 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
522 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
523 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
524 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
525};
526
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800527#define STRING_TO_ENUM(string) { #string, string }
528
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800529struct string_to_enum {
530 const char *name;
531 uint32_t value;
532};
533
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700534static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800535 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800536 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
537 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
538 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700539 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800540 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
541 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800542 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700543 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
544 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
545 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
546 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
547 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
548 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
549 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
550 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
551 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
552 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
553 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800554};
555
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700556static const struct string_to_enum formats_name_to_enum_table[] = {
557 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
558 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
559 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700560 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
561 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
562 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700563 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800564 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
565 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700566 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800567};
568
569//list of all supported sample rates by HDMI specification.
570static const int out_hdmi_sample_rates[] = {
571 32000, 44100, 48000, 88200, 96000, 176400, 192000,
572};
573
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700574static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800575 STRING_TO_ENUM(32000),
576 STRING_TO_ENUM(44100),
577 STRING_TO_ENUM(48000),
578 STRING_TO_ENUM(88200),
579 STRING_TO_ENUM(96000),
580 STRING_TO_ENUM(176400),
581 STRING_TO_ENUM(192000),
Mingshu pange8aedf12019-10-25 15:38:27 +0800582 STRING_TO_ENUM(352800),
583 STRING_TO_ENUM(384000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700584};
585
Carter Hsu2e429db2019-05-14 18:50:52 +0800586struct in_effect_list {
587 struct listnode list;
588 effect_handle_t handle;
589};
590
Krishna Kishor Jha0f4d8482022-02-18 10:56:05 +0530591static const audio_usecase_t record_usecases[] = {
592 USECASE_AUDIO_RECORD,
593 USECASE_AUDIO_RECORD2,
594 USECASE_AUDIO_RECORD3,
595};
596
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700597static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700598static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700599static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700600//cache last MBDRC cal step level
601static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700602
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530603static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Arun Mirpuri5d170872019-03-26 13:21:31 -0700604static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800605static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530606static int out_set_pcm_volume(struct audio_stream_out *stream, float left, float right);
Krishna Kishor Jha10ad39f2022-02-21 17:02:47 +0530607#ifdef SOFT_VOLUME
608static int out_set_soft_volume_params(struct audio_stream_out *stream);
609#endif
Derek Chen6f293672019-04-01 01:40:24 -0700610static void adev_snd_mon_cb(void *cookie, struct str_parms *parms);
611static void in_snd_mon_cb(void * stream, struct str_parms * parms);
612static void out_snd_mon_cb(void * stream, struct str_parms * parms);
613
Zhou Song331c8e52019-08-26 14:16:12 +0800614static int configure_btsco_sample_rate(snd_device_t snd_device);
615
Vatsal Buchac09ae062018-11-14 13:25:08 +0530616#ifdef AUDIO_FEATURE_ENABLED_GCOV
617extern void __gcov_flush();
618static void enable_gcov()
619{
620 __gcov_flush();
621}
622#else
623static void enable_gcov()
624{
625}
626#endif
627
justinweng20fb6d82019-02-21 18:49:00 -0700628static int in_set_microphone_direction(const struct audio_stream_in *stream,
629 audio_microphone_direction_t dir);
630static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom);
631
Krishna Kishor Jha0f4d8482022-02-18 10:56:05 +0530632static bool is_pcm_record_usecase(audio_usecase_t uc_id)
633{
634 unsigned int record_uc_index;
635 unsigned int num_usecase = sizeof(record_usecases)/sizeof(record_usecases[0]);
636
637 for (record_uc_index = 0; record_uc_index < num_usecase; record_uc_index++) {
638 if (uc_id == record_usecases[record_uc_index])
639 return true;
640 }
641 return false;
642}
643
644static audio_usecase_t get_record_usecase(struct audio_device *adev)
645{
646 audio_usecase_t ret_uc = USECASE_INVALID;
647 unsigned int record_uc_index;
648 unsigned int num_usecase = sizeof(record_usecases)/sizeof(record_usecases[0]);
649
650 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
651 for (record_uc_index = 0; record_uc_index < num_usecase; record_uc_index++) {
652 if (!(adev->pcm_record_uc_state & (0x1 << record_uc_index))) {
653 adev->pcm_record_uc_state |= 0x1 << record_uc_index;
654 ret_uc = record_usecases[record_uc_index];
655 break;
656 }
657 }
658
659 ALOGV("%s: pcm record usecase is %d", __func__, ret_uc);
660 return ret_uc;
661}
662
663static void free_record_usecase(struct audio_device *adev,
664 audio_usecase_t uc_id)
665{
666 unsigned int record_uc_index;
667 unsigned int num_usecase = sizeof(record_usecases)/sizeof(record_usecases[0]);
668
669 for (record_uc_index = 0; record_uc_index < num_usecase; record_uc_index++) {
670 if (record_usecases[record_uc_index] == uc_id) {
671 adev->pcm_record_uc_state &= ~(0x1 << record_uc_index);
672 break;
673 }
674 }
675 ALOGV("%s: free pcm record usecase %d", __func__, uc_id);
676}
677
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700678static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
679 int flags __unused)
680{
681 int dir = 0;
682 switch (uc_id) {
683 case USECASE_AUDIO_RECORD_LOW_LATENCY:
Revathi Uddarajud9f23d92020-07-27 10:55:06 +0530684 case USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY:
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700685 dir = 1;
686 case USECASE_AUDIO_PLAYBACK_ULL:
687 break;
688 default:
689 return false;
690 }
691
692 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
693 PCM_PLAYBACK : PCM_CAPTURE);
694 if (adev->adm_is_noirq_avail)
695 return adev->adm_is_noirq_avail(adev->adm_data,
696 adev->snd_card, dev_id, dir);
697 return false;
698}
699
700static void register_out_stream(struct stream_out *out)
701{
702 struct audio_device *adev = out->dev;
703 if (is_offload_usecase(out->usecase) ||
704 !adev->adm_register_output_stream)
705 return;
706
707 // register stream first for backward compatibility
708 adev->adm_register_output_stream(adev->adm_data,
709 out->handle,
710 out->flags);
711
712 if (!adev->adm_set_config)
713 return;
714
Kogara Naveen Kumar6db5fb02022-05-07 00:22:50 +0530715 if (out->realtime || (out->flags & AUDIO_OUTPUT_FLAG_SYS_NOTIFICATION))
716 adev->adm_set_config(adev->adm_data,
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700717 out->handle,
718 out->pcm, &out->config);
719}
720
721static void register_in_stream(struct stream_in *in)
722{
723 struct audio_device *adev = in->dev;
724 if (!adev->adm_register_input_stream)
725 return;
726
727 adev->adm_register_input_stream(adev->adm_data,
728 in->capture_handle,
729 in->flags);
730
731 if (!adev->adm_set_config)
732 return;
733
734 if (in->realtime)
735 adev->adm_set_config(adev->adm_data,
736 in->capture_handle,
737 in->pcm,
738 &in->config);
739}
740
741static void request_out_focus(struct stream_out *out, long ns)
742{
743 struct audio_device *adev = out->dev;
744
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700745 if (adev->adm_request_focus_v2)
746 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
747 else if (adev->adm_request_focus)
748 adev->adm_request_focus(adev->adm_data, out->handle);
749}
750
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700751static int request_in_focus(struct stream_in *in, long ns)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700752{
753 struct audio_device *adev = in->dev;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700754 int ret = 0;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700755
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700756 if (adev->adm_request_focus_v2_1)
757 ret = adev->adm_request_focus_v2_1(adev->adm_data, in->capture_handle, ns);
758 else if (adev->adm_request_focus_v2)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700759 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
760 else if (adev->adm_request_focus)
761 adev->adm_request_focus(adev->adm_data, in->capture_handle);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700762
763 return ret;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700764}
765
766static void release_out_focus(struct stream_out *out)
767{
768 struct audio_device *adev = out->dev;
769
770 if (adev->adm_abandon_focus)
771 adev->adm_abandon_focus(adev->adm_data, out->handle);
772}
773
774static void release_in_focus(struct stream_in *in)
775{
776 struct audio_device *adev = in->dev;
777 if (adev->adm_abandon_focus)
778 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
779}
780
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530781static int parse_snd_card_status(struct str_parms *parms, int *card,
782 card_status_t *status)
783{
784 char value[32]={0};
785 char state[32]={0};
786
787 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
788 if (ret < 0)
789 return -1;
790
791 // sscanf should be okay as value is of max length 32.
792 // same as sizeof state.
793 if (sscanf(value, "%d,%s", card, state) < 2)
794 return -1;
795
796 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
797 CARD_STATUS_OFFLINE;
798 return 0;
799}
800
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700801static inline void adjust_frames_for_device_delay(struct stream_out *out,
802 uint32_t *dsp_frames) {
803 // Adjustment accounts for A2dp encoder latency with offload usecases
804 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -0800805 if (is_a2dp_out_device_type(&out->device_list)) {
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700806 unsigned long offset =
807 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
808 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
809 }
810}
811
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700812static inline bool free_entry(void *key __unused,
813 void *value, void *context __unused)
814{
815 free(value);
816 return true;
817}
818
819static inline void free_map(Hashmap *map)
820{
821 if (map) {
822 hashmapForEach(map, free_entry, (void *) NULL);
823 hashmapFree(map);
824 }
825}
826
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800827static inline void patch_map_remove_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700828 audio_patch_handle_t patch_handle)
829{
830 if (patch_handle == AUDIO_PATCH_HANDLE_NONE)
831 return;
832
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700833 struct audio_patch_info *p_info =
834 hashmapGet(adev->patch_map, (void *) (intptr_t) patch_handle);
835 if (p_info) {
836 ALOGV("%s: Remove patch %d", __func__, patch_handle);
837 hashmapRemove(adev->patch_map, (void *) (intptr_t) patch_handle);
838 free(p_info->patch);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700839 free(p_info);
840 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700841}
842
843static inline int io_streams_map_insert(struct audio_device *adev,
844 struct audio_stream *stream,
845 audio_io_handle_t handle,
846 audio_patch_handle_t patch_handle)
847{
848 struct audio_stream_info *s_info =
849 (struct audio_stream_info *) calloc(1, sizeof(struct audio_stream_info));
850
851 if (s_info == NULL) {
852 ALOGE("%s: Could not allocate stream info", __func__);
853 return -ENOMEM;
854 }
855 s_info->stream = stream;
856 s_info->patch_handle = patch_handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700857
858 pthread_mutex_lock(&adev->lock);
859 struct audio_stream_info *stream_info =
860 hashmapPut(adev->io_streams_map, (void *) (intptr_t) handle, (void *) s_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700861 if (stream_info != NULL)
862 free(stream_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800863 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Latad13758f2020-08-06 15:11:36 -0700864 ALOGV("%s: Added stream in io_streams_map with handle %d", __func__, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700865 return 0;
866}
867
868static inline void io_streams_map_remove(struct audio_device *adev,
869 audio_io_handle_t handle)
870{
871 pthread_mutex_lock(&adev->lock);
872 struct audio_stream_info *s_info =
873 hashmapRemove(adev->io_streams_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700874 if (s_info == NULL)
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800875 goto done;
Aniket Kumar Latad13758f2020-08-06 15:11:36 -0700876 ALOGV("%s: Removed stream with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800877 patch_map_remove_l(adev, s_info->patch_handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700878 free(s_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800879done:
880 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700881 return;
882}
883
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800884static struct audio_patch_info* fetch_patch_info_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700885 audio_patch_handle_t handle)
886{
887 struct audio_patch_info *p_info = NULL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700888 p_info = (struct audio_patch_info *)
889 hashmapGet(adev->patch_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700890 return p_info;
891}
892
vivek mehtaa76401a2015-04-24 14:12:15 -0700893__attribute__ ((visibility ("default")))
894bool audio_hw_send_gain_dep_calibration(int level) {
895 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700896 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700897
898 pthread_mutex_lock(&adev_init_lock);
899
900 if (adev != NULL && adev->platform != NULL) {
901 pthread_mutex_lock(&adev->lock);
902 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700903
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530904 // cache level info for any of the use case which
905 // was not started.
906 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700907
vivek mehtaa76401a2015-04-24 14:12:15 -0700908 pthread_mutex_unlock(&adev->lock);
909 } else {
910 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
911 }
912
913 pthread_mutex_unlock(&adev_init_lock);
914
915 return ret_val;
916}
917
Ashish Jain5106d362016-05-11 19:23:33 +0530918static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
919{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800920 bool gapless_enabled = false;
921 const char *mixer_ctl_name = "Compress Gapless Playback";
922 struct mixer_ctl *ctl;
923
924 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700925 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530926
927 /*Disable gapless if its AV playback*/
928 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800929
930 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
931 if (!ctl) {
932 ALOGE("%s: Could not get ctl for mixer cmd - %s",
933 __func__, mixer_ctl_name);
934 return -EINVAL;
935 }
936
937 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
938 ALOGE("%s: Could not set gapless mode %d",
939 __func__, gapless_enabled);
940 return -EINVAL;
941 }
942 return 0;
943}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700944
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700945__attribute__ ((visibility ("default")))
946int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
947 int table_size) {
948 int ret_val = 0;
949 ALOGV("%s: enter ... ", __func__);
950
951 pthread_mutex_lock(&adev_init_lock);
952 if (adev == NULL) {
953 ALOGW("%s: adev is NULL .... ", __func__);
954 goto done;
955 }
956
957 pthread_mutex_lock(&adev->lock);
958 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
959 pthread_mutex_unlock(&adev->lock);
960done:
961 pthread_mutex_unlock(&adev_init_lock);
962 ALOGV("%s: exit ... ", __func__);
963 return ret_val;
964}
965
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800966bool audio_hw_send_qdsp_parameter(int stream_type, float vol, bool active)
Aalique Grahame22e49102018-12-18 14:23:57 -0800967{
968 bool ret = false;
969 ALOGV("%s: enter ...", __func__);
970
971 pthread_mutex_lock(&adev_init_lock);
972
973 if (adev != NULL && adev->platform != NULL) {
974 pthread_mutex_lock(&adev->lock);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800975 ret = audio_extn_qdsp_set_state(adev, stream_type, vol, active);
Aalique Grahame22e49102018-12-18 14:23:57 -0800976 pthread_mutex_unlock(&adev->lock);
977 }
978
979 pthread_mutex_unlock(&adev_init_lock);
980
981 ALOGV("%s: exit with ret %d", __func__, ret);
982 return ret;
983}
Aalique Grahame22e49102018-12-18 14:23:57 -0800984
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700985static bool is_supported_format(audio_format_t format)
986{
Eric Laurent86e17132013-09-12 17:49:30 -0700987 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530988 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530989 format == AUDIO_FORMAT_AAC_LC ||
990 format == AUDIO_FORMAT_AAC_HE_V1 ||
991 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530992 format == AUDIO_FORMAT_AAC_ADTS_LC ||
993 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
994 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530995 format == AUDIO_FORMAT_AAC_LATM_LC ||
996 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
997 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530998 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
999 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +05301000 format == AUDIO_FORMAT_PCM_FLOAT ||
1001 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -07001002 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301003 format == AUDIO_FORMAT_AC3 ||
1004 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -07001005 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301006 format == AUDIO_FORMAT_DTS ||
1007 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001008 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301009 format == AUDIO_FORMAT_ALAC ||
1010 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301011 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301012 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001013 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05301014 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07001015 format == AUDIO_FORMAT_APTX ||
1016 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08001017 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001018
1019 return false;
1020}
1021
Kunlei Zhang67cc7072020-12-18 17:16:49 +08001022static bool is_supported_conc_usecase_for_power_mode_call(struct audio_device *adev)
1023{
1024 struct listnode *node;
1025 struct audio_usecase *usecase;
1026
1027 list_for_each(node, &adev->usecase_list) {
1028 usecase = node_to_item(node, struct audio_usecase, list);
1029 if (usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1030 ALOGD("%s: FM usecase is active, not setting power mode", __func__);
1031 return false;
1032 }
1033 }
1034
1035 return true;
1036}
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001037static inline bool is_mmap_usecase(audio_usecase_t uc_id)
1038{
1039 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
Zhou Song62ea0282020-03-22 19:53:01 +08001040 (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY2) ||
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001041 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
1042}
1043
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07001044static inline bool is_valid_volume(float left, float right)
1045{
1046 return ((left >= 0.0f && right >= 0.0f) ? true : false);
1047}
1048
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301049static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301050{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301051 ALOGV("%s", __func__);
1052 audio_route_apply_and_update_path(adev->audio_route,
1053 "asrc-mode");
1054 adev->asrc_mode_enabled = true;
1055}
1056
1057static void disable_asrc_mode(struct audio_device *adev)
1058{
1059 ALOGV("%s", __func__);
1060 audio_route_reset_and_update_path(adev->audio_route,
1061 "asrc-mode");
1062 adev->asrc_mode_enabled = false;
1063}
1064
Saurav Kumarc1411662020-10-14 10:50:45 +05301065static void check_and_configure_headphone(struct audio_device *adev,
1066 struct audio_usecase *uc_info,
1067 snd_device_t snd_device)
1068{
1069 struct listnode *node;
1070 struct audio_usecase *usecase;
1071 int new_backend_idx, usecase_backend_idx;
1072 bool spkr_hph_single_be_native_concurrency;
1073
1074 new_backend_idx = platform_get_backend_index(snd_device);
1075 spkr_hph_single_be_native_concurrency = platform_get_spkr_hph_single_be_native_concurrency_flag();
Zhou Songd4b18c42021-01-14 15:15:29 +08001076 if ((spkr_hph_single_be_native_concurrency && (new_backend_idx == DEFAULT_CODEC_BACKEND)) ||
1077 uc_info->id == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
Saurav Kumarc1411662020-10-14 10:50:45 +05301078 list_for_each(node, &adev->usecase_list) {
1079 usecase = node_to_item(node, struct audio_usecase, list);
1080 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
1081 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
1082 if (((usecase_backend_idx == HEADPHONE_BACKEND) ||
1083 (usecase_backend_idx == HEADPHONE_44_1_BACKEND)) &&
1084 ((usecase->stream.out->sample_rate % OUTPUT_SAMPLING_RATE_44100) == 0)) {
1085 disable_audio_route(adev, usecase);
1086 disable_snd_device(adev, usecase->out_snd_device);
1087 usecase->stream.out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Saurav Kumar70902382020-10-28 11:16:04 +05301088 platform_check_and_set_codec_backend_cfg(adev, usecase,
1089 usecase->out_snd_device);
Saurav Kumarc1411662020-10-14 10:50:45 +05301090 enable_snd_device(adev, usecase->out_snd_device);
Zhou Songd4b18c42021-01-14 15:15:29 +08001091 enable_audio_route(adev, usecase);
Saurav Kumarc1411662020-10-14 10:50:45 +05301092 }
1093 }
Revathi Uddaraju2c0eac02021-07-27 02:06:42 -07001094 else if ((usecase->type != PCM_CAPTURE) && (usecase == uc_info)) {
1095 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
1096 if (((usecase_backend_idx == HEADPHONE_BACKEND) ||
1097 (usecase_backend_idx == HEADPHONE_44_1_BACKEND)) &&
1098 ((usecase->stream.out->sample_rate % OUTPUT_SAMPLING_RATE_44100) == 0)) {
1099 usecase->stream.out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1100 platform_check_and_set_codec_backend_cfg(adev, usecase,
1101 usecase->out_snd_device);
1102 }
1103 }
Saurav Kumarc1411662020-10-14 10:50:45 +05301104 }
1105 }
1106}
1107
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301108/*
1109 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
1110 * 44.1 or Native DSD backends are enabled for any of current use case.
1111 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
1112 * - Disable current mix path use case(Headphone backend) and re-enable it with
1113 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
1114 * e.g. Naitve DSD or Headphone 44.1 -> + 48
1115 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301116static void check_and_set_asrc_mode(struct audio_device *adev,
1117 struct audio_usecase *uc_info,
1118 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301119{
1120 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301121 int i, num_new_devices = 0;
1122 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
1123 /*
1124 *Split snd device for new combo use case
1125 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
1126 */
1127 if (platform_split_snd_device(adev->platform,
1128 snd_device,
1129 &num_new_devices,
1130 split_new_snd_devices) == 0) {
1131 for (i = 0; i < num_new_devices; i++)
1132 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
1133 } else {
1134 int new_backend_idx = platform_get_backend_index(snd_device);
1135 if (((new_backend_idx == HEADPHONE_BACKEND) ||
1136 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
1137 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
1138 !adev->asrc_mode_enabled) {
1139 struct listnode *node = NULL;
1140 struct audio_usecase *uc = NULL;
1141 struct stream_out *curr_out = NULL;
1142 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
1143 int i, num_devices, ret = 0;
1144 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301145
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301146 list_for_each(node, &adev->usecase_list) {
1147 uc = node_to_item(node, struct audio_usecase, list);
1148 curr_out = (struct stream_out*) uc->stream.out;
1149 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
1150 /*
1151 *Split snd device for existing combo use case
1152 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
1153 */
1154 ret = platform_split_snd_device(adev->platform,
1155 uc->out_snd_device,
1156 &num_devices,
1157 split_snd_devices);
1158 if (ret < 0 || num_devices == 0) {
1159 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
1160 split_snd_devices[0] = uc->out_snd_device;
1161 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -08001162 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301163 for (i = 0; i < num_devices; i++) {
1164 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
1165 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
1166 if((new_backend_idx == HEADPHONE_BACKEND) &&
1167 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
1168 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07001169 ALOGV("%s:DSD or native stream detected enabling asrcmode in hardware",
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301170 __func__);
1171 enable_asrc_mode(adev);
1172 break;
1173 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
1174 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
1175 (usecase_backend_idx == HEADPHONE_BACKEND)) {
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07001176 ALOGV("%s: 48K stream detected, disabling and enabling it \
1177 with asrcmode in hardware", __func__);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301178 disable_audio_route(adev, uc);
1179 disable_snd_device(adev, uc->out_snd_device);
1180 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
1181 if (new_backend_idx == DSD_NATIVE_BACKEND)
1182 audio_route_apply_and_update_path(adev->audio_route,
1183 "hph-true-highquality-mode");
1184 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
1185 (curr_out->bit_width >= 24))
1186 audio_route_apply_and_update_path(adev->audio_route,
1187 "hph-highquality-mode");
1188 enable_asrc_mode(adev);
1189 enable_snd_device(adev, uc->out_snd_device);
1190 enable_audio_route(adev, uc);
1191 break;
1192 }
1193 }
1194 // reset split devices count
1195 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -08001196 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301197 if (adev->asrc_mode_enabled)
1198 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301199 }
1200 }
1201 }
1202}
1203
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001204static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
1205 struct audio_effect_config effect_config,
1206 unsigned int param_value)
1207{
1208 char mixer_ctl_name[] = "Audio Effect";
1209 struct mixer_ctl *ctl;
1210 long set_values[6];
Eric Laurent637e2d42018-11-15 12:24:31 -08001211 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001212
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001213 if (in == NULL) {
1214 ALOGE("%s: active input stream is NULL", __func__);
1215 return -EINVAL;
1216 }
1217
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001218 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1219 if (!ctl) {
1220 ALOGE("%s: Could not get mixer ctl - %s",
1221 __func__, mixer_ctl_name);
1222 return -EINVAL;
1223 }
1224
1225 set_values[0] = 1; //0:Rx 1:Tx
1226 set_values[1] = in->app_type_cfg.app_type;
1227 set_values[2] = (long)effect_config.module_id;
1228 set_values[3] = (long)effect_config.instance_id;
1229 set_values[4] = (long)effect_config.param_id;
1230 set_values[5] = param_value;
1231
1232 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
1233
1234 return 0;
1235
1236}
1237
1238static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
1239 int effect_type, unsigned int *param_value)
1240{
1241 int ret = 0;
1242 struct audio_effect_config other_effect_config;
1243 struct audio_usecase *usecase = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08001244 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001245
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001246 if (in == NULL) {
1247 ALOGE("%s: active input stream is NULL", __func__);
1248 return -EINVAL;
1249 }
1250
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001251 usecase = get_usecase_from_list(adev, in->usecase);
1252 if (!usecase)
1253 return -EINVAL;
1254
1255 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
1256 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
1257 if (ret < 0) {
1258 ALOGE("%s Failed to get effect params %d", __func__, ret);
1259 return ret;
1260 }
1261
1262 if (module_id == other_effect_config.module_id) {
1263 //Same module id for AEC/NS. Values need to be combined
1264 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
1265 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
1266 *param_value |= other_effect_config.param_value;
1267 }
1268 }
1269
1270 return ret;
1271}
1272
1273static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
Gangadhar Sb0210342019-02-22 17:39:41 +05301274{
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001275 struct audio_effect_config effect_config;
1276 struct audio_usecase *usecase = NULL;
1277 int ret = 0;
1278 unsigned int param_value = 0;
Eric Laurent637e2d42018-11-15 12:24:31 -08001279 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001280
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001281 if(!voice_extn_is_dynamic_ecns_enabled())
1282 return ENOSYS;
1283
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001284 if (!in) {
1285 ALOGE("%s: Invalid input stream", __func__);
1286 return -EINVAL;
1287 }
1288
1289 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
1290
1291 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +08001292 if (usecase == NULL) {
1293 ALOGE("%s: Could not find the usecase (%d) in the list",
1294 __func__, in->usecase);
1295 return -EINVAL;
1296 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001297
1298 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
1299 if (ret < 0) {
1300 ALOGE("%s Failed to get module id %d", __func__, ret);
1301 return ret;
1302 }
1303 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
1304 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
1305
1306 if(enable)
1307 param_value = effect_config.param_value;
1308
1309 /*Special handling for AEC & NS effects Param values need to be
1310 updated if module ids are same*/
1311
1312 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
1313 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
1314 if (ret < 0)
1315 return ret;
1316 }
1317
1318 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
1319
1320 return ret;
1321}
1322
1323static void check_and_enable_effect(struct audio_device *adev)
1324{
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001325 if(!voice_extn_is_dynamic_ecns_enabled())
1326 return;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001327
Eric Laurent637e2d42018-11-15 12:24:31 -08001328 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001329
Eric Laurent637e2d42018-11-15 12:24:31 -08001330 if (in != NULL && !in->standby) {
1331 if (in->enable_aec)
1332 enable_disable_effect(adev, EFFECT_AEC, true);
1333
1334 if (in->enable_ns &&
1335 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1336 enable_disable_effect(adev, EFFECT_NS, true);
1337 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001338 }
1339}
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001340
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001341int pcm_ioctl(struct pcm *pcm, int request, ...)
1342{
1343 va_list ap;
1344 void * arg;
1345 int pcm_fd = *(int*)pcm;
1346
1347 va_start(ap, request);
1348 arg = va_arg(ap, void *);
1349 va_end(ap);
1350
1351 return ioctl(pcm_fd, request, arg);
1352}
1353
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001354int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001355 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001356{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001357 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001358 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +05301359 struct stream_out *out = NULL;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301360 struct stream_in *in = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001361 struct listnode out_devices;
Soumya Managoli6993b762018-06-28 16:04:57 +05301362 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001363
1364 if (usecase == NULL)
1365 return -EINVAL;
1366
1367 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
1368
Carter Hsu2e429db2019-05-14 18:50:52 +08001369 if (usecase->type == PCM_CAPTURE) {
1370 struct stream_in *in = usecase->stream.in;
1371 struct audio_usecase *uinfo;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001372 snd_device = usecase->in_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001373
1374 if (in) {
1375 if (in->enable_aec || in->enable_ec_port) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001376 list_init(&out_devices);
1377 update_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "", true);
Carter Hsu2e429db2019-05-14 18:50:52 +08001378 struct listnode *node;
1379 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1380 USECASE_AUDIO_PLAYBACK_VOIP);
1381 if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001382 assign_devices(&out_devices,
1383 &voip_usecase->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001384 } else if (adev->primary_output &&
1385 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001386 assign_devices(&out_devices,
1387 &adev->primary_output->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001388 } else {
1389 list_for_each(node, &adev->usecase_list) {
1390 uinfo = node_to_item(node, struct audio_usecase, list);
1391 if (uinfo->type != PCM_CAPTURE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001392 assign_devices(&out_devices,
1393 &uinfo->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001394 break;
1395 }
1396 }
1397 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001398
1399 platform_set_echo_reference(adev, true, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001400 in->ec_opened = true;
1401 }
1402 }
Guodong Huf5e614d2019-06-24 18:42:03 +08001403 } else if ((usecase->type == TRANSCODE_LOOPBACK_TX) || ((usecase->type == PCM_HFP_CALL) &&
1404 ((usecase->id == USECASE_AUDIO_HFP_SCO) || (usecase->id == USECASE_AUDIO_HFP_SCO_WB)) &&
1405 (usecase->in_snd_device == SND_DEVICE_IN_VOICE_SPEAKER_MIC_HFP_MMSECNS))) {
Carter Hsu2e429db2019-05-14 18:50:52 +08001406 snd_device = usecase->in_snd_device;
1407 } else {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001408 snd_device = usecase->out_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001409 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001410
Kunlei Zhanga3c4cb02021-03-05 16:03:54 +08001411 if (usecase->type == PCM_CAPTURE) {
1412 if (platform_get_fluence_nn_state(adev->platform) == 0) {
1413 platform_set_fluence_nn_state(adev->platform, true);
1414 ALOGD("%s: set fluence nn capture state", __func__);
1415 }
1416 }
1417
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001418#ifdef DS1_DOLBY_DAP_ENABLED
1419 audio_extn_dolby_set_dmid(adev);
1420 audio_extn_dolby_set_endpoint(adev);
1421#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001422 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001423 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301424 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001425 audio_extn_utils_send_app_type_cfg(adev, usecase);
Jasmine Cha4dcc1092019-03-04 18:12:47 +08001426 if (audio_extn_is_maxx_audio_enabled())
1427 audio_extn_ma_set_device(usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301428 audio_extn_utils_send_audio_calibration(adev, usecase);
Zhou Songbaddf9f2020-11-20 13:57:39 +08001429 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1430 out = usecase->stream.out;
1431 if (out && out->compr)
Manish Dewangan58229382017-02-02 15:48:41 +05301432 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1433 }
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301434
1435 if (usecase->type == PCM_CAPTURE) {
Kunlei Zhanga3c4cb02021-03-05 16:03:54 +08001436 if (platform_get_fluence_nn_state(adev->platform) == 1 &&
1437 adev->fluence_nn_usecase_id == USECASE_INVALID ) {
1438 adev->fluence_nn_usecase_id = usecase->id;
1439 ALOGD("%s: assign fluence nn usecase %d", __func__, usecase->id);
1440 }
1441 }
1442
1443 if (usecase->type == PCM_CAPTURE) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301444 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001445 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301446 ALOGD("%s: set custom mtmx params v1", __func__);
1447 audio_extn_set_custom_mtmx_params_v1(adev, usecase, true);
1448 }
1449 } else {
1450 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
1451 }
Manish Dewangan58229382017-02-02 15:48:41 +05301452
Andy Hung756ecc12018-10-19 17:47:12 -07001453 // we shouldn't truncate mixer_path
1454 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1455 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1456 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001457 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001458 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301459 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1460 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1461 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1462 if (parms) {
1463 audio_extn_fm_set_parameters(adev, parms);
1464 str_parms_destroy(parms);
1465 }
1466 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001467 ALOGV("%s: exit", __func__);
1468 return 0;
1469}
1470
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001471int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001472 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001473{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001474 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001475 char mixer_path[MIXER_PATH_MAX_LENGTH];
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301476 struct stream_in *in = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001477
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301478 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001479 return -EINVAL;
1480
1481 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301482 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001483 snd_device = usecase->in_snd_device;
1484 else
1485 snd_device = usecase->out_snd_device;
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001486
1487 /* disable island and power mode on supported device for voice call */
1488 if (usecase->type == VOICE_CALL) {
1489 if (usecase->in_snd_device != SND_DEVICE_NONE) {
1490 if (platform_get_island_cfg_on_device(adev->platform, usecase->in_snd_device) &&
1491 platform_get_power_mode_on_device(adev->platform, usecase->in_snd_device)) {
1492 platform_set_island_cfg_on_device(adev, usecase->in_snd_device, false);
1493 platform_set_power_mode_on_device(adev, usecase->in_snd_device, false);
1494 platform_reset_island_power_status(adev->platform, usecase->in_snd_device);
Kunlei Zhang91c4b332020-07-20 17:53:14 +08001495 if (voice_is_lte_call_active(adev))
1496 platform_set_tx_lpi_mode(adev->platform, false);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001497 ALOGD("%s: disable island cfg and power mode in voice tx path",
1498 __func__);
1499 }
1500 }
1501 if (usecase->out_snd_device != SND_DEVICE_NONE) {
1502 if (platform_get_island_cfg_on_device(adev->platform, usecase->out_snd_device) &&
1503 platform_get_power_mode_on_device(adev->platform, usecase->out_snd_device)) {
1504 platform_set_island_cfg_on_device(adev, usecase->out_snd_device, false);
1505 platform_set_power_mode_on_device(adev, usecase->out_snd_device, false);
1506 platform_reset_island_power_status(adev->platform, usecase->out_snd_device);
1507 ALOGD("%s: disable island cfg and power mode in voice rx path",
1508 __func__);
1509 }
1510 }
1511 }
1512
Andy Hung756ecc12018-10-19 17:47:12 -07001513 // we shouldn't truncate mixer_path
1514 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1515 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1516 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001517 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001518 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001519 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Carter Hsu2e429db2019-05-14 18:50:52 +08001520 if (usecase->type == PCM_CAPTURE) {
1521 struct stream_in *in = usecase->stream.in;
1522 if (in && in->ec_opened) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001523 struct listnode out_devices;
1524 list_init(&out_devices);
1525 platform_set_echo_reference(in->dev, false, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001526 in->ec_opened = false;
1527 }
1528 }
Kunlei Zhanga3c4cb02021-03-05 16:03:54 +08001529 if (usecase->id == adev->fluence_nn_usecase_id) {
1530 platform_set_fluence_nn_state(adev->platform, false);
1531 adev->fluence_nn_usecase_id = USECASE_INVALID;
1532 ALOGD("%s: reset fluence nn capture state", __func__);
1533 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001534 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301535 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301536
1537 if (usecase->type == PCM_CAPTURE) {
1538 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001539 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301540 ALOGD("%s: reset custom mtmx params v1", __func__);
1541 audio_extn_set_custom_mtmx_params_v1(adev, usecase, false);
1542 }
1543 } else {
1544 audio_extn_set_custom_mtmx_params_v2(adev, usecase, false);
1545 }
1546
Weiyin Jiang298ffd92019-06-03 14:29:30 +08001547 if ((usecase->type == PCM_PLAYBACK) &&
1548 (usecase->stream.out != NULL))
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05301549 usecase->stream.out->pspd_coeff_sent = false;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301550
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001551 ALOGV("%s: exit", __func__);
1552 return 0;
1553}
1554
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001555int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001556 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001557{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301558 int i, num_devices = 0;
1559 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001560 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1561
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001562 if (snd_device < SND_DEVICE_MIN ||
1563 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001564 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001565 return -EINVAL;
1566 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001567
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001568 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001569 ALOGE("%s: Invalid sound device returned", __func__);
1570 return -EINVAL;
1571 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001572
1573 adev->snd_dev_ref_cnt[snd_device]++;
1574
1575 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1576 (platform_split_snd_device(adev->platform,
1577 snd_device,
1578 &num_devices,
1579 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001580 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001581 __func__, snd_device, device_name);
Aniket Kumar Lata990de552019-07-11 14:20:23 -07001582 /* Set backend config for A2DP to ensure slimbus configuration
1583 is correct if A2DP is already active and backend is closed
1584 and re-opened */
1585 if (snd_device == SND_DEVICE_OUT_BT_A2DP)
1586 audio_extn_a2dp_set_source_backend_cfg();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001587 return 0;
1588 }
1589
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001590 if (audio_extn_spkr_prot_is_enabled())
1591 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001592
Aalique Grahame22e49102018-12-18 14:23:57 -08001593 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1594
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001595 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1596 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001597 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1598 goto err;
1599 }
1600 audio_extn_dev_arbi_acquire(snd_device);
1601 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001602 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001603 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001604 goto err;
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001605 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001606 } else if (platform_split_snd_device(adev->platform,
1607 snd_device,
1608 &num_devices,
1609 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301610 for (i = 0; i < num_devices; i++) {
1611 enable_snd_device(adev, new_snd_devices[i]);
1612 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001613 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001614 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001615 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301616
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001617 /* enable island and power mode on supported device */
1618 if (platform_get_island_cfg_on_device(adev->platform, snd_device) &&
1619 platform_get_power_mode_on_device(adev->platform, snd_device)) {
1620 platform_set_island_cfg_on_device(adev, snd_device, true);
1621 platform_set_power_mode_on_device(adev, snd_device, true);
Kunlei Zhang91c4b332020-07-20 17:53:14 +08001622 if (voice_is_lte_call_active(adev) &&
1623 (snd_device >= SND_DEVICE_IN_BEGIN &&
1624 snd_device < SND_DEVICE_IN_END))
1625 platform_set_tx_lpi_mode(adev->platform, true);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001626 ALOGD("%s: enable island cfg and power mode on: %s",
1627 __func__, device_name);
1628 }
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301629
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301630 if (SND_DEVICE_OUT_BT_A2DP == snd_device) {
Ramjee Singh2d2944a2021-12-14 14:13:41 +05301631
1632 struct audio_usecase *usecase;
1633 struct listnode *node;
1634 /* Disable SCO Devices and enable handset mic for active input stream */
1635 list_for_each(node, &adev->usecase_list) {
1636 usecase = node_to_item(node, struct audio_usecase, list);
1637 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
1638 is_sco_in_device_type(&usecase->stream.in->device_list)) {
1639 ALOGD("a2dp resumed, switch bt sco mic to handset mic");
1640 reassign_device_list(&usecase->stream.in->device_list,
1641 AUDIO_DEVICE_IN_BUILTIN_MIC, "");
1642 select_devices(adev, usecase->id);
1643 }
1644 }
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301645 if (audio_extn_a2dp_start_playback() < 0) {
1646 ALOGE(" fail to configure A2dp Source control path ");
1647 goto err;
1648 } else {
1649 adev->a2dp_started = true;
1650 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001651 }
Florian Pfister1a84f312018-07-19 14:38:18 +02001652
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001653 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1654 (audio_extn_a2dp_start_capture() < 0)) {
1655 ALOGE(" fail to configure A2dp Sink control path ");
1656 goto err;
1657 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301658
Mingshu Pang7be5b1d2020-03-04 15:24:38 +08001659 if ((SND_DEVICE_OUT_BT_SCO_SWB == snd_device) ||
1660 (SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC == snd_device) ||
1661 (SND_DEVICE_IN_BT_SCO_MIC_SWB == snd_device)) {
1662 if (!adev->bt_sco_on || (audio_extn_sco_start_configuration() < 0)) {
1663 ALOGE(" fail to configure sco control path ");
1664 goto err;
1665 }
Zhou Song12c29502019-03-16 10:37:18 +08001666 }
1667
Zhou Song331c8e52019-08-26 14:16:12 +08001668 configure_btsco_sample_rate(snd_device);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001669 /* due to the possibility of calibration overwrite between listen
1670 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001671 audio_extn_sound_trigger_update_device_status(snd_device,
1672 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301673 audio_extn_listen_update_device_status(snd_device,
1674 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001675 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001676 audio_extn_sound_trigger_update_device_status(snd_device,
1677 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301678 audio_extn_listen_update_device_status(snd_device,
1679 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001680 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001681 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001682 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001683 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301684
1685 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1686 !adev->native_playback_enabled &&
1687 audio_is_true_native_stream_active(adev)) {
1688 ALOGD("%s: %d: napb: enabling native mode in hardware",
1689 __func__, __LINE__);
1690 audio_route_apply_and_update_path(adev->audio_route,
1691 "true-native-mode");
1692 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301693 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301694 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1695 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001696 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001697 ALOGD("%s: init ec ref loopback", __func__);
1698 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1699 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001700 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001701 return 0;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001702err:
1703 adev->snd_dev_ref_cnt[snd_device]--;
1704 return -EINVAL;;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001705}
1706
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001707int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001708 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001709{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301710 int i, num_devices = 0;
1711 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001712 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1713
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001714 if (snd_device < SND_DEVICE_MIN ||
1715 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001716 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001717 return -EINVAL;
1718 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001719
1720 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1721 ALOGE("%s: Invalid sound device returned", __func__);
1722 return -EINVAL;
1723 }
1724
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001725 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1726 ALOGE("%s: device ref cnt is already 0", __func__);
1727 return -EINVAL;
1728 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001729
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001730 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001731
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001732
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001733 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001734 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301735
Aalique Grahame22e49102018-12-18 14:23:57 -08001736 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1737
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001738 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1739 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001740 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001741
1742 // when speaker device is disabled, reset swap.
1743 // will be renabled on usecase start
1744 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001745 } else if (platform_split_snd_device(adev->platform,
1746 snd_device,
1747 &num_devices,
1748 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301749 for (i = 0; i < num_devices; i++) {
1750 disable_snd_device(adev, new_snd_devices[i]);
1751 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001752 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001753 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001754 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001755 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001756
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301757 if (snd_device == SND_DEVICE_OUT_BT_A2DP) {
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301758 audio_extn_a2dp_stop_playback();
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301759 adev->a2dp_started = false;
1760 } else if (snd_device == SND_DEVICE_IN_BT_A2DP)
Florian Pfister1a84f312018-07-19 14:38:18 +02001761 audio_extn_a2dp_stop_capture();
Zhou Songd6d71752019-05-21 18:08:51 +08001762 else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001763 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
Ashish Jain81eb2a82015-05-13 10:52:34 +05301764 adev->is_channel_status_set = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001765 else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301766 adev->native_playback_enabled) {
1767 ALOGD("%s: %d: napb: disabling native mode in hardware",
1768 __func__, __LINE__);
1769 audio_route_reset_and_update_path(adev->audio_route,
1770 "true-native-mode");
1771 adev->native_playback_enabled = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001772 } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301773 adev->asrc_mode_enabled) {
1774 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301775 disable_asrc_mode(adev);
1776 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001777 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301778 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001779 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001780 ALOGD("%s: deinit ec ref loopback", __func__);
1781 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1782 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001783
1784 audio_extn_utils_release_snd_device(snd_device);
1785 } else {
1786 if (platform_split_snd_device(adev->platform,
1787 snd_device,
1788 &num_devices,
1789 new_snd_devices) == 0) {
1790 for (i = 0; i < num_devices; i++) {
1791 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1792 }
1793 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001794 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001795
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001796 return 0;
1797}
1798
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001799/*
1800 legend:
1801 uc - existing usecase
1802 new_uc - new usecase
1803 d1, d11, d2 - SND_DEVICE enums
1804 a1, a2 - corresponding ANDROID device enums
1805 B1, B2 - backend strings
1806
1807case 1
1808 uc->dev d1 (a1) B1
1809 new_uc->dev d1 (a1), d2 (a2) B1, B2
1810
1811 resolution: disable and enable uc->dev on d1
1812
1813case 2
1814 uc->dev d1 (a1) B1
1815 new_uc->dev d11 (a1) B1
1816
1817 resolution: need to switch uc since d1 and d11 are related
1818 (e.g. speaker and voice-speaker)
1819 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1820
1821case 3
1822 uc->dev d1 (a1) B1
1823 new_uc->dev d2 (a2) B2
1824
1825 resolution: no need to switch uc
1826
1827case 4
1828 uc->dev d1 (a1) B1
1829 new_uc->dev d2 (a2) B1
1830
1831 resolution: disable enable uc-dev on d2 since backends match
1832 we cannot enable two streams on two different devices if they
1833 share the same backend. e.g. if offload is on speaker device using
1834 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1835 using the same backend, offload must also be switched to voice-handset.
1836
1837case 5
1838 uc->dev d1 (a1) B1
1839 new_uc->dev d1 (a1), d2 (a2) B1
1840
1841 resolution: disable enable uc-dev on d2 since backends match
1842 we cannot enable two streams on two different devices if they
1843 share the same backend.
1844
1845case 6
1846 uc->dev d1 (a1) B1
1847 new_uc->dev d2 (a1) B2
1848
1849 resolution: no need to switch
1850
1851case 7
1852 uc->dev d1 (a1), d2 (a2) B1, B2
1853 new_uc->dev d1 (a1) B1
1854
1855 resolution: no need to switch
1856
Zhou Song4ba65882018-07-09 14:48:07 +08001857case 8
1858 uc->dev d1 (a1) B1
1859 new_uc->dev d11 (a1), d2 (a2) B1, B2
1860 resolution: compared to case 1, for this case, d1 and d11 are related
1861 then need to do the same as case 2 to siwtch to new uc
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301862
1863case 9
1864 uc->dev d1 (a1), d2(a2) B1 B2
1865 new_uc->dev d1 (a1), d22 (a2) B1, B2
1866 resolution: disable enable uc-dev on d2 since backends match
1867 we cannot enable two streams on two different devices if they
1868 share the same backend. This is special case for combo use case
1869 with a2dp and sco devices which uses same backend.
1870 e.g. speaker-a2dp and speaker-btsco
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001871*/
1872static snd_device_t derive_playback_snd_device(void * platform,
1873 struct audio_usecase *uc,
1874 struct audio_usecase *new_uc,
1875 snd_device_t new_snd_device)
1876{
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001877 struct listnode a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001878
1879 snd_device_t d1 = uc->out_snd_device;
1880 snd_device_t d2 = new_snd_device;
1881
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001882 list_init(&a1);
1883 list_init(&a2);
1884
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301885 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301886 case TRANSCODE_LOOPBACK_RX :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001887 assign_devices(&a1, &uc->stream.inout->out_config.device_list);
1888 assign_devices(&a2, &new_uc->stream.inout->out_config.device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301889 break;
1890 default :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001891 assign_devices(&a1, &uc->stream.out->device_list);
1892 assign_devices(&a2, &new_uc->stream.out->device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301893 break;
1894 }
1895
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001896 // Treat as a special case when a1 and a2 are not disjoint
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001897 if (!compare_devices(&a1, &a2) &&
1898 compare_devices_for_any_match(&a1 ,&a2)) {
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001899 snd_device_t d3[2];
1900 int num_devices = 0;
1901 int ret = platform_split_snd_device(platform,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001902 list_length(&a1) > 1 ? d1 : d2,
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001903 &num_devices,
1904 d3);
1905 if (ret < 0) {
1906 if (ret != -ENOSYS) {
1907 ALOGW("%s failed to split snd_device %d",
1908 __func__,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001909 list_length(&a1) > 1 ? d1 : d2);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001910 }
1911 goto end;
1912 }
1913
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001914 if (platform_check_backends_match(d3[0], d3[1])) {
1915 return d2; // case 5
1916 } else {
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301917 if ((list_length(&a1) > 1) && (list_length(&a2) > 1) &&
1918 platform_check_backends_match(d1, d2))
1919 return d2; //case 9
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001920 if (list_length(&a1) > 1)
Samyak Jaind826b502019-07-17 16:16:42 +05301921 return d1; //case 7
Garmond Leungb9eeba42018-09-18 11:10:41 -07001922 // check if d1 is related to any of d3's
1923 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001924 return d1; // case 1
1925 else
1926 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001927 }
1928 } else {
1929 if (platform_check_backends_match(d1, d2)) {
1930 return d2; // case 2, 4
1931 } else {
1932 return d1; // case 6, 3
1933 }
1934 }
1935
1936end:
1937 return d2; // return whatever was calculated before.
1938}
1939
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001940static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301941 struct audio_usecase *uc_info,
1942 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001943{
1944 struct listnode *node;
1945 struct audio_usecase *usecase;
1946 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301947 snd_device_t uc_derive_snd_device;
1948 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001949 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1950 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001951 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301952 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001953 /*
1954 * This function is to make sure that all the usecases that are active on
1955 * the hardware codec backend are always routed to any one device that is
1956 * handled by the hardware codec.
1957 * For example, if low-latency and deep-buffer usecases are currently active
1958 * on speaker and out_set_parameters(headset) is received on low-latency
1959 * output, then we have to make sure deep-buffer is also switched to headset,
1960 * because of the limitation that both the devices cannot be enabled
1961 * at the same time as they share the same backend.
1962 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001963 /*
1964 * This call is to check if we need to force routing for a particular stream
1965 * If there is a backend configuration change for the device when a
1966 * new stream starts, then ADM needs to be closed and re-opened with the new
1967 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001968 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001969 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001970 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1971 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301972 /* For a2dp device reconfigure all active sessions
1973 * with new AFE encoder format based on a2dp state
1974 */
1975 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301976 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device ||
1977 SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP == snd_device) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301978 audio_extn_a2dp_is_force_device_switch()) {
1979 force_routing = true;
1980 force_restart_session = true;
1981 }
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001982
1983 /*
1984 * Island cfg and power mode config needs to set before AFE port start.
1985 * Set force routing in case of voice device was enable before.
1986 */
1987 if (uc_info->type == VOICE_CALL &&
1988 voice_extn_is_voice_power_mode_supported() &&
Kunlei Zhang67cc7072020-12-18 17:16:49 +08001989 is_supported_conc_usecase_for_power_mode_call(adev) &&
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001990 platform_check_and_update_island_power_status(adev->platform,
1991 uc_info,
1992 snd_device)) {
1993 force_routing = true;
1994 ALOGD("%s:becf: force routing %d for power mode supported device",
1995 __func__, force_routing);
1996 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301997 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1998
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001999 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002000 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002001 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002002 for (i = 0; i < AUDIO_USECASE_MAX; i++)
2003 switch_device[i] = false;
2004
2005 list_for_each(node, &adev->usecase_list) {
2006 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08002007
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05302008 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
2009 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302010 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05302011 platform_get_snd_device_name(usecase->out_snd_device),
2012 platform_check_backends_match(snd_device, usecase->out_snd_device));
Rahul Sharma99770982019-03-06 17:05:26 +05302013 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
2014 (usecase->type != PCM_PASSTHROUGH)) {
Ashish Jain6a65b352017-03-21 17:24:40 +05302015 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
2016 usecase, uc_info, snd_device);
2017 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002018 (is_codec_backend_out_device_type(&usecase->device_list) ||
2019 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
2020 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_DEVICE) ||
2021 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_HEADSET) ||
2022 is_a2dp_out_device_type(&usecase->device_list) ||
2023 is_sco_out_device_type(&usecase->device_list)) &&
Ashish Jain6a65b352017-03-21 17:24:40 +05302024 ((force_restart_session) ||
2025 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05302026 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
2027 __func__, use_case_table[usecase->id],
2028 platform_get_snd_device_name(usecase->out_snd_device));
2029 disable_audio_route(adev, usecase);
2030 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05302031 /* Enable existing usecase on derived playback device */
2032 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05302033 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05302034 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002035 }
2036 }
2037
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302038 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
2039 num_uc_to_switch);
2040
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002041 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07002042 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002043
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05302044 /* Make sure the previous devices to be disabled first and then enable the
2045 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002046 list_for_each(node, &adev->usecase_list) {
2047 usecase = node_to_item(node, struct audio_usecase, list);
2048 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08002049 /* Check if output sound device to be switched can be split and if any
2050 of the split devices match with derived sound device */
2051 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
2052 &num_devices, split_snd_devices) == 0) {
2053 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
2054 for (i = 0; i < num_devices; i++) {
2055 /* Disable devices that do not match with derived sound device */
2056 if (split_snd_devices[i] != derive_snd_device[usecase->id])
2057 disable_snd_device(adev, split_snd_devices[i]);
2058 }
2059 } else {
2060 disable_snd_device(adev, usecase->out_snd_device);
2061 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002062 }
2063 }
2064
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07002065 list_for_each(node, &adev->usecase_list) {
2066 usecase = node_to_item(node, struct audio_usecase, list);
2067 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08002068 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
2069 &num_devices, split_snd_devices) == 0) {
2070 /* Enable derived sound device only if it does not match with
2071 one of the split sound devices. This is because the matching
2072 sound device was not disabled */
2073 bool should_enable = true;
2074 for (i = 0; i < num_devices; i++) {
2075 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
2076 should_enable = false;
2077 break;
2078 }
2079 }
2080 if (should_enable)
2081 enable_snd_device(adev, derive_snd_device[usecase->id]);
2082 } else {
2083 enable_snd_device(adev, derive_snd_device[usecase->id]);
2084 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07002085 }
2086 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002087
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002088 /* Re-route all the usecases on the shared backend other than the
2089 specified usecase to new snd devices */
2090 list_for_each(node, &adev->usecase_list) {
2091 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05302092 /* Update the out_snd_device only before enabling the audio route */
2093 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05302094 usecase->out_snd_device = derive_snd_device[usecase->id];
Lakshman Chaluvarajuab7e5572020-10-28 19:29:23 +05302095 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
2096 use_case_table[usecase->id],
2097 platform_get_snd_device_name(usecase->out_snd_device));
2098 /* Update voc calibration before enabling Voice/VoIP route */
2099 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL)
2100 status = platform_switch_voice_call_device_post(adev->platform,
2101 usecase->out_snd_device,
2102 platform_get_input_snd_device(
2103 adev->platform, NULL,
2104 &uc_info->device_list,
2105 usecase->type));
2106 enable_audio_route(adev, usecase);
2107 if (usecase->stream.out && usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
2108 out_set_voip_volume(&usecase->stream.out->stream,
2109 usecase->stream.out->volume_l,
2110 usecase->stream.out->volume_r);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05302111 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002112 }
2113 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002114 }
2115}
2116
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302117static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002118 struct audio_usecase *uc_info,
2119 snd_device_t snd_device)
2120{
2121 struct listnode *node;
2122 struct audio_usecase *usecase;
2123 bool switch_device[AUDIO_USECASE_MAX];
2124 int i, num_uc_to_switch = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002125 int backend_check_cond = is_codec_backend_out_device_type(&uc_info->device_list);
kunleiz5cd52b82016-11-07 17:22:52 +08002126 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002127
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302128 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
2129 snd_device);
2130 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05302131
2132 /*
2133 * Make sure out devices is checked against out codec backend device and
2134 * also in devices against in codec backend. Checking out device against in
2135 * codec backend or vice versa causes issues.
2136 */
2137 if (uc_info->type == PCM_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002138 backend_check_cond = is_codec_backend_in_device_type(&uc_info->device_list);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08002139
2140 /*
2141 * Island cfg and power mode config needs to set before AFE port start.
2142 * Set force routing in case of voice device was enable before.
2143 */
2144
2145 if (uc_info->type == VOICE_CALL &&
2146 voice_extn_is_voice_power_mode_supported() &&
Kunlei Zhang67cc7072020-12-18 17:16:49 +08002147 is_supported_conc_usecase_for_power_mode_call(adev) &&
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08002148 platform_check_and_update_island_power_status(adev->platform,
2149 uc_info,
2150 snd_device)) {
2151 force_routing = true;
2152 ALOGD("%s:becf: force routing %d for power mode supported device",
2153 __func__, force_routing);
2154 }
2155
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002156 /*
2157 * This function is to make sure that all the active capture usecases
2158 * are always routed to the same input sound device.
2159 * For example, if audio-record and voice-call usecases are currently
2160 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
2161 * is received for voice call then we have to make sure that audio-record
2162 * usecase is also switched to earpiece i.e. voice-dmic-ef,
2163 * because of the limitation that two devices cannot be enabled
2164 * at the same time if they share the same backend.
2165 */
2166 for (i = 0; i < AUDIO_USECASE_MAX; i++)
2167 switch_device[i] = false;
2168
2169 list_for_each(node, &adev->usecase_list) {
2170 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05302171 /*
2172 * TODO: Enhance below condition to handle BT sco/USB multi recording
2173 */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302174
2175 bool capture_uc_needs_routing = usecase->type != PCM_PLAYBACK && (usecase != uc_info &&
2176 (usecase->in_snd_device != snd_device || force_routing));
2177 bool call_proxy_snd_device = platform_is_call_proxy_snd_device(snd_device) ||
2178 platform_is_call_proxy_snd_device(usecase->in_snd_device);
2179 if (capture_uc_needs_routing && !call_proxy_snd_device &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002180 ((backend_check_cond &&
2181 (is_codec_backend_in_device_type(&usecase->device_list) ||
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08002182 (usecase->type == VOIP_CALL))) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08002183 ((uc_info->type == VOICE_CALL &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002184 is_single_device_type_equal(&usecase->device_list,
2185 AUDIO_DEVICE_IN_VOICE_CALL)) ||
Anver sadhique4fdc6992022-01-21 12:26:28 +05302186 platform_check_all_backends_match(snd_device,\
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002187 usecase->in_snd_device))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07002188 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05302189 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..",
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002190 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07002191 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002192 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002193 switch_device[usecase->id] = true;
2194 num_uc_to_switch++;
2195 }
2196 }
2197
2198 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07002199 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002200
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05302201 /* Make sure the previous devices to be disabled first and then enable the
2202 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002203 list_for_each(node, &adev->usecase_list) {
2204 usecase = node_to_item(node, struct audio_usecase, list);
2205 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002206 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08002207 }
2208 }
2209
2210 list_for_each(node, &adev->usecase_list) {
2211 usecase = node_to_item(node, struct audio_usecase, list);
2212 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002213 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002214 }
2215 }
2216
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002217 /* Re-route all the usecases on the shared backend other than the
2218 specified usecase to new snd devices */
2219 list_for_each(node, &adev->usecase_list) {
2220 usecase = node_to_item(node, struct audio_usecase, list);
2221 /* Update the in_snd_device only before enabling the audio route */
2222 if (switch_device[usecase->id] ) {
2223 usecase->in_snd_device = snd_device;
Lakshman Chaluvarajuab7e5572020-10-28 19:29:23 +05302224 /* Update voc calibration before enabling Voice/VoIP route */
2225 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
2226 snd_device_t voip_snd_device;
2227 voip_snd_device = platform_get_output_snd_device(adev->platform,
2228 usecase->stream.out,
2229 usecase->type);
2230 status = platform_switch_voice_call_device_post(adev->platform,
2231 voip_snd_device,
2232 usecase->in_snd_device);
kunleiz5cd52b82016-11-07 17:22:52 +08002233 }
Lakshman Chaluvarajuab7e5572020-10-28 19:29:23 +05302234 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002235 }
2236 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002237 }
2238}
2239
Mingming Yin3a941d42016-02-17 18:08:05 -08002240static void reset_hdmi_sink_caps(struct stream_out *out) {
2241 int i = 0;
2242
2243 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
2244 out->supported_channel_masks[i] = 0;
2245 }
2246 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
2247 out->supported_formats[i] = 0;
2248 }
2249 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
2250 out->supported_sample_rates[i] = 0;
2251 }
2252}
2253
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002254/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08002255static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002256{
Mingming Yin3a941d42016-02-17 18:08:05 -08002257 int ret = 0, i = 0, j = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002258 int channels = platform_edid_get_max_channels_v2(out->dev->platform,
2259 out->extconn.cs.controller,
2260 out->extconn.cs.stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002261
Mingming Yin3a941d42016-02-17 18:08:05 -08002262 reset_hdmi_sink_caps(out);
2263
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002264 /* Cache ext disp type */
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002265 ret = platform_get_ext_disp_type_v2(adev->platform,
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002266 out->extconn.cs.controller,
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002267 out->extconn.cs.stream);
2268 if(ret < 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002269 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07002270 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002271 }
2272
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002273 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002274 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08002275 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002276 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08002277 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
2278 case 6:
2279 ALOGV("%s: HDMI supports 5.1 channels", __func__);
2280 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
2281 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
2282 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
2283 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
2284 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002285 break;
2286 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08002287 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002288 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002289 break;
2290 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002291
2292 // check channel format caps
2293 i = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002294 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_AC3,
2295 out->extconn.cs.controller,
2296 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002297 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
2298 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
2299 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
2300 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
2301 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
2302 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
2303 }
2304
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002305 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD,
2306 out->extconn.cs.controller,
2307 out->extconn.cs.stream)) {
Ben Romberger1aaaf862017-04-06 17:49:46 -07002308 ALOGV(":%s HDMI supports TRUE HD format", __func__);
2309 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
2310 }
2311
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002312 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS,
2313 out->extconn.cs.controller,
2314 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002315 ALOGV(":%s HDMI supports DTS format", __func__);
2316 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
2317 }
2318
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002319 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS_HD,
2320 out->extconn.cs.controller,
2321 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002322 ALOGV(":%s HDMI supports DTS HD format", __func__);
2323 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
2324 }
2325
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002326 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_IEC61937,
2327 out->extconn.cs.controller,
2328 out->extconn.cs.stream)) {
Naresh Tanniru928f0862017-04-07 16:44:23 -07002329 ALOGV(":%s HDMI supports IEC61937 format", __func__);
2330 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
2331 }
2332
Mingming Yin3a941d42016-02-17 18:08:05 -08002333
2334 // check sample rate caps
2335 i = 0;
2336 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002337 if (platform_is_edid_supported_sample_rate_v2(out->dev->platform, out_hdmi_sample_rates[j],
2338 out->extconn.cs.controller,
2339 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002340 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
2341 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
2342 }
2343 }
2344
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002345 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002346}
2347
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002348static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
2349 uint32_t *supported_sample_rates __unused,
2350 uint32_t max_rates __unused)
2351{
2352 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
2353 supported_sample_rates,
2354 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05302355 ssize_t i = 0;
2356
2357 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002358 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
2359 supported_sample_rates[i]);
2360 }
2361 return count;
2362}
2363
2364static inline int read_usb_sup_channel_masks(bool is_playback,
2365 audio_channel_mask_t *supported_channel_masks,
2366 uint32_t max_masks)
2367{
2368 int channels = audio_extn_usb_get_max_channels(is_playback);
2369 int channel_count;
2370 uint32_t num_masks = 0;
2371 if (channels > MAX_HIFI_CHANNEL_COUNT)
2372 channels = MAX_HIFI_CHANNEL_COUNT;
2373
2374 if (is_playback) {
Eric Laurent68a87112019-05-01 18:07:29 -07002375 // start from 2 channels as framework currently doesn't support mono.
2376 if (channels >= FCC_2) {
2377 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(FCC_2);
2378 }
2379 for (channel_count = FCC_2;
2380 channel_count <= channels && num_masks < max_masks;
2381 ++channel_count) {
2382 supported_channel_masks[num_masks++] =
2383 audio_channel_mask_for_index_assignment_from_count(channel_count);
2384 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002385 } else {
vincenttewf51c94e2019-05-07 10:28:53 +08002386 // For capture we report all supported channel masks from 1 channel up.
2387 channel_count = MIN_CHANNEL_COUNT;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002388 // audio_channel_in_mask_from_count() does the right conversion to either positional or
2389 // indexed mask
Eric Laurent68a87112019-05-01 18:07:29 -07002390 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
2391 audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
2392 if (channel_count <= FCC_2) {
2393 mask = audio_channel_in_mask_from_count(channel_count);
2394 supported_channel_masks[num_masks++] = mask;
2395 }
2396 const audio_channel_mask_t index_mask =
2397 audio_channel_mask_for_index_assignment_from_count(channel_count);
2398 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
2399 supported_channel_masks[num_masks++] = index_mask;
2400 }
2401 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002402 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302403
vincenttewf51c94e2019-05-07 10:28:53 +08002404 for (size_t i = 0; i < num_masks; ++i) {
2405 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
2406 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302407 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002408 return num_masks;
2409}
2410
2411static inline int read_usb_sup_formats(bool is_playback __unused,
2412 audio_format_t *supported_formats,
2413 uint32_t max_formats __unused)
2414{
2415 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
2416 switch (bitwidth) {
2417 case 24:
2418 // XXX : usb.c returns 24 for s24 and s24_le?
2419 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
2420 break;
2421 case 32:
2422 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
2423 break;
2424 case 16:
2425 default :
2426 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
2427 break;
2428 }
2429 ALOGV("%s: %s supported format %d", __func__,
2430 is_playback ? "P" : "C", bitwidth);
2431 return 1;
2432}
2433
2434static inline int read_usb_sup_params_and_compare(bool is_playback,
2435 audio_format_t *format,
2436 audio_format_t *supported_formats,
2437 uint32_t max_formats,
2438 audio_channel_mask_t *mask,
2439 audio_channel_mask_t *supported_channel_masks,
2440 uint32_t max_masks,
2441 uint32_t *rate,
2442 uint32_t *supported_sample_rates,
2443 uint32_t max_rates) {
2444 int ret = 0;
2445 int num_formats;
2446 int num_masks;
2447 int num_rates;
2448 int i;
2449
2450 num_formats = read_usb_sup_formats(is_playback, supported_formats,
2451 max_formats);
2452 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
2453 max_masks);
2454
2455 num_rates = read_usb_sup_sample_rates(is_playback,
2456 supported_sample_rates, max_rates);
2457
2458#define LUT(table, len, what, dflt) \
2459 for (i=0; i<len && (table[i] != what); i++); \
2460 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
2461
2462 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
2463 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
2464 LUT(supported_sample_rates, num_rates, *rate, 0);
2465
2466#undef LUT
2467 return ret < 0 ? -EINVAL : 0; // HACK TBD
2468}
2469
Alexy Josephb1379942016-01-29 15:49:38 -08002470audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002471 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002472{
2473 struct audio_usecase *usecase;
2474 struct listnode *node;
2475
2476 list_for_each(node, &adev->usecase_list) {
2477 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002478 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002479 ALOGV("%s: usecase id %d", __func__, usecase->id);
2480 return usecase->id;
2481 }
2482 }
2483 return USECASE_INVALID;
2484}
2485
Alexy Josephb1379942016-01-29 15:49:38 -08002486struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002487 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002488{
2489 struct audio_usecase *usecase;
2490 struct listnode *node;
2491
2492 list_for_each(node, &adev->usecase_list) {
2493 usecase = node_to_item(node, struct audio_usecase, list);
2494 if (usecase->id == uc_id)
2495 return usecase;
2496 }
2497 return NULL;
2498}
2499
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302500/*
2501 * is a true native playback active
2502 */
2503bool audio_is_true_native_stream_active(struct audio_device *adev)
2504{
2505 bool active = false;
2506 int i = 0;
2507 struct listnode *node;
2508
2509 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
2510 ALOGV("%s:napb: not in true mode or non hdphones device",
2511 __func__);
2512 active = false;
2513 goto exit;
2514 }
2515
2516 list_for_each(node, &adev->usecase_list) {
2517 struct audio_usecase *uc;
2518 uc = node_to_item(node, struct audio_usecase, list);
2519 struct stream_out *curr_out =
2520 (struct stream_out*) uc->stream.out;
2521
2522 if (curr_out && PCM_PLAYBACK == uc->type) {
2523 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
2524 "(%d) device %s", __func__, i++, use_case_table[uc->id],
2525 uc->id, curr_out->sample_rate,
2526 curr_out->bit_width,
2527 platform_get_snd_device_name(uc->out_snd_device));
2528
2529 if (is_offload_usecase(uc->id) &&
2530 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
2531 active = true;
2532 ALOGD("%s:napb:native stream detected", __func__);
2533 }
2534 }
2535 }
2536exit:
2537 return active;
2538}
2539
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002540uint32_t adev_get_dsp_bit_width_enforce_mode()
2541{
2542 if (adev == NULL) {
2543 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
2544 return 0;
2545 }
2546 return adev->dsp_bit_width_enforce_mode;
2547}
2548
2549static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
2550{
2551 char value[PROPERTY_VALUE_MAX];
2552 int trial;
2553 uint32_t dsp_bit_width_enforce_mode = 0;
2554
2555 if (!mixer) {
2556 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
2557 __func__);
2558 return 0;
2559 }
2560
2561 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
2562 value, NULL) > 0) {
2563 trial = atoi(value);
2564 switch (trial) {
2565 case 16:
2566 dsp_bit_width_enforce_mode = 16;
2567 break;
2568 case 24:
2569 dsp_bit_width_enforce_mode = 24;
2570 break;
2571 case 32:
2572 dsp_bit_width_enforce_mode = 32;
2573 break;
2574 default:
2575 dsp_bit_width_enforce_mode = 0;
2576 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
2577 break;
2578 }
2579 }
2580
2581 return dsp_bit_width_enforce_mode;
2582}
2583
2584static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
2585 uint32_t enforce_mode,
2586 bool enable)
2587{
2588 struct mixer_ctl *ctl = NULL;
2589 const char *mixer_ctl_name = "ASM Bit Width";
2590 uint32_t asm_bit_width_mode = 0;
2591
2592 if (enforce_mode == 0) {
2593 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
2594 return;
2595 }
2596
2597 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
2598 if (!ctl) {
2599 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2600 __func__, mixer_ctl_name);
2601 return;
2602 }
2603
2604 if (enable)
2605 asm_bit_width_mode = enforce_mode;
2606 else
2607 asm_bit_width_mode = 0;
2608
2609 ALOGV("%s DSP bit width feature status is %d width=%d",
2610 __func__, enable, asm_bit_width_mode);
2611 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2612 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2613 asm_bit_width_mode);
2614
2615 return;
2616}
2617
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302618/*
2619 * if native DSD playback active
2620 */
2621bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2622{
2623 bool active = false;
2624 struct listnode *node = NULL;
2625 struct audio_usecase *uc = NULL;
2626 struct stream_out *curr_out = NULL;
2627
2628 list_for_each(node, &adev->usecase_list) {
2629 uc = node_to_item(node, struct audio_usecase, list);
2630 curr_out = (struct stream_out*) uc->stream.out;
2631
2632 if (curr_out && PCM_PLAYBACK == uc->type &&
2633 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2634 active = true;
2635 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302636 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302637 }
2638 }
2639 return active;
2640}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302641
2642static bool force_device_switch(struct audio_usecase *usecase)
2643{
2644 bool ret = false;
2645 bool is_it_true_mode = false;
2646
Zhou Song30f2c3e2018-02-08 14:02:15 +08002647 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302648 usecase->type == TRANSCODE_LOOPBACK_RX ||
2649 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002650 return false;
2651 }
2652
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002653 if(usecase->stream.out == NULL) {
2654 ALOGE("%s: stream.out is NULL", __func__);
2655 return false;
2656 }
2657
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302658 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002659 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002660 (compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADSET) ||
2661 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADPHONE))) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302662 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2663 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2664 (!is_it_true_mode && adev->native_playback_enabled)){
2665 ret = true;
2666 ALOGD("napb: time to toggle native mode");
2667 }
2668 }
2669
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302670 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302671 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2672 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002673 if(is_a2dp_out_device_type(&usecase->stream.out->device_list) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302674 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302675 ALOGD("Force a2dp device switch to update new encoder config");
2676 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002677 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302678
Florian Pfister1a84f312018-07-19 14:38:18 +02002679 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302680 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2681 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002682 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302683 return ret;
2684}
2685
Aalique Grahame22e49102018-12-18 14:23:57 -08002686static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2687{
2688 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2689}
2690
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302691bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2692{
2693 bool ret=false;
2694 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
Zhou Song5657f492019-08-07 11:30:39 +08002695 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
2696 out_snd_device == SND_DEVICE_OUT_BT_SCO_SWB) ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302697 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2698 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
Zhou Song5657f492019-08-07 11:30:39 +08002699 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302700 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
Mingshu Pang16093502020-04-20 11:21:16 +08002701 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC ||
2702 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC)
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302703 ret = true;
2704
2705 return ret;
2706}
2707
2708bool is_a2dp_device(snd_device_t out_snd_device)
2709{
2710 bool ret=false;
2711 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2712 ret = true;
2713
2714 return ret;
2715}
2716
2717bool is_bt_soc_on(struct audio_device *adev)
2718{
2719 struct mixer_ctl *ctl;
2720 char *mixer_ctl_name = "BT SOC status";
2721 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2722 bool bt_soc_status = true;
2723 if (!ctl) {
2724 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2725 __func__, mixer_ctl_name);
2726 /*This is to ensure we dont break targets which dont have the kernel change*/
2727 return true;
2728 }
2729 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2730 ALOGD("BT SOC status: %d",bt_soc_status);
2731 return bt_soc_status;
2732}
2733
Zhou Song331c8e52019-08-26 14:16:12 +08002734static int configure_btsco_sample_rate(snd_device_t snd_device)
2735{
2736 struct mixer_ctl *ctl = NULL;
2737 struct mixer_ctl *ctl_sr_rx = NULL, *ctl_sr_tx = NULL, *ctl_sr = NULL;
2738 char *rate_str = NULL;
2739 bool is_rx_dev = true;
2740
2741 if (is_btsco_device(snd_device, snd_device)) {
2742 ctl_sr_tx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate TX");
2743 ctl_sr_rx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate RX");
2744 if (!ctl_sr_tx || !ctl_sr_rx) {
2745 ctl_sr = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate");
2746 if (!ctl_sr)
2747 return -ENOSYS;
2748 }
2749
2750 switch (snd_device) {
2751 case SND_DEVICE_OUT_BT_SCO:
2752 rate_str = "KHZ_8";
2753 break;
2754 case SND_DEVICE_IN_BT_SCO_MIC_NREC:
2755 case SND_DEVICE_IN_BT_SCO_MIC:
2756 rate_str = "KHZ_8";
2757 is_rx_dev = false;
2758 break;
2759 case SND_DEVICE_OUT_BT_SCO_WB:
2760 rate_str = "KHZ_16";
2761 break;
2762 case SND_DEVICE_IN_BT_SCO_MIC_WB_NREC:
2763 case SND_DEVICE_IN_BT_SCO_MIC_WB:
2764 rate_str = "KHZ_16";
2765 is_rx_dev = false;
2766 break;
2767 default:
2768 return 0;
2769 }
2770
2771 ctl = (ctl_sr == NULL) ? (is_rx_dev ? ctl_sr_rx : ctl_sr_tx) : ctl_sr;
2772 if (mixer_ctl_set_enum_by_string(ctl, rate_str) != 0)
2773 return -ENOSYS;
2774 }
2775 return 0;
2776}
2777
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302778int out_standby_l(struct audio_stream *stream);
2779
Eric Laurent637e2d42018-11-15 12:24:31 -08002780struct stream_in *adev_get_active_input(const struct audio_device *adev)
2781{
2782 struct listnode *node;
2783 struct stream_in *last_active_in = NULL;
2784
2785 /* Get last added active input.
2786 * TODO: We may use a priority mechanism to pick highest priority active source */
2787 list_for_each(node, &adev->usecase_list)
2788 {
2789 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2790 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL)
2791 last_active_in = usecase->stream.in;
2792 }
2793
2794 return last_active_in;
2795}
2796
2797struct stream_in *get_voice_communication_input(const struct audio_device *adev)
2798{
2799 struct listnode *node;
2800
2801 /* First check active inputs with voice communication source and then
2802 * any input if audio mode is in communication */
2803 list_for_each(node, &adev->usecase_list)
2804 {
2805 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2806 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
2807 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
2808 return usecase->stream.in;
2809 }
2810 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION)
2811 return adev_get_active_input(adev);
2812
2813 return NULL;
2814}
2815
Carter Hsu2e429db2019-05-14 18:50:52 +08002816/*
2817 * Aligned with policy.h
2818 */
2819static inline int source_priority(int inputSource)
2820{
2821 switch (inputSource) {
2822 case AUDIO_SOURCE_VOICE_COMMUNICATION:
2823 return 9;
2824 case AUDIO_SOURCE_CAMCORDER:
2825 return 8;
2826 case AUDIO_SOURCE_VOICE_PERFORMANCE:
2827 return 7;
2828 case AUDIO_SOURCE_UNPROCESSED:
2829 return 6;
2830 case AUDIO_SOURCE_MIC:
2831 return 5;
2832 case AUDIO_SOURCE_ECHO_REFERENCE:
2833 return 4;
2834 case AUDIO_SOURCE_FM_TUNER:
2835 return 3;
2836 case AUDIO_SOURCE_VOICE_RECOGNITION:
2837 return 2;
2838 case AUDIO_SOURCE_HOTWORD:
2839 return 1;
2840 default:
2841 break;
2842 }
2843 return 0;
2844}
2845
2846static struct stream_in *get_priority_input(struct audio_device *adev)
2847{
2848 struct listnode *node;
2849 struct audio_usecase *usecase;
2850 int last_priority = 0, priority;
2851 struct stream_in *priority_in = NULL;
2852 struct stream_in *in;
2853
2854 list_for_each(node, &adev->usecase_list) {
2855 usecase = node_to_item(node, struct audio_usecase, list);
2856 if (usecase->type == PCM_CAPTURE) {
2857 in = usecase->stream.in;
2858 if (!in)
2859 continue;
2860 priority = source_priority(in->source);
2861
2862 if (priority > last_priority) {
2863 last_priority = priority;
2864 priority_in = in;
2865 }
2866 }
2867 }
2868 return priority_in;
2869}
2870
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002871int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002872{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002873 snd_device_t out_snd_device = SND_DEVICE_NONE;
2874 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002875 struct audio_usecase *usecase = NULL;
2876 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002877 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002878 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302879 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002880 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002881 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002882
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302883 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2884
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002885 usecase = get_usecase_from_list(adev, uc_id);
2886 if (usecase == NULL) {
2887 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2888 return -EINVAL;
2889 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002890
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002891 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002892 (usecase->type == VOIP_CALL) ||
Derek Chena30a5f42019-12-03 11:17:09 -05002893 (usecase->type == PCM_HFP_CALL)||
Fei Tongaffdf732020-02-20 20:39:05 +08002894 (usecase->type == ICC_CALL) ||
2895 (usecase->type == SYNTH_LOOPBACK)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302896 if(usecase->stream.out == NULL) {
2897 ALOGE("%s: stream.out is NULL", __func__);
2898 return -EINVAL;
2899 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002900 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS)) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002901 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev,
2902 uc_id);
2903 in_snd_device = audio_extn_auto_hal_get_input_snd_device(adev,
2904 uc_id);
2905 } else {
2906 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302907 usecase->stream.out, usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002908 in_snd_device = platform_get_input_snd_device(adev->platform,
2909 NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302910 &usecase->stream.out->device_list,
2911 usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002912 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002913 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302914 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302915 if (usecase->stream.inout == NULL) {
2916 ALOGE("%s: stream.inout is NULL", __func__);
2917 return -EINVAL;
2918 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002919 assign_devices(&stream_out.device_list, &usecase->stream.inout->out_config.device_list);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302920 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2921 stream_out.format = usecase->stream.inout->out_config.format;
2922 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
Jaideep Sharma477917f2020-03-13 18:13:33 +05302923 out_snd_device = platform_get_output_snd_device(adev->platform, &stream_out, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002924 assign_devices(&usecase->device_list,
2925 &usecase->stream.inout->out_config.device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302926 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2927 if (usecase->stream.inout == NULL) {
2928 ALOGE("%s: stream.inout is NULL", __func__);
2929 return -EINVAL;
2930 }
Manisha Agarwal03297972020-04-17 15:36:55 +05302931 struct listnode out_devices;
2932 list_init(&out_devices);
2933 in_snd_device = platform_get_input_snd_device(adev->platform, NULL,
2934 &out_devices, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002935 assign_devices(&usecase->device_list,
2936 &usecase->stream.inout->in_config.device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002937 } else {
2938 /*
2939 * If the voice call is active, use the sound devices of voice call usecase
2940 * so that it would not result any device switch. All the usecases will
2941 * be switched to new device when select_devices() is called for voice call
2942 * usecase. This is to avoid switching devices for voice call when
2943 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002944 * choose voice call device only if the use case device is
2945 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002946 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002947 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002948 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002949 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002950 if ((vc_usecase) && ((is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2951 is_codec_backend_out_device_type(&usecase->device_list)) ||
2952 (is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2953 is_codec_backend_in_device_type(&usecase->device_list)) ||
2954 is_single_device_type_equal(&vc_usecase->device_list,
2955 AUDIO_DEVICE_OUT_HEARING_AID) ||
2956 is_single_device_type_equal(&usecase->device_list,
Robert Lee8a6aaf32019-09-20 16:40:19 +08002957 AUDIO_DEVICE_IN_VOICE_CALL) ||
2958 (is_single_device_type_equal(&usecase->device_list,
Gautam Manam8fa06162021-09-24 10:41:29 +05302959 AUDIO_DEVICE_IN_BUILTIN_MIC) &&
2960 is_single_device_type_equal(&vc_usecase->device_list,
2961 AUDIO_DEVICE_OUT_USB_HEADSET)) ||
2962 (is_single_device_type_equal(&usecase->device_list,
Robert Lee8a6aaf32019-09-20 16:40:19 +08002963 AUDIO_DEVICE_IN_USB_HEADSET) &&
2964 is_single_device_type_equal(&vc_usecase->device_list,
Kamalakar Yalasiri5edba852021-01-28 14:52:38 +05302965 AUDIO_DEVICE_OUT_USB_HEADSET))||
Gautam Manamf4002142021-09-13 22:05:56 +05302966 (is_single_device_type_equal(&usecase->device_list,
2967 AUDIO_DEVICE_IN_USB_HEADSET) &&
2968 is_codec_backend_out_device_type(&vc_usecase->device_list)) ||
Kamalakar Yalasiri5edba852021-01-28 14:52:38 +05302969 (is_single_device_type_equal(&usecase->device_list,
2970 AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) &&
2971 is_codec_backend_out_device_type(&vc_usecase->device_list)))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002972 in_snd_device = vc_usecase->in_snd_device;
2973 out_snd_device = vc_usecase->out_snd_device;
2974 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002975 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002976 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002977 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002978 if ((voip_usecase != NULL) &&
2979 (usecase->type == PCM_PLAYBACK) &&
2980 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002981 out_snd_device_backend_match = platform_check_backends_match(
2982 voip_usecase->out_snd_device,
2983 platform_get_output_snd_device(
2984 adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302985 usecase->stream.out, usecase->type));
yidongh02ef86f2017-04-21 15:36:04 +08002986 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002987 if ((voip_usecase) && (is_codec_backend_out_device_type(&voip_usecase->device_list) &&
2988 (is_codec_backend_out_device_type(&usecase->device_list) ||
2989 is_codec_backend_in_device_type(&usecase->device_list)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002990 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002991 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002992 in_snd_device = voip_usecase->in_snd_device;
2993 out_snd_device = voip_usecase->out_snd_device;
2994 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002995 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002996 hfp_ucid = audio_extn_hfp_get_usecase();
2997 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002998 if ((hfp_usecase) && is_codec_backend_out_device_type(&hfp_usecase->device_list)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002999 in_snd_device = hfp_usecase->in_snd_device;
3000 out_snd_device = hfp_usecase->out_snd_device;
3001 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003002 }
3003 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05303004 if (usecase->stream.out == NULL) {
3005 ALOGE("%s: stream.out is NULL", __func__);
3006 return -EINVAL;
3007 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003008 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003009 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003010 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003011 struct stream_out *voip_out = adev->primary_output;
3012 struct stream_in *voip_in = get_voice_communication_input(adev);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003013 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS))
Guodong Hu267bdf82019-08-12 19:22:32 +08003014 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev, uc_id);
3015 else
3016 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05303017 usecase->stream.out,
3018 usecase->type);
kunleizdcf967a2018-08-07 17:09:11 +08003019 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizdcf967a2018-08-07 17:09:11 +08003020
Eric Laurent637e2d42018-11-15 12:24:31 -08003021 if (voip_usecase)
3022 voip_out = voip_usecase->stream.out;
3023
3024 if (usecase->stream.out == voip_out && voip_in != NULL)
3025 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003026 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003027 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05303028 if (usecase->stream.in == NULL) {
3029 ALOGE("%s: stream.in is NULL", __func__);
3030 return -EINVAL;
3031 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003032 assign_devices(&usecase->device_list, &usecase->stream.in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003033 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003034 if (in_snd_device == SND_DEVICE_NONE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003035 struct listnode out_devices;
Eric Laurent637e2d42018-11-15 12:24:31 -08003036 struct stream_in *voip_in = get_voice_communication_input(adev);
Carter Hsu2e429db2019-05-14 18:50:52 +08003037 struct stream_in *priority_in = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08003038
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003039 list_init(&out_devices);
Eric Laurent637e2d42018-11-15 12:24:31 -08003040 if (voip_in != NULL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003041 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
3042 USECASE_AUDIO_PLAYBACK_VOIP);
3043
Carter Hsu2e429db2019-05-14 18:50:52 +08003044 usecase->stream.in->enable_ec_port = false;
3045
Zhou Song503196b2021-07-23 17:31:05 +08003046 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY ||
3047 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY2) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003048 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_TELEPHONY_TX, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08003049 } else if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003050 assign_devices(&out_devices, &voip_usecase->stream.out->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08003051 } else if (adev->primary_output &&
3052 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003053 assign_devices(&out_devices, &adev->primary_output->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08003054 } else {
3055 /* forcing speaker o/p device to get matching i/p pair
3056 in case o/p is not routed from same primary HAL */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003057 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08003058 }
Carter Hsu2e429db2019-05-14 18:50:52 +08003059 priority_in = voip_in;
3060 } else {
3061 /* get the input with the highest priority source*/
3062 priority_in = get_priority_input(adev);
3063
Susan Wang727dd6b2021-03-26 11:28:59 -04003064 if (!priority_in ||
3065 audio_extn_auto_hal_overwrite_priority_for_auto(usecase->stream.in))
Carter Hsu2e429db2019-05-14 18:50:52 +08003066 priority_in = usecase->stream.in;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003067 }
Huicheng Liu1404ba12020-09-11 01:03:25 -04003068 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_IN_BUS)){
3069 in_snd_device = audio_extn_auto_hal_get_snd_device_for_car_audio_stream(priority_in->car_audio_stream);
3070 }
3071 else
3072 in_snd_device = platform_get_input_snd_device(adev->platform,
3073 priority_in,
3074 &out_devices,
3075 usecase->type);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003076 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003077 }
3078 }
3079
3080 if (out_snd_device == usecase->out_snd_device &&
3081 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05303082
3083 if (!force_device_switch(usecase))
3084 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003085 }
3086
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003087 if (!compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS) &&
Guodong Hu267bdf82019-08-12 19:22:32 +08003088 ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003089 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready()))) {
Guodong Hu267bdf82019-08-12 19:22:32 +08003090 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
3091 return 0;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303092 }
3093
Aalique Grahame22e49102018-12-18 14:23:57 -08003094 if (out_snd_device != SND_DEVICE_NONE &&
3095 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
3096 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
3097 __func__,
3098 use_case_table[uc_id],
3099 adev->last_logged_snd_device[uc_id][0],
3100 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
3101 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
3102 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
3103 -1,
3104 out_snd_device,
3105 platform_get_snd_device_name(out_snd_device),
3106 platform_get_snd_device_acdb_id(out_snd_device));
3107 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
3108 }
3109 if (in_snd_device != SND_DEVICE_NONE &&
3110 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
3111 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
3112 __func__,
3113 use_case_table[uc_id],
3114 adev->last_logged_snd_device[uc_id][1],
3115 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
3116 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
3117 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
3118 -1,
3119 in_snd_device,
3120 platform_get_snd_device_name(in_snd_device),
3121 platform_get_snd_device_acdb_id(in_snd_device));
3122 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
3123 }
3124
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003125
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003126 /*
3127 * Limitation: While in call, to do a device switch we need to disable
3128 * and enable both RX and TX devices though one of them is same as current
3129 * device.
3130 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07003131 if ((usecase->type == VOICE_CALL) &&
3132 (usecase->in_snd_device != SND_DEVICE_NONE) &&
3133 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07003134 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07003135 }
3136
3137 if (((usecase->type == VOICE_CALL) ||
3138 (usecase->type == VOIP_CALL)) &&
3139 (usecase->out_snd_device != SND_DEVICE_NONE)) {
3140 /* Disable sidetone only if voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303141 if (voice_is_call_state_active_in_call(adev) ||
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07003142 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07003143 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003144
3145 /* Disable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303146 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003147 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08003148 }
3149
Aalique Grahame22e49102018-12-18 14:23:57 -08003150 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
3151 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003152 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303153 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08003154 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
3155 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
3156 else
3157 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303158 }
3159
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003160 /* Disable current sound devices */
3161 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003162 disable_audio_route(adev, usecase);
3163 disable_snd_device(adev, usecase->out_snd_device);
Gautam Manam274f4752021-09-24 10:58:49 +05303164 if (usecase->id == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
3165 disable_snd_device(adev, SND_DEVICE_OUT_HAPTICS);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003166 }
3167
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003168 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003169 disable_audio_route(adev, usecase);
3170 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003171 }
3172
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08003173 /* Applicable only on the targets that has external modem.
3174 * New device information should be sent to modem before enabling
3175 * the devices to reduce in-call device switch time.
3176 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07003177 if ((usecase->type == VOICE_CALL) &&
3178 (usecase->in_snd_device != SND_DEVICE_NONE) &&
3179 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08003180 status = platform_switch_voice_call_enable_device_config(adev->platform,
3181 out_snd_device,
3182 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07003183 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08003184
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003185 /* Enable new sound devices */
3186 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08003187 check_usecases_codec_backend(adev, usecase, out_snd_device);
Saurav Kumarc1411662020-10-14 10:50:45 +05303188 check_and_configure_headphone(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05303189 if (platform_check_codec_asrc_support(adev->platform))
3190 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003191 enable_snd_device(adev, out_snd_device);
Zhou Songd9bd9302020-08-04 16:34:45 +08003192 /* Enable haptics device for haptic usecase */
3193 if (usecase->id == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
3194 enable_snd_device(adev, SND_DEVICE_OUT_HAPTICS);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003195 }
3196
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07003197 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303198 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003199 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07003200 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003201
Lakshman Chaluvarajuab7e5572020-10-28 19:29:23 +05303202 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL)
Eric Laurentb23d5282013-05-14 15:27:20 -07003203 status = platform_switch_voice_call_device_post(adev->platform,
3204 out_snd_device,
3205 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08003206
sangwoo170731f2013-06-08 15:36:36 +09003207 usecase->in_snd_device = in_snd_device;
3208 usecase->out_snd_device = out_snd_device;
3209
Dhananjay Kumard6d32152016-10-13 16:11:03 +05303210 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
3211 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05303212 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003213 if ((24 == usecase->stream.out->bit_width) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003214 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_SPEAKER)) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003215 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3216 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
3217 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
3218 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
3219 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
3220 /*
3221 * To best utlize DSP, check if the stream sample rate is supported/multiple of
3222 * configured device sample rate, if not update the COPP rate to be equal to the
3223 * device sample rate, else open COPP at stream sample rate
3224 */
3225 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
3226 usecase->stream.out->sample_rate,
3227 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05303228 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
Preetam Singh Ranawat590d0432019-09-30 14:39:47 +05303229 out_snd_device != SND_DEVICE_OUT_HEADPHONES &&
3230 out_snd_device != SND_DEVICE_OUT_HEADPHONES_HIFI_FILTER &&
Ashish Jain4826f6c2017-02-06 13:33:20 +05303231 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003232 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
3233 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +05303234 if (!(compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS) && ((usecase->stream.out->flags &
3235 (audio_output_flags_t)AUDIO_OUTPUT_FLAG_SYS_NOTIFICATION) || (usecase->stream.out->flags &
3236 (audio_output_flags_t)AUDIO_OUTPUT_FLAG_PHONE)))) {
3237 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3238 }
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003239 }
Weiyin Jiangcdece202019-07-08 16:13:16 +08003240 }
3241 enable_audio_route(adev, usecase);
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003242
Shalini Manjunatha5e610912020-12-29 13:02:25 +05303243 if (uc_id == USECASE_AUDIO_PLAYBACK_VOIP) {
3244 struct stream_in *voip_in = get_voice_communication_input(adev);
3245 struct audio_usecase *voip_in_usecase = NULL;
3246 voip_in_usecase = get_usecase_from_list(adev, USECASE_AUDIO_RECORD_VOIP);
3247 if (voip_in != NULL &&
3248 voip_in_usecase != NULL &&
3249 !(out_snd_device == AUDIO_DEVICE_OUT_SPEAKER ||
3250 out_snd_device == AUDIO_DEVICE_OUT_SPEAKER_SAFE) &&
3251 (voip_in_usecase->in_snd_device ==
3252 platform_get_input_snd_device(adev->platform, voip_in,
3253 &usecase->stream.out->device_list,usecase->type))) {
3254 /*
3255 * if VOIP TX is enabled before VOIP RX, needs to re-route the TX path
3256 * for enabling echo-reference-voip with correct port
3257 */
3258 ALOGD("%s: VOIP TX is enabled before VOIP RX,needs to re-route the TX path",__func__);
3259 disable_audio_route(adev, voip_in_usecase);
3260 disable_snd_device(adev, voip_in_usecase->in_snd_device);
3261 enable_snd_device(adev, voip_in_usecase->in_snd_device);
3262 enable_audio_route(adev, voip_in_usecase);
3263 }
3264 }
Ramjee Singhcdf67af2021-09-29 14:20:27 +05303265 if (voice_extn_compress_voip_is_active(adev)) {
3266 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
3267 USECASE_COMPRESS_VOIP_CALL);
3268 /*
3269 * If only compress voip input is opened voip out will be primary out.
3270 * Need to consider re-routing to select correct i/p pair
3271 */
3272 if ((voip_usecase != NULL) &&
3273 (usecase->type == PCM_PLAYBACK) &&
3274 (usecase->stream.out == voip_usecase->stream.out)) {
3275 in_snd_device = platform_get_input_snd_device(adev->platform,
3276 NULL,
3277 &usecase->stream.out->device_list,
3278 usecase->type);
3279 if (voip_usecase->in_snd_device != in_snd_device ) {
3280 ALOGD("%s:Re routing compress voip tx snd device matching voip rx pair",
3281 __func__);
3282 disable_audio_route(adev, voip_usecase);
3283 disable_snd_device(adev, voip_usecase->in_snd_device);
3284 voip_usecase->in_snd_device = in_snd_device;
3285 voip_usecase->out_snd_device = usecase->out_snd_device;
3286 /* Route all TX usecase to Compress voip BE */
3287 check_usecases_capture_codec_backend(adev, voip_usecase, in_snd_device);
3288 enable_snd_device(adev, in_snd_device);
3289 /* Send Voice related calibration for RX /TX pair */
3290 status = platform_switch_voice_call_device_post(adev->platform,
3291 out_snd_device,
3292 in_snd_device);
3293 enable_audio_route(adev, voip_usecase);
3294 }
3295 }
3296 }
Shalini Manjunatha5e610912020-12-29 13:02:25 +05303297
3298
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08003299 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08003300
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003301 /* If input stream is already running then effect needs to be
3302 applied on the new input device that's being enabled here. */
Eric Laurent637e2d42018-11-15 12:24:31 -08003303 if (in_snd_device != SND_DEVICE_NONE)
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003304 check_and_enable_effect(adev);
3305
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003306 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003307 /* Enable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303308 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003309 voice_check_and_update_aanc_path(adev, out_snd_device, true);
3310
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003311 /* Enable sidetone only if other voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303312 if (voice_is_call_state_active_in_call(adev) ||
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003313 voice_extn_compress_voip_is_started(adev))
3314 voice_set_sidetone(adev, out_snd_device, true);
3315 }
3316
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003317 /* Applicable only on the targets that has external modem.
3318 * Enable device command should be sent to modem only after
3319 * enabling voice call mixer controls
3320 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07003321 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003322 status = platform_switch_voice_call_usecase_route_post(adev->platform,
3323 out_snd_device,
3324 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303325
3326 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003327 struct stream_in *in = adev_get_active_input(adev);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303328 if (usecase->type == VOIP_CALL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003329 if (in != NULL && !in->standby) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303330 if (is_bt_soc_on(adev) == false){
3331 ALOGD("BT SCO MIC disconnected while in connection");
Eric Laurent637e2d42018-11-15 12:24:31 -08003332 if (in->pcm != NULL)
3333 pcm_stop(in->pcm);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303334 }
3335 }
3336 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
3337 && usecase->stream.out->started) {
3338 if (is_bt_soc_on(adev) == false) {
3339 ALOGD("BT SCO/A2DP disconnected while in connection");
3340 out_standby_l(&usecase->stream.out->stream.common);
3341 }
3342 }
3343 } else if ((usecase->stream.out != NULL) &&
3344 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05303345 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
3346 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Weiyin Jiang0d373242019-07-25 13:18:17 +08003347 (usecase->type != PCM_CAPTURE) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303348 usecase->stream.out->started) {
3349 if (is_bt_soc_on(adev) == false) {
3350 ALOGD("BT SCO/A2dp disconnected while in connection");
3351 out_standby_l(&usecase->stream.out->stream.common);
3352 }
3353 }
3354 }
3355
Yung Ti Su70cb8242018-06-22 17:38:47 +08003356 if (usecase->type != PCM_CAPTURE && usecase == voip_usecase) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003357 struct stream_out *voip_out = voip_usecase->stream.out;
3358 audio_extn_utils_send_app_type_gain(adev,
3359 voip_out->app_type_cfg.app_type,
3360 &voip_out->app_type_cfg.gain[0]);
3361 }
3362
Ajender Reddyb940b832021-07-07 11:51:42 +05303363 ALOGD("%s: done",__func__);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303364
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003365 return status;
3366}
3367
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003368static int stop_input_stream(struct stream_in *in)
3369{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303370 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003371 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05303372
3373 if (in == NULL) {
3374 ALOGE("%s: stream_in ptr is NULL", __func__);
3375 return -EINVAL;
3376 }
3377
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003378 struct audio_device *adev = in->dev;
Carter Hsu2e429db2019-05-14 18:50:52 +08003379 struct stream_in *priority_in = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003380
Eric Laurent994a6932013-07-17 11:51:42 -07003381 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003382 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003383 uc_info = get_usecase_from_list(adev, in->usecase);
3384 if (uc_info == NULL) {
3385 ALOGE("%s: Could not find the usecase (%d) in the list",
3386 __func__, in->usecase);
3387 return -EINVAL;
3388 }
3389
Carter Hsu2e429db2019-05-14 18:50:52 +08003390 priority_in = get_priority_input(adev);
3391
Derek Chenea197282019-01-07 17:35:01 -08003392 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3393 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003394
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003395 /* Close in-call recording streams */
3396 voice_check_and_stop_incall_rec_usecase(adev, in);
3397
Eric Laurent150dbfe2013-02-27 14:31:02 -08003398 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003399 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003400
3401 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003402 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003403
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003404 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303405 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_PRIMARY);
3406
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003407 list_remove(&uc_info->list);
3408 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003409
Carter Hsu2e429db2019-05-14 18:50:52 +08003410 if (priority_in == in) {
3411 priority_in = get_priority_input(adev);
Sujin Panicker110f7942021-08-26 17:01:22 +05303412 if (priority_in) {
3413 if (is_usb_in_device_type(&priority_in->device_list)) {
3414 if (audio_extn_usb_connected(NULL))
3415 select_devices(adev, priority_in->usecase);
3416 } else {
3417 select_devices(adev, priority_in->usecase);
3418 }
3419 }
Carter Hsu2e429db2019-05-14 18:50:52 +08003420 }
3421
Vatsal Buchac09ae062018-11-14 13:25:08 +05303422 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07003423 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003424 return ret;
3425}
3426
3427int start_input_stream(struct stream_in *in)
3428{
3429 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08003430 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003431 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05303432
3433 if (in == NULL) {
3434 ALOGE("%s: stream_in ptr is NULL", __func__);
3435 return -EINVAL;
3436 }
3437
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003438 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07003439 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07003440 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003441
Mingming Yin2664a5b2015-09-03 10:53:11 -07003442 if (get_usecase_from_list(adev, usecase) == NULL)
3443 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303444 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
3445 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003446
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303447 if (CARD_STATUS_OFFLINE == in->card_status||
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05003448 CARD_STATUS_OFFLINE == adev->card_status ||
3449 POWER_POLICY_STATUS_OFFLINE == adev->in_power_policy) {
3450 ALOGW("in->card_status or adev->card_status or adev->input_power offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303451 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303452 goto error_config;
3453 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303454
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003455 if (is_sco_in_device_type(&in->device_list)) {
Lakshman Chaluvaraju87f53aa2021-02-02 15:50:11 +05303456 if (!adev->bt_sco_on || audio_extn_a2dp_source_is_ready()) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303457 ALOGE("%s: SCO profile is not ready, return error", __func__);
3458 ret = -EIO;
3459 goto error_config;
3460 }
3461 }
3462
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003463 /* Check if source matches incall recording usecase criteria */
3464 ret = voice_check_and_set_incall_rec_usecase(adev, in);
3465 if (ret)
3466 goto error_config;
3467 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07003468 ALOGV("%s: usecase(%d)", __func__, in->usecase);
3469
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303470 if (audio_extn_cin_attached_usecase(in))
3471 audio_extn_cin_acquire_usecase(in);
3472
Mingming Yin2664a5b2015-09-03 10:53:11 -07003473 if (get_usecase_from_list(adev, in->usecase) != NULL) {
3474 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
3475 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Weiyin Jiang38c0e612020-09-10 16:10:51 +08003476 ret = -EINVAL;
3477 goto error_config;
Mingming Yin2664a5b2015-09-03 10:53:11 -07003478 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003479
Eric Laurentb23d5282013-05-14 15:27:20 -07003480 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003481 if (in->pcm_device_id < 0) {
3482 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
3483 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08003484 ret = -EINVAL;
3485 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003486 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003487
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003488 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003489
3490 if (!uc_info) {
3491 ret = -ENOMEM;
3492 goto error_config;
3493 }
3494
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003495 uc_info->id = in->usecase;
3496 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003497 uc_info->stream.in = in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003498 list_init(&uc_info->device_list);
3499 assign_devices(&uc_info->device_list, &in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003500 uc_info->in_snd_device = SND_DEVICE_NONE;
3501 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003502
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003503 list_add_tail(&adev->usecase_list, &uc_info->list);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003504 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303505 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3506 adev->perf_lock_opts,
3507 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003508 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003509
Derek Chenea197282019-01-07 17:35:01 -08003510 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3511 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003512
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05303513 android_atomic_acquire_cas(true, false, &(in->capture_stopped));
3514
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303515 if (audio_extn_cin_attached_usecase(in)) {
Manish Dewangan46e07982018-12-13 18:18:59 +05303516 ret = audio_extn_cin_open_input_stream(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303517 if (ret)
3518 goto error_open;
3519 else
3520 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003521 }
3522
Haynes Mathew George16081042017-05-31 17:16:49 -07003523 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003524 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003525 ALOGE("%s: pcm stream not ready", __func__);
3526 goto error_open;
3527 }
3528 ret = pcm_start(in->pcm);
3529 if (ret < 0) {
3530 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3531 goto error_open;
3532 }
3533 } else {
3534 unsigned int flags = PCM_IN | PCM_MONOTONIC;
3535 unsigned int pcm_open_retry_count = 0;
3536
Zhou Song62ea0282020-03-22 19:53:01 +08003537 if ((in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) ||
3538 (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003539 flags |= PCM_MMAP | PCM_NOIRQ;
3540 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
3541 } else if (in->realtime) {
3542 flags |= PCM_MMAP | PCM_NOIRQ;
3543 }
3544
Garmond Leunge2433c32017-09-28 21:51:22 -07003545 if (audio_extn_ffv_get_stream() == in) {
3546 ALOGD("%s: ffv stream, update pcm config", __func__);
3547 audio_extn_ffv_update_pcm_config(&config);
3548 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003549 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3550 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3551
3552 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003553 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07003554 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07003555 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003556 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303557 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303558 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3559 adev->card_status = CARD_STATUS_OFFLINE;
3560 in->card_status = CARD_STATUS_OFFLINE;
3561 ret = -EIO;
3562 goto error_open;
3563 }
3564
Haynes Mathew George16081042017-05-31 17:16:49 -07003565 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3566 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3567 if (in->pcm != NULL) {
3568 pcm_close(in->pcm);
3569 in->pcm = NULL;
3570 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003571 if (pcm_open_retry_count == 0) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003572 ret = -EIO;
3573 goto error_open;
3574 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003575 pcm_open_retry_count--;
Haynes Mathew George16081042017-05-31 17:16:49 -07003576 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3577 continue;
3578 }
3579 break;
3580 }
3581
3582 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003583 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07003584 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003585 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003586 if (ret < 0) {
3587 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3588 pcm_close(in->pcm);
3589 in->pcm = NULL;
3590 goto error_open;
3591 }
Narsinga Rao Chellaa6e1f702021-10-22 13:57:32 +05303592 if (in->flags == AUDIO_INPUT_FLAG_FAST)
3593 register_in_stream(in);
Haynes Mathew George16081042017-05-31 17:16:49 -07003594 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003595 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07003596 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003597 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003598 if (ret < 0) {
3599 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003600 pcm_close(in->pcm);
3601 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003602 goto error_open;
3603 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003604 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003605 }
3606
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003607 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07003608 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
3609 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003610
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003611 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303612 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
3613
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303614done_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003615 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303616 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Manisha Agarwal4c2402e2020-10-21 12:02:57 +05303617 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303618 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003619 return ret;
3620
3621error_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003622 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303623 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003624 stop_input_stream(in);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003625
Eric Laurentc8400632013-02-14 19:04:54 -08003626error_config:
Weiyin Jiang38c0e612020-09-10 16:10:51 +08003627 if (audio_extn_cin_attached_usecase(in))
3628 audio_extn_cin_close_input_stream(in);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303629 /*
3630 * sleep 50ms to allow sufficient time for kernel
3631 * drivers to recover incases like SSR.
3632 */
3633 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003634 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303635 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003636 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003637}
3638
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003639void lock_input_stream(struct stream_in *in)
3640{
3641 pthread_mutex_lock(&in->pre_lock);
3642 pthread_mutex_lock(&in->lock);
3643 pthread_mutex_unlock(&in->pre_lock);
3644}
3645
3646void lock_output_stream(struct stream_out *out)
3647{
3648 pthread_mutex_lock(&out->pre_lock);
3649 pthread_mutex_lock(&out->lock);
3650 pthread_mutex_unlock(&out->pre_lock);
3651}
3652
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003653/* must be called with out->lock locked */
3654static int send_offload_cmd_l(struct stream_out* out, int command)
3655{
3656 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
3657
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003658 if (!cmd) {
3659 ALOGE("failed to allocate mem for command 0x%x", command);
3660 return -ENOMEM;
3661 }
3662
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003663 ALOGVV("%s %d", __func__, command);
3664
3665 cmd->cmd = command;
3666 list_add_tail(&out->offload_cmd_list, &cmd->node);
3667 pthread_cond_signal(&out->offload_cond);
3668 return 0;
3669}
3670
Gautam Manam14c198b2020-12-24 14:08:04 +05303671/* must be called with out->lock */
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003672static void stop_compressed_output_l(struct stream_out *out)
3673{
Gautam Manam14c198b2020-12-24 14:08:04 +05303674 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003675 out->offload_state = OFFLOAD_STATE_IDLE;
Gautam Manam14c198b2020-12-24 14:08:04 +05303676 pthread_mutex_unlock(&out->latch_lock);
Weiyin Jiang906db3c2021-03-02 13:17:04 +08003677
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003678 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003679 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003680 if (out->compr != NULL) {
3681 compress_stop(out->compr);
3682 while (out->offload_thread_blocked) {
3683 pthread_cond_wait(&out->cond, &out->lock);
3684 }
3685 }
3686}
3687
Varun Balaraje49253e2017-07-06 19:48:56 +05303688bool is_interactive_usecase(audio_usecase_t uc_id)
3689{
3690 unsigned int i;
3691 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
3692 if (uc_id == interactive_usecases[i])
3693 return true;
3694 }
3695 return false;
3696}
3697
3698static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
3699{
3700 audio_usecase_t ret_uc = USECASE_INVALID;
3701 unsigned int intract_uc_index;
3702 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3703
3704 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
3705 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
3706 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
3707 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
3708 ret_uc = interactive_usecases[intract_uc_index];
3709 break;
3710 }
3711 }
3712
3713 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
3714 return ret_uc;
3715}
3716
3717static void free_interactive_usecase(struct audio_device *adev,
3718 audio_usecase_t uc_id)
3719{
3720 unsigned int interact_uc_index;
3721 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3722
3723 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
3724 if (interactive_usecases[interact_uc_index] == uc_id) {
3725 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
3726 break;
3727 }
3728 }
3729 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
3730}
3731
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003732bool is_offload_usecase(audio_usecase_t uc_id)
3733{
3734 unsigned int i;
3735 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
3736 if (uc_id == offload_usecases[i])
3737 return true;
3738 }
3739 return false;
3740}
3741
Dhananjay Kumarac341582017-02-23 23:42:25 +05303742static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003743{
vivek mehta446c3962015-09-14 10:57:35 -07003744 audio_usecase_t ret_uc = USECASE_INVALID;
3745 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003746 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003747 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05303748 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07003749 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
3750 else
3751 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003752
vivek mehta446c3962015-09-14 10:57:35 -07003753 pthread_mutex_lock(&adev->lock);
3754 if (get_usecase_from_list(adev, ret_uc) != NULL)
3755 ret_uc = USECASE_INVALID;
3756 pthread_mutex_unlock(&adev->lock);
3757
3758 return ret_uc;
3759 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003760
3761 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003762 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3763 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3764 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3765 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003766 break;
3767 }
3768 }
vivek mehta446c3962015-09-14 10:57:35 -07003769
3770 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3771 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003772}
3773
3774static void free_offload_usecase(struct audio_device *adev,
3775 audio_usecase_t uc_id)
3776{
vivek mehta446c3962015-09-14 10:57:35 -07003777 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003778 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003779
3780 if (!adev->multi_offload_enable)
3781 return;
3782
3783 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3784 if (offload_usecases[offload_uc_index] == uc_id) {
3785 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003786 break;
3787 }
3788 }
3789 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3790}
3791
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003792static void *offload_thread_loop(void *context)
3793{
3794 struct stream_out *out = (struct stream_out *) context;
3795 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003796 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003797
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003798 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08003799 set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003800 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3801
3802 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003803 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003804 out->offload_state = OFFLOAD_STATE_IDLE;
3805 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003806 for (;;) {
3807 struct offload_cmd *cmd = NULL;
3808 stream_callback_event_t event;
3809 bool send_callback = false;
3810
3811 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3812 __func__, list_empty(&out->offload_cmd_list),
3813 out->offload_state);
3814 if (list_empty(&out->offload_cmd_list)) {
3815 ALOGV("%s SLEEPING", __func__);
3816 pthread_cond_wait(&out->offload_cond, &out->lock);
3817 ALOGV("%s RUNNING", __func__);
3818 continue;
3819 }
3820
3821 item = list_head(&out->offload_cmd_list);
3822 cmd = node_to_item(item, struct offload_cmd, node);
3823 list_remove(item);
3824
3825 ALOGVV("%s STATE %d CMD %d out->compr %p",
3826 __func__, out->offload_state, cmd->cmd, out->compr);
3827
3828 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3829 free(cmd);
3830 break;
3831 }
3832
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003833 // allow OFFLOAD_CMD_ERROR reporting during standby
3834 // this is needed to handle failures during compress_open
3835 // Note however that on a pause timeout, the stream is closed
3836 // and no offload usecase will be active. Therefore this
3837 // special case is needed for compress_open failures alone
3838 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3839 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003840 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003841 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003842 pthread_cond_signal(&out->cond);
3843 continue;
3844 }
3845 out->offload_thread_blocked = true;
3846 pthread_mutex_unlock(&out->lock);
3847 send_callback = false;
3848 switch(cmd->cmd) {
3849 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003850 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003851 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003852 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003853 send_callback = true;
3854 event = STREAM_CBK_EVENT_WRITE_READY;
3855 break;
3856 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003857 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303858 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003859 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303860 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003861 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303862 if (ret < 0)
3863 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303864 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303865 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003866 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003867 else
3868 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003869 if (-ENETRESET != ret && !(-EINTR == ret &&
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05003870 (CARD_STATUS_OFFLINE == out->card_status ||
3871 POWER_POLICY_STATUS_OFFLINE == adev->out_power_policy))) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303872 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303873 pthread_mutex_lock(&out->lock);
3874 out->send_new_metadata = 1;
3875 out->send_next_track_params = true;
3876 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303877 event = STREAM_CBK_EVENT_DRAIN_READY;
3878 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3879 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303880 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003881 break;
3882 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003883 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003884 ret = compress_drain(out->compr);
3885 ALOGD("copl(%p):out of compress_drain", out);
3886 // EINTR check avoids drain interruption due to SSR
3887 if (-ENETRESET != ret && !(-EINTR == ret &&
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05003888 (CARD_STATUS_OFFLINE == out->card_status ||
3889 POWER_POLICY_STATUS_OFFLINE == adev->out_power_policy))) {
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003890 send_callback = true;
3891 event = STREAM_CBK_EVENT_DRAIN_READY;
3892 } else
3893 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003894 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303895 case OFFLOAD_CMD_ERROR:
3896 ALOGD("copl(%p): sending error callback to AF", out);
3897 send_callback = true;
3898 event = STREAM_CBK_EVENT_ERROR;
3899 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003900 default:
3901 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3902 break;
3903 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003904 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003905 out->offload_thread_blocked = false;
3906 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003907 if (send_callback && out->client_callback) {
3908 ALOGVV("%s: sending client_callback event %d", __func__, event);
3909 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003910 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003911 free(cmd);
3912 }
3913
3914 pthread_cond_signal(&out->cond);
3915 while (!list_empty(&out->offload_cmd_list)) {
3916 item = list_head(&out->offload_cmd_list);
3917 list_remove(item);
3918 free(node_to_item(item, struct offload_cmd, node));
3919 }
3920 pthread_mutex_unlock(&out->lock);
3921
3922 return NULL;
3923}
3924
3925static int create_offload_callback_thread(struct stream_out *out)
3926{
3927 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3928 list_init(&out->offload_cmd_list);
3929 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3930 offload_thread_loop, out);
3931 return 0;
3932}
3933
3934static int destroy_offload_callback_thread(struct stream_out *out)
3935{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003936 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003937 stop_compressed_output_l(out);
3938 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3939
3940 pthread_mutex_unlock(&out->lock);
3941 pthread_join(out->offload_thread, (void **) NULL);
3942 pthread_cond_destroy(&out->offload_cond);
3943
3944 return 0;
3945}
3946
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003947static int stop_output_stream(struct stream_out *out)
3948{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303949 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003950 struct audio_usecase *uc_info;
3951 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003952 bool has_voip_usecase =
3953 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003954
Eric Laurent994a6932013-07-17 11:51:42 -07003955 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003956 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003957 uc_info = get_usecase_from_list(adev, out->usecase);
3958 if (uc_info == NULL) {
3959 ALOGE("%s: Could not find the usecase (%d) in the list",
3960 __func__, out->usecase);
3961 return -EINVAL;
3962 }
3963
Zhou Songbaddf9f2020-11-20 13:57:39 +08003964 out->a2dp_muted = false;
3965
Derek Chenea197282019-01-07 17:35:01 -08003966 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3967 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003968
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003969 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303970 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003971 if (adev->visualizer_stop_output != NULL)
3972 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003973
3974 audio_extn_dts_remove_state_notifier_node(out->usecase);
3975
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003976 if (adev->offload_effects_stop_output != NULL)
3977 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07003978 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3979 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3980 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003981 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003982
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003983 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3984 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003985 voice_set_device_mute_flag(adev, false);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003986 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003987
Eric Laurent150dbfe2013-02-27 14:31:02 -08003988 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003989 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003990
3991 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003992 disable_snd_device(adev, uc_info->out_snd_device);
Zhou Songd9bd9302020-08-04 16:34:45 +08003993 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
3994 disable_snd_device(adev, SND_DEVICE_OUT_HAPTICS);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003995
Aalique Grahame22e49102018-12-18 14:23:57 -08003996 audio_extn_extspk_update(adev->extspk);
3997
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003998 if (is_offload_usecase(out->usecase)) {
3999 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
4000 adev->dsp_bit_width_enforce_mode,
4001 false);
4002 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004003 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07004004 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
4005 false);
4006
4007 if (ret != 0)
4008 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
4009 /* default service interval was successfully updated,
4010 reopen USB backend with new service interval */
4011 ret = 0;
4012 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08004013
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004014 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304015 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004016 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304017 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004018 ALOGV("Disable passthrough , reset mixer to pcm");
4019 /* NO_PASSTHROUGH */
Meng Wang4c32fb42020-01-16 17:57:11 +08004020#ifdef AUDIO_GKI_ENABLED
4021 /* out->compr_config.codec->reserved[0] is for compr_passthr */
4022 out->compr_config.codec->reserved[0] = 0;
4023#else
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004024 out->compr_config.codec->compr_passthr = 0;
Meng Wang4c32fb42020-01-16 17:57:11 +08004025#endif
Mingming Yin21854652016-04-13 11:54:02 -07004026 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004027 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
4028 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07004029
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304030 /* Must be called after removing the usecase from list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004031 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL))
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05304032 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304033
Manish Dewangan21a850a2017-08-14 12:03:55 +05304034 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07004035 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
4036 if (ret < 0)
4037 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
4038 }
4039
Zhou Song642ec432020-12-23 16:11:10 +08004040 /* trigger voip input to reroute when voip output changes to hearing aid */
Aalique Grahame22e49102018-12-18 14:23:57 -08004041 if (has_voip_usecase ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004042 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08004043 struct listnode *node;
4044 struct audio_usecase *usecase;
4045 list_for_each(node, &adev->usecase_list) {
4046 usecase = node_to_item(node, struct audio_usecase, list);
Zhou Song642ec432020-12-23 16:11:10 +08004047 if (usecase->type == PCM_PLAYBACK || usecase == uc_info ||
4048 (usecase->type == PCM_CAPTURE &&
Revathi Uddarajud9f23d92020-07-27 10:55:06 +05304049 usecase->id != USECASE_AUDIO_RECORD_VOIP &&
Zhou Song642ec432020-12-23 16:11:10 +08004050 usecase->id != USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY))
Aalique Grahame22e49102018-12-18 14:23:57 -08004051 continue;
4052
4053 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
4054 __func__, usecase->id, use_case_table[usecase->id],
4055 out->usecase, use_case_table[out->usecase]);
4056 select_devices(adev, usecase->id);
4057 }
4058 }
4059
Garmond Leung5fd0b552018-04-17 11:56:12 -07004060 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07004061 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004062 return ret;
4063}
4064
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004065struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
4066 unsigned int flags, unsigned int pcm_open_retry_count,
4067 struct pcm_config *config)
4068{
4069 struct pcm* pcm = NULL;
4070
4071 while (1) {
4072 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
4073 if (pcm == NULL || !pcm_is_ready(pcm)) {
4074 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
4075 if (pcm != NULL) {
4076 pcm_close(pcm);
4077 pcm = NULL;
4078 }
Weiyin Jiang72197252019-10-09 11:49:32 +08004079 if (pcm_open_retry_count == 0)
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004080 return NULL;
4081
Weiyin Jiang72197252019-10-09 11:49:32 +08004082 pcm_open_retry_count--;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004083 usleep(PROXY_OPEN_WAIT_TIME * 1000);
4084 continue;
4085 }
4086 break;
4087 }
4088
4089 if (pcm_is_ready(pcm)) {
4090 int ret = pcm_prepare(pcm);
4091 if (ret < 0) {
4092 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
4093 pcm_close(pcm);
4094 pcm = NULL;
4095 }
4096 }
4097
4098 return pcm;
4099}
4100
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004101int start_output_stream(struct stream_out *out)
4102{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004103 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004104 struct audio_usecase *uc_info;
4105 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004106 char mixer_ctl_name[128];
4107 struct mixer_ctl *ctl = NULL;
4108 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304109 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004110 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004111
Haynes Mathew George380745d2017-10-04 15:27:45 -07004112 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004113 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
4114 ret = -EINVAL;
4115 goto error_config;
4116 }
4117
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004118 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304119 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004120 get_device_types(&out->device_list), is_haptic_usecase);
4121
4122 bool is_speaker_active = compare_device_type(&out->device_list,
4123 AUDIO_DEVICE_OUT_SPEAKER);
4124 bool is_speaker_safe_active = compare_device_type(&out->device_list,
4125 AUDIO_DEVICE_OUT_SPEAKER_SAFE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304126
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304127 if (CARD_STATUS_OFFLINE == out->card_status ||
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05004128 CARD_STATUS_OFFLINE == adev->card_status ||
4129 POWER_POLICY_STATUS_OFFLINE == adev->out_power_policy) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304130 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05304131 ret = -EIO;
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004132 goto error_fatal;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304133 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05304134
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004135 //Update incall music usecase to reflect correct voice session
4136 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
4137 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
4138 if (ret != 0) {
4139 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
4140 __func__, ret);
4141 goto error_config;
4142 }
4143 }
4144
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004145 if (is_a2dp_out_device_type(&out->device_list)) {
Florian Pfister1a84f312018-07-19 14:38:18 +02004146 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004147 if (is_speaker_active || is_speaker_safe_active) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304148 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304149 } else {
Zhou Songd01e7a22020-09-23 22:49:01 +08004150 if (!is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304151 ALOGE("%s: A2DP profile is not ready, return error", __func__);
4152 ret = -EAGAIN;
4153 goto error_config;
4154 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304155 }
4156 }
4157 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004158 if (is_sco_out_device_type(&out->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304159 if (!adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004160 if (is_speaker_active) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304161 //combo usecase just by pass a2dp
4162 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004163 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304164 } else {
4165 ALOGE("%s: SCO profile is not ready, return error", __func__);
4166 ret = -EAGAIN;
4167 goto error_config;
4168 }
4169 }
4170 }
4171
Eric Laurentb23d5282013-05-14 15:27:20 -07004172 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004173 if (out->pcm_device_id < 0) {
4174 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
4175 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004176 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004177 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004178 }
4179
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004180 if (is_haptic_usecase) {
Meng Wang51d8c2a2020-04-27 15:23:21 +08004181 adev->haptic_pcm_device_id = platform_get_pcm_device_id(
4182 USECASE_AUDIO_PLAYBACK_HAPTICS, PCM_PLAYBACK);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004183 if (adev->haptic_pcm_device_id < 0) {
4184 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
4185 __func__, adev->haptic_pcm_device_id, out->usecase);
4186 ret = -EINVAL;
4187 goto error_config;
4188 }
4189 }
4190
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004191 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004192
4193 if (!uc_info) {
4194 ret = -ENOMEM;
4195 goto error_config;
4196 }
4197
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004198 uc_info->id = out->usecase;
4199 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004200 uc_info->stream.out = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004201 list_init(&uc_info->device_list);
4202 assign_devices(&uc_info->device_list, &out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004203 uc_info->in_snd_device = SND_DEVICE_NONE;
4204 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07004205
4206 /* This must be called before adding this usecase to the list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004207 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07004208 audio_extn_usb_check_and_set_svc_int(uc_info, true);
4209 /* USB backend is not reopened immediately.
4210 This is eventually done as part of select_devices */
4211 }
4212
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004213 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004214
Wei Wangf7ca6c92017-11-21 14:51:20 -08004215 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304216 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4217 adev->perf_lock_opts,
4218 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304219
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004220 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05304221 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304222 if (audio_extn_passthru_is_enabled() &&
4223 audio_extn_passthru_is_passthrough_stream(out)) {
4224 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304225 }
4226 }
4227
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004228 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02004229 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304230 if (!a2dp_combo) {
4231 check_a2dp_restore_l(adev, out, false);
4232 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004233 struct listnode dev;
4234 list_init(&dev);
4235 assign_devices(&dev, &out->device_list);
4236 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4237 reassign_device_list(&out->device_list,
4238 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aalique Grahame22e49102018-12-18 14:23:57 -08004239 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004240 reassign_device_list(&out->device_list,
4241 AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304242 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004243 assign_devices(&out->device_list, &dev);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304244 }
4245 } else {
Revathi Uddarajub26e3932020-06-10 14:51:02 +05304246 select_devices(adev, out->usecase);
4247 if (is_a2dp_out_device_type(&out->device_list) &&
4248 !adev->a2dp_started) {
4249 if (is_speaker_active || is_speaker_safe_active) {
4250 struct listnode dev;
4251 list_init(&dev);
4252 assign_devices(&dev, &out->device_list);
4253 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4254 reassign_device_list(&out->device_list,
4255 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
4256 else
4257 reassign_device_list(&out->device_list,
4258 AUDIO_DEVICE_OUT_SPEAKER, "");
4259 select_devices(adev, out->usecase);
4260 assign_devices(&out->device_list, &dev);
4261 } else {
4262 ret = -EINVAL;
4263 goto error_open;
4264 }
4265 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304266 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004267
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004268 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
4269 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07004270 voice_set_device_mute_flag(adev, true);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004271 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07004272
Derek Chenea197282019-01-07 17:35:01 -08004273 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
4274 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08004275
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004276 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
4277 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07004278
4279 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07004280 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07004281 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4282 ALOGE("%s: pcm stream not ready", __func__);
4283 goto error_open;
4284 }
4285 ret = pcm_start(out->pcm);
4286 if (ret < 0) {
4287 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
4288 goto error_open;
4289 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07004290 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07004291 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004292 unsigned int flags = PCM_OUT;
4293 unsigned int pcm_open_retry_count = 0;
4294 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
4295 flags |= PCM_MMAP | PCM_NOIRQ;
4296 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004297 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08004298 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004299 } else
4300 flags |= PCM_MONOTONIC;
4301
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004302 if ((adev->vr_audio_mode_enabled) &&
4303 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
4304 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4305 "PCM_Dev %d Topology", out->pcm_device_id);
4306 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4307 if (!ctl) {
4308 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
4309 __func__, mixer_ctl_name);
4310 } else {
4311 //if success use ULLPP
4312 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
4313 __func__, mixer_ctl_name, out->pcm_device_id);
4314 //There is a still a possibility that some sessions
4315 // that request for FAST|RAW when 3D audio is active
4316 //can go through ULLPP. Ideally we expects apps to
4317 //listen to audio focus and stop concurrent playback
4318 //Also, we will look for mode flag (voice_in_communication)
4319 //before enabling the realtime flag.
4320 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
4321 }
4322 }
4323
Vatsal Bucha3f39f222021-06-29 16:16:55 +05304324 platform_set_stream_channel_map(adev->platform, out->channel_mask,
4325 out->pcm_device_id, -1, &out->channel_map_param.channel_map[0]);
Surendar Karka91fa3682018-07-02 18:12:12 +05304326
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004327 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
4328 flags, pcm_open_retry_count,
4329 &(out->config));
4330 if (out->pcm == NULL) {
4331 ret = -EIO;
4332 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004333 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004334
4335 if (is_haptic_usecase) {
4336 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
4337 adev->haptic_pcm_device_id,
4338 flags, pcm_open_retry_count,
4339 &(adev->haptics_config));
4340 // failure to open haptics pcm shouldnt stop audio,
4341 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07004342
4343 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
4344 ALOGD("%s: enable haptic audio synchronization", __func__);
4345 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
4346 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004347 }
4348
Zhou Song2b8f28f2017-09-11 10:51:38 +08004349 // apply volume for voip playback after path is set up
4350 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
4351 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05304352 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
4353 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304354 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
4355 out->apply_volume = false;
Derek Chenf13dd492018-11-13 14:53:51 -08004356 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
4357 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Krishna Kishor Jha10ad39f2022-02-21 17:02:47 +05304358#ifdef SOFT_VOLUME
4359 out_set_soft_volume_params(&out->stream);
4360#endif
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304361 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004362 } else {
Zhou Song79929fe2020-01-20 17:57:43 +08004363 /*
4364 * set custom channel map if:
4365 * 1. neither mono nor stereo clips i.e. channels > 2 OR
4366 * 2. custom channel map has been set by client
4367 * else default channel map of FC/FR/FL can always be set to DSP
4368 */
4369 if (popcount(out->channel_mask) > 2 || out->channel_map_param.channel_map[0])
4370 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Weiyin Jiang810a80d2021-01-18 16:04:31 +08004371 out->pcm_device_id, -1, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08004372 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
4373 adev->dsp_bit_width_enforce_mode,
4374 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004375 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07004376 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004377 out->compr = compress_open(adev->snd_card,
4378 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004379 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004380 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05304381 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05304382 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
4383 adev->card_status = CARD_STATUS_OFFLINE;
4384 out->card_status = CARD_STATUS_OFFLINE;
4385 ret = -EIO;
4386 goto error_open;
4387 }
4388
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004389 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004390 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004391 compress_close(out->compr);
4392 out->compr = NULL;
4393 ret = -EIO;
4394 goto error_open;
4395 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304396 /* compress_open sends params of the track, so reset the flag here */
4397 out->is_compr_metadata_avail = false;
4398
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004399 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004400 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07004401
Fred Oh3f43e742015-03-04 18:42:34 -08004402 /* Since small bufs uses blocking writes, a write will be blocked
4403 for the default max poll time (20s) in the event of an SSR.
4404 Reduce the poll time to observe and deal with SSR faster.
4405 */
Ashish Jain5106d362016-05-11 19:23:33 +05304406 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08004407 compress_set_max_poll_wait(out->compr, 1000);
4408 }
4409
Manish Dewangan69426c82017-01-30 17:35:36 +05304410 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05304411 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05304412
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004413 audio_extn_dts_create_state_notifier_node(out->usecase);
4414 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4415 popcount(out->channel_mask),
4416 out->playback_started);
4417
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004418#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304419 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004420 audio_extn_dolby_send_ddp_endp_params(adev);
4421#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05304422 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
4423 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004424 if (adev->visualizer_start_output != NULL)
4425 adev->visualizer_start_output(out->handle, out->pcm_device_id);
4426 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05304427 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004428 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004429 }
Derek Chenf13dd492018-11-13 14:53:51 -08004430
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004431 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf13dd492018-11-13 14:53:51 -08004432 /* Update cached volume from media to offload/direct stream */
4433 struct listnode *node = NULL;
4434 list_for_each(node, &adev->active_outputs_list) {
4435 streams_output_ctxt_t *out_ctxt = node_to_item(node,
4436 streams_output_ctxt_t,
4437 list);
4438 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
4439 out->volume_l = out_ctxt->output->volume_l;
4440 out->volume_r = out_ctxt->output->volume_r;
4441 }
4442 }
4443 out_set_compr_volume(&out->stream,
4444 out->volume_l, out->volume_r);
4445 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004446 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004447
4448 if (ret == 0) {
Narsinga Rao Chellaa6e1f702021-10-22 13:57:32 +05304449 if (out->flags == AUDIO_OUTPUT_FLAG_FAST)
4450 register_out_stream(out);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004451 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07004452 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4453 ALOGE("%s: pcm stream not ready", __func__);
4454 goto error_open;
4455 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004456 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004457 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004458 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004459 if (ret < 0)
4460 goto error_open;
4461 }
4462 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004463 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304464 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Jaideep Sharma0fa53812020-09-17 09:00:11 +05304465 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004466
vivek mehtad15d2bf2019-05-17 13:35:10 -07004467 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
4468 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4469 audio_low_latency_hint_start();
4470 }
4471
Manish Dewangan21a850a2017-08-14 12:03:55 +05304472 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07004473 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07004474 if (ret < 0)
4475 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
4476 }
4477
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004478 // consider a scenario where on pause lower layers are tear down.
4479 // so on resume, swap mixer control need to be sent only when
4480 // backend is active, hence rather than sending from enable device
4481 // sending it from start of streamtream
4482
4483 platform_set_swap_channels(adev, true);
4484
Haynes Mathew George380745d2017-10-04 15:27:45 -07004485 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304486 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004487 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004488error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004489 if (adev->haptic_pcm) {
4490 pcm_close(adev->haptic_pcm);
4491 adev->haptic_pcm = NULL;
4492 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004493 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304494 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004495 stop_output_stream(out);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004496error_fatal:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05304497 /*
4498 * sleep 50ms to allow sufficient time for kernel
4499 * drivers to recover incases like SSR.
4500 */
4501 usleep(50000);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004502error_config:
Haynes Mathew George380745d2017-10-04 15:27:45 -07004503 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304504 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004505 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004506}
4507
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004508static int check_input_parameters(uint32_t sample_rate,
4509 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08004510 int channel_count,
4511 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004512{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004513 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004514
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304515 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
4516 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
4517 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07004518 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02004519 !audio_extn_compr_cap_format_supported(format) &&
4520 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004521 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004522
Aalique Grahame22e49102018-12-18 14:23:57 -08004523 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
4524 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
4525 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
4526 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
4527 return -EINVAL;
4528 }
4529
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004530 switch (channel_count) {
4531 case 1:
4532 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304533 case 3:
4534 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004535 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07004536 case 8:
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05304537 case 10:
4538 case 12:
4539 case 14:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004540 break;
4541 default:
4542 ret = -EINVAL;
4543 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004544
4545 switch (sample_rate) {
4546 case 8000:
4547 case 11025:
4548 case 12000:
4549 case 16000:
4550 case 22050:
4551 case 24000:
4552 case 32000:
4553 case 44100:
4554 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004555 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304556 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004557 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304558 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004559 break;
4560 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004561 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004562 }
4563
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004564 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004565}
4566
Naresh Tanniru04f71882018-06-26 17:46:22 +05304567
4568/** Add a value in a list if not already present.
4569 * @return true if value was successfully inserted or already present,
4570 * false if the list is full and does not contain the value.
4571 */
4572static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
4573 for (size_t i = 0; i < list_length; i++) {
4574 if (list[i] == value) return true; // value is already present
4575 if (list[i] == 0) { // no values in this slot
4576 list[i] = value;
4577 return true; // value inserted
4578 }
4579 }
4580 return false; // could not insert value
4581}
4582
4583/** Add channel_mask in supported_channel_masks if not already present.
4584 * @return true if channel_mask was successfully inserted or already present,
4585 * false if supported_channel_masks is full and does not contain channel_mask.
4586 */
4587static void register_channel_mask(audio_channel_mask_t channel_mask,
4588 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
4589 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
4590 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
4591}
4592
4593/** Add format in supported_formats if not already present.
4594 * @return true if format was successfully inserted or already present,
4595 * false if supported_formats is full and does not contain format.
4596 */
4597static void register_format(audio_format_t format,
4598 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
4599 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
4600 "%s: stream can not declare supporting its format %x", __func__, format);
4601}
4602/** Add sample_rate in supported_sample_rates if not already present.
4603 * @return true if sample_rate was successfully inserted or already present,
4604 * false if supported_sample_rates is full and does not contain sample_rate.
4605 */
4606static void register_sample_rate(uint32_t sample_rate,
4607 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
4608 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
4609 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
4610}
4611
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004612static inline uint32_t lcm(uint32_t num1, uint32_t num2)
4613{
4614 uint32_t high = num1, low = num2, temp = 0;
4615
4616 if (!num1 || !num2)
4617 return 0;
4618
4619 if (num1 < num2) {
4620 high = num2;
4621 low = num1;
4622 }
4623
4624 while (low != 0) {
4625 temp = low;
4626 low = high % low;
4627 high = temp;
4628 }
4629 return (num1 * num2)/high;
4630}
4631
4632static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
4633{
4634 uint32_t remainder = 0;
4635
4636 if (!multiplier)
4637 return num;
4638
4639 remainder = num % multiplier;
4640 if (remainder)
4641 num += (multiplier - remainder);
4642
4643 return num;
4644}
4645
Aalique Grahame22e49102018-12-18 14:23:57 -08004646static size_t get_stream_buffer_size(size_t duration_ms,
4647 uint32_t sample_rate,
4648 audio_format_t format,
4649 int channel_count,
4650 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004651{
4652 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004653 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004654
Aalique Grahame22e49102018-12-18 14:23:57 -08004655 size = (sample_rate * duration_ms) / 1000;
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +05304656 if (is_low_latency){
4657 switch(sample_rate) {
4658 case 48000:
4659 size = 240;
4660 break;
4661 case 32000:
4662 size = 160;
4663 break;
4664 case 24000:
4665 size = 120;
4666 break;
4667 case 16000:
4668 size = 80;
4669 break;
4670 case 8000:
4671 size = 40;
4672 break;
4673 default:
4674 size = 240;
4675 }
4676 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304677
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004678 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08004679 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004680
Ralf Herzbd08d632018-09-28 15:50:49 +02004681 /* make sure the size is multiple of 32 bytes and additionally multiple of
4682 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004683 * At 48 kHz mono 16-bit PCM:
4684 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
4685 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004686 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004687 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004688 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07004689
4690 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004691}
4692
Aalique Grahame22e49102018-12-18 14:23:57 -08004693static size_t get_input_buffer_size(uint32_t sample_rate,
4694 audio_format_t format,
4695 int channel_count,
4696 bool is_low_latency)
4697{
4698 /* Don't know if USB HIFI in this context so use true to be conservative */
4699 if (check_input_parameters(sample_rate, format, channel_count,
4700 true /*is_usb_hifi */) != 0)
4701 return 0;
4702
4703 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4704 sample_rate,
4705 format,
4706 channel_count,
4707 is_low_latency);
4708}
4709
Derek Chenf6318be2017-06-12 17:16:24 -04004710size_t get_output_period_size(uint32_t sample_rate,
4711 audio_format_t format,
4712 int channel_count,
4713 int duration /*in millisecs*/)
Ashish Jain058165c2016-09-28 23:18:48 +05304714{
4715 size_t size = 0;
4716 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
4717
4718 if ((duration == 0) || (sample_rate == 0) ||
4719 (bytes_per_sample == 0) || (channel_count == 0)) {
4720 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
4721 bytes_per_sample, channel_count);
4722 return -EINVAL;
4723 }
4724
4725 size = (sample_rate *
4726 duration *
4727 bytes_per_sample *
4728 channel_count) / 1000;
4729 /*
4730 * To have same PCM samples for all channels, the buffer size requires to
4731 * be multiple of (number of channels * bytes per sample)
4732 * For writes to succeed, the buffer must be written at address which is multiple of 32
4733 */
4734 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
4735
4736 return (size/(channel_count * bytes_per_sample));
4737}
4738
Zhou Song48453a02018-01-10 17:50:59 +08004739static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05304740{
4741 uint64_t actual_frames_rendered = 0;
Weiyin Jiang4813da12020-05-28 00:37:28 +08004742 uint64_t written_frames = 0;
4743 uint64_t kernel_frames = 0;
4744 uint64_t dsp_frames = 0;
4745 uint64_t signed_frames = 0;
4746 size_t kernel_buffer_size = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304747
4748 /* This adjustment accounts for buffering after app processor.
4749 * It is based on estimated DSP latency per use case, rather than exact.
4750 */
George Gao9ba8a142020-07-23 14:30:03 -07004751 dsp_frames = platform_render_latency(out) *
Weiyin Jiang4813da12020-05-28 00:37:28 +08004752 out->sample_rate / 1000000LL;
Ashish Jain5106d362016-05-11 19:23:33 +05304753
Zhou Song48453a02018-01-10 17:50:59 +08004754 pthread_mutex_lock(&out->position_query_lock);
Weiyin Jiang4813da12020-05-28 00:37:28 +08004755 written_frames = out->written /
4756 (audio_bytes_per_sample(out->hal_ip_format) * popcount(out->channel_mask));
4757
Ashish Jain5106d362016-05-11 19:23:33 +05304758 /* not querying actual state of buffering in kernel as it would involve an ioctl call
4759 * which then needs protection, this causes delay in TS query for pcm_offload usecase
4760 * hence only estimate.
4761 */
Weiyin Jiang4813da12020-05-28 00:37:28 +08004762 kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
4763 kernel_frames = kernel_buffer_size /
4764 (audio_bytes_per_sample(out->hal_op_format) * popcount(out->channel_mask));
Ashish Jain5106d362016-05-11 19:23:33 +05304765
Weiyin Jiang4813da12020-05-28 00:37:28 +08004766 if (written_frames >= (kernel_frames + dsp_frames))
4767 signed_frames = written_frames - kernel_frames - dsp_frames;
Ashish Jain5106d362016-05-11 19:23:33 +05304768
Zhou Song48453a02018-01-10 17:50:59 +08004769 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05304770 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08004771 if (timestamp != NULL )
4772 *timestamp = out->writeAt;
4773 } else if (timestamp != NULL) {
4774 clock_gettime(CLOCK_MONOTONIC, timestamp);
4775 }
4776 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304777
Weiyin Jiang4813da12020-05-28 00:37:28 +08004778 ALOGVV("%s signed frames %lld written frames %lld kernel frames %lld dsp frames %lld",
4779 __func__, signed_frames, written_frames, kernel_frames, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05304780
4781 return actual_frames_rendered;
4782}
4783
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004784static uint32_t out_get_sample_rate(const struct audio_stream *stream)
4785{
4786 struct stream_out *out = (struct stream_out *)stream;
4787
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004788 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004789}
4790
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004791static int out_set_sample_rate(struct audio_stream *stream __unused,
4792 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004793{
4794 return -ENOSYS;
4795}
4796
4797static size_t out_get_buffer_size(const struct audio_stream *stream)
4798{
4799 struct stream_out *out = (struct stream_out *)stream;
4800
Varun Balaraje49253e2017-07-06 19:48:56 +05304801 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05304802 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05304803 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304804 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4805 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
4806 else
4807 return out->compr_config.fragment_size;
4808 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004809 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304810 else if (is_offload_usecase(out->usecase) &&
4811 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304812 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004813
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004814 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004815 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004816}
4817
4818static uint32_t out_get_channels(const struct audio_stream *stream)
4819{
4820 struct stream_out *out = (struct stream_out *)stream;
4821
4822 return out->channel_mask;
4823}
4824
4825static audio_format_t out_get_format(const struct audio_stream *stream)
4826{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004827 struct stream_out *out = (struct stream_out *)stream;
4828
4829 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004830}
4831
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004832static int out_set_format(struct audio_stream *stream __unused,
4833 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004834{
4835 return -ENOSYS;
4836}
4837
4838static int out_standby(struct audio_stream *stream)
4839{
4840 struct stream_out *out = (struct stream_out *)stream;
4841 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07004842 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004843
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304844 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4845 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004846
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004847 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004848 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004849 if (adev->adm_deregister_stream)
4850 adev->adm_deregister_stream(adev->adm_data, out->handle);
4851
Weiyin Jiang280ea742020-09-08 20:28:22 +08004852 if (is_offload_usecase(out->usecase)) {
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004853 stop_compressed_output_l(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08004854 }
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004855
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004856 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004857 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004858 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4859 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304860 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08004861 pthread_mutex_unlock(&adev->lock);
4862 pthread_mutex_unlock(&out->lock);
4863 ALOGD("VOIP output entered standby");
4864 return 0;
4865 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004866 if (out->pcm) {
4867 pcm_close(out->pcm);
4868 out->pcm = NULL;
4869 }
Meng Wanga09da002020-04-20 12:56:04 +08004870 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4871 if (adev->haptic_pcm) {
4872 pcm_close(adev->haptic_pcm);
4873 adev->haptic_pcm = NULL;
4874 }
4875
4876 if (adev->haptic_buffer != NULL) {
4877 free(adev->haptic_buffer);
4878 adev->haptic_buffer = NULL;
4879 adev->haptic_buffer_size = 0;
4880 }
4881 adev->haptic_pcm_device_id = 0;
4882 }
4883
Haynes Mathew George16081042017-05-31 17:16:49 -07004884 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4885 do_stop = out->playback_started;
4886 out->playback_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07004887
4888 if (out->mmap_shared_memory_fd >= 0) {
4889 ALOGV("%s: closing mmap_shared_memory_fd = %d",
4890 __func__, out->mmap_shared_memory_fd);
4891 close(out->mmap_shared_memory_fd);
4892 out->mmap_shared_memory_fd = -1;
4893 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004894 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004895 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004896 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304897 out->send_next_track_params = false;
4898 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004899 out->gapless_mdata.encoder_delay = 0;
4900 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004901 if (out->compr != NULL) {
4902 compress_close(out->compr);
4903 out->compr = NULL;
4904 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004905 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004906 if (do_stop) {
4907 stop_output_stream(out);
4908 }
Lakshman Chaluvaraju06677b42019-06-24 10:04:52 +05304909 // if fm is active route on selected device in UI
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004910 audio_extn_fm_route_on_selected_device(adev, &out->device_list);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004911 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004912 }
4913 pthread_mutex_unlock(&out->lock);
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07004914 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004915 return 0;
4916}
4917
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304918static int out_on_error(struct audio_stream *stream)
4919{
4920 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004921 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304922
4923 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004924 // always send CMD_ERROR for offload streams, this
4925 // is needed e.g. when SSR happens within compress_open
4926 // since the stream is active, offload_callback_thread is also active.
4927 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
4928 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004929 }
4930 pthread_mutex_unlock(&out->lock);
4931
4932 status = out_standby(&out->stream.common);
4933
4934 lock_output_stream(out);
4935 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004936 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304937 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05304938
4939 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
4940 ALOGD("Setting previous card status if offline");
4941 out->prev_card_status_offline = true;
4942 }
4943
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304944 pthread_mutex_unlock(&out->lock);
4945
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004946 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304947}
4948
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304949/*
Weiyin Jiang280ea742020-09-08 20:28:22 +08004950 * standby implementation without locks, assumes that the callee already
4951 * has taken adev and out lock.
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304952 */
4953int out_standby_l(struct audio_stream *stream)
4954{
4955 struct stream_out *out = (struct stream_out *)stream;
4956 struct audio_device *adev = out->dev;
4957
4958 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4959 stream, out->usecase, use_case_table[out->usecase]);
4960
4961 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07004962 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304963 if (adev->adm_deregister_stream)
4964 adev->adm_deregister_stream(adev->adm_data, out->handle);
4965
Weiyin Jiang280ea742020-09-08 20:28:22 +08004966 if (is_offload_usecase(out->usecase)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304967 stop_compressed_output_l(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08004968 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304969
4970 out->standby = true;
4971 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4972 voice_extn_compress_voip_close_output_stream(stream);
4973 out->started = 0;
4974 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07004975 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304976 return 0;
4977 } else if (!is_offload_usecase(out->usecase)) {
4978 if (out->pcm) {
4979 pcm_close(out->pcm);
4980 out->pcm = NULL;
4981 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004982 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4983 if (adev->haptic_pcm) {
4984 pcm_close(adev->haptic_pcm);
4985 adev->haptic_pcm = NULL;
4986 }
4987
4988 if (adev->haptic_buffer != NULL) {
4989 free(adev->haptic_buffer);
4990 adev->haptic_buffer = NULL;
4991 adev->haptic_buffer_size = 0;
4992 }
4993 adev->haptic_pcm_device_id = 0;
4994 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304995 } else {
4996 ALOGD("copl(%p):standby", out);
4997 out->send_next_track_params = false;
4998 out->is_compr_metadata_avail = false;
4999 out->gapless_mdata.encoder_delay = 0;
5000 out->gapless_mdata.encoder_padding = 0;
5001 if (out->compr != NULL) {
5002 compress_close(out->compr);
5003 out->compr = NULL;
5004 }
5005 }
5006 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005007 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305008 }
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07005009 ALOGV("%s: exit", __func__);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305010 return 0;
5011}
5012
Aalique Grahame22e49102018-12-18 14:23:57 -08005013static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005014{
Aalique Grahame22e49102018-12-18 14:23:57 -08005015 struct stream_out *out = (struct stream_out *)stream;
5016
5017 // We try to get the lock for consistency,
5018 // but it isn't necessary for these variables.
5019 // If we're not in standby, we may be blocked on a write.
5020 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
5021 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
5022 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
Dechen Chai22768452021-07-30 09:29:16 +05305023#ifndef LINUX_ENABLED
Andy Hunga1f48fa2019-07-01 18:14:53 -07005024 char buffer[256]; // for statistics formatting
5025 if (!is_offload_usecase(out->usecase)) {
5026 simple_stats_to_string(&out->fifo_underruns, buffer, sizeof(buffer));
5027 dprintf(fd, " Fifo frame underruns: %s\n", buffer);
5028 }
5029
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005030 if (out->start_latency_ms.n > 0) {
5031 simple_stats_to_string(&out->start_latency_ms, buffer, sizeof(buffer));
5032 dprintf(fd, " Start latency ms: %s\n", buffer);
5033 }
Dechen Chai22768452021-07-30 09:29:16 +05305034#endif
Aalique Grahame22e49102018-12-18 14:23:57 -08005035 if (locked) {
5036 pthread_mutex_unlock(&out->lock);
5037 }
5038
Dechen Chai22768452021-07-30 09:29:16 +05305039#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -08005040 // dump error info
5041 (void)error_log_dump(
5042 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Dechen Chai22768452021-07-30 09:29:16 +05305043#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005044 return 0;
5045}
5046
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005047static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
5048{
5049 int ret = 0;
5050 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08005051
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005052 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08005053 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005054 return -EINVAL;
5055 }
5056
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05305057 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08005058
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005059 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
5060 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05305061 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005062 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005063 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
5064 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05305065 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005066 }
5067
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005068 ALOGV("%s new encoder delay %u and padding %u", __func__,
5069 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
5070
5071 return 0;
5072}
5073
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005074static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
5075{
5076 return out == adev->primary_output || out == adev->voice_tx_output;
5077}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005078
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305079// note: this call is safe only if the stream_cb is
5080// removed first in close_output_stream (as is done now).
5081static void out_snd_mon_cb(void * stream, struct str_parms * parms)
5082{
5083 if (!stream || !parms)
5084 return;
5085
5086 struct stream_out *out = (struct stream_out *)stream;
5087 struct audio_device *adev = out->dev;
5088
5089 card_status_t status;
5090 int card;
5091 if (parse_snd_card_status(parms, &card, &status) < 0)
5092 return;
5093
5094 pthread_mutex_lock(&adev->lock);
5095 bool valid_cb = (card == adev->snd_card);
5096 pthread_mutex_unlock(&adev->lock);
5097
5098 if (!valid_cb)
5099 return;
5100
5101 lock_output_stream(out);
5102 if (out->card_status != status)
5103 out->card_status = status;
5104 pthread_mutex_unlock(&out->lock);
5105
5106 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
5107 use_case_table[out->usecase],
5108 status == CARD_STATUS_OFFLINE ? "offline" : "online");
5109
Aditya Bavanari59ebed42019-02-05 17:44:57 +05305110 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305111 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05305112 if (voice_is_call_state_active(adev) &&
5113 out == adev->primary_output) {
5114 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
5115 pthread_mutex_lock(&adev->lock);
5116 voice_stop_call(adev);
5117 adev->mode = AUDIO_MODE_NORMAL;
5118 pthread_mutex_unlock(&adev->lock);
5119 }
5120 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305121 return;
5122}
5123
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005124int route_output_stream(struct stream_out *out,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005125 struct listnode *devices)
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005126{
5127 struct audio_device *adev = out->dev;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005128 int ret = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005129 struct listnode new_devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005130 bool bypass_a2dp = false;
5131 bool reconfig = false;
5132 unsigned long service_interval = 0;
5133
5134 ALOGD("%s: enter: usecase(%d: %s) devices %x",
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005135 __func__, out->usecase, use_case_table[out->usecase], get_device_types(devices));
5136
5137 list_init(&new_devices);
5138 assign_devices(&new_devices, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005139
5140 lock_output_stream(out);
5141 pthread_mutex_lock(&adev->lock);
5142
5143 /*
5144 * When HDMI cable is unplugged the music playback is paused and
5145 * the policy manager sends routing=0. But the audioflinger continues
5146 * to write data until standby time (3sec). As the HDMI core is
5147 * turned off, the write gets blocked.
5148 * Avoid this by routing audio to speaker until standby.
5149 */
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08005150 if (is_single_device_type_equal(&out->device_list,
5151 AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005152 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005153 !audio_extn_passthru_is_passthrough_stream(out) &&
5154 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005155 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005156 }
5157 /*
5158 * When A2DP is disconnected the
5159 * music playback is paused and the policy manager sends routing=0
5160 * But the audioflinger continues to write data until standby time
5161 * (3sec). As BT is turned off, the write gets blocked.
5162 * Avoid this by routing audio to speaker until standby.
5163 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005164 if (is_a2dp_out_device_type(&out->device_list) &&
5165 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005166 !audio_extn_a2dp_source_is_ready() &&
5167 !adev->bt_sco_on) {
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 /*
Weiyin Jiangabedea32020-12-09 12:49:19 +08005171 * When USB headset is disconnected the music playback paused
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005172 * and the policy manager send routing=0. But if the USB is connected
5173 * back before the standby time, AFE is not closed and opened
5174 * when USB is connected back. So routing to speker will guarantee
5175 * AFE reconfiguration and AFE will be opend once USB is connected again
5176 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005177 if (is_usb_out_device_type(&out->device_list) &&
5178 list_empty(&new_devices) &&
5179 !audio_extn_usb_connected(NULL)) {
Sujin Panicker84d953a2020-11-16 17:39:54 +05305180 if (adev->mode == AUDIO_MODE_IN_CALL || adev->mode == AUDIO_MODE_IN_COMMUNICATION)
5181 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_EARPIECE, "");
5182 else
5183 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005184 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005185 /* To avoid a2dp to sco overlapping / BT device improper state
5186 * check with BT lib about a2dp streaming support before routing
5187 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005188 if (is_a2dp_out_device_type(&new_devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005189 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005190 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER) ||
5191 compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005192 //combo usecase just by pass a2dp
5193 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
5194 bypass_a2dp = true;
5195 } else {
5196 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
5197 /* update device to a2dp and don't route as BT returned error
5198 * However it is still possible a2dp routing called because
5199 * of current active device disconnection (like wired headset)
5200 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005201 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005202 pthread_mutex_unlock(&adev->lock);
5203 pthread_mutex_unlock(&out->lock);
5204 goto error;
5205 }
5206 }
5207 }
5208
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005209 // Workaround: If routing to an non existing usb device, fail gracefully
5210 // The routing request will otherwise block during 10 second
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005211 if (is_usb_out_device_type(&new_devices)) {
5212 struct str_parms *parms =
5213 str_parms_create_str(get_usb_device_address(&new_devices));
5214 if (!parms)
5215 goto error;
Weiyin Jiangabedea32020-12-09 12:49:19 +08005216 if (!audio_extn_usb_connected(NULL)) {
5217 ALOGW("%s: ignoring rerouting to non existing USB card", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005218 pthread_mutex_unlock(&adev->lock);
5219 pthread_mutex_unlock(&out->lock);
5220 str_parms_destroy(parms);
5221 ret = -ENOSYS;
5222 goto error;
5223 }
5224 str_parms_destroy(parms);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005225 }
5226
Weiyin Jiang80c8f9a2020-01-10 20:42:08 +08005227 // Workaround: If routing to an non existing hdmi device, fail gracefully
5228 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
5229 (platform_get_edid_info_v2(adev->platform,
5230 out->extconn.cs.controller,
5231 out->extconn.cs.stream) != 0)) {
5232 ALOGW("out_set_parameters() ignoring rerouting to non existing HDMI/DP");
5233 pthread_mutex_unlock(&adev->lock);
5234 pthread_mutex_unlock(&out->lock);
5235 ret = -ENOSYS;
5236 goto error;
5237 }
5238
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005239 /*
5240 * select_devices() call below switches all the usecases on the same
5241 * backend to the new device. Refer to check_usecases_codec_backend() in
5242 * the select_devices(). But how do we undo this?
5243 *
5244 * For example, music playback is active on headset (deep-buffer usecase)
5245 * and if we go to ringtones and select a ringtone, low-latency usecase
5246 * will be started on headset+speaker. As we can't enable headset+speaker
5247 * and headset devices at the same time, select_devices() switches the music
5248 * playback to headset+speaker while starting low-lateny usecase for ringtone.
5249 * So when the ringtone playback is completed, how do we undo the same?
5250 *
5251 * We are relying on the out_set_parameters() call on deep-buffer output,
5252 * once the ringtone playback is ended.
5253 * NOTE: We should not check if the current devices are same as new devices.
5254 * Because select_devices() must be called to switch back the music
5255 * playback to headset.
5256 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005257 if (!list_empty(&new_devices)) {
5258 bool same_dev = compare_devices(&out->device_list, &new_devices);
5259 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005260
5261 if (output_drives_call(adev, out)) {
5262 if (!voice_is_call_state_active(adev)) {
5263 if (adev->mode == AUDIO_MODE_IN_CALL) {
5264 adev->current_call_output = out;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005265 ret = voice_start_call(adev);
5266 }
5267 } else {
Kunlei Zhang253ad102020-10-14 16:21:28 +08005268 platform_is_volume_boost_supported_device(adev->platform, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005269 adev->current_call_output = out;
5270 voice_update_devices_for_all_voice_usecases(adev);
5271 }
5272 }
5273
Mingshu Pang971ff702020-09-09 15:28:22 +08005274 if (is_usb_out_device_type(&out->device_list)) {
5275 service_interval = audio_extn_usb_find_service_interval(false, true /*playback*/);
5276 audio_extn_usb_set_service_interval(true /*playback*/,
5277 service_interval,
5278 &reconfig);
5279 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
5280 }
5281
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005282 if (!out->standby) {
5283 if (!same_dev) {
5284 ALOGV("update routing change");
5285 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
5286 adev->perf_lock_opts,
5287 adev->perf_lock_opts_size);
5288 if (adev->adm_on_routing_change)
5289 adev->adm_on_routing_change(adev->adm_data,
5290 out->handle);
5291 }
5292 if (!bypass_a2dp) {
5293 select_devices(adev, out->usecase);
5294 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005295 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
5296 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005297 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005298 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005299 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005300 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005301 }
5302
5303 if (!same_dev) {
5304 // on device switch force swap, lower functions will make sure
5305 // to check if swap is allowed or not.
5306 platform_set_swap_channels(adev, true);
5307 audio_extn_perf_lock_release(&adev->perf_lock_handle);
5308 }
Zhou Songbaddf9f2020-11-20 13:57:39 +08005309 pthread_mutex_lock(&out->latch_lock);
5310 if (!is_a2dp_out_device_type(&out->device_list) || audio_extn_a2dp_source_is_ready()) {
5311 if (out->a2dp_muted) {
5312 out->a2dp_muted = false;
5313 if (is_offload_usecase(out->usecase))
5314 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5315 else if (out->usecase != USECASE_AUDIO_PLAYBACK_VOIP)
5316 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Weiyin Jiang280ea742020-09-08 20:28:22 +08005317 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005318 }
Zhou Songbaddf9f2020-11-20 13:57:39 +08005319 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP && !out->a2dp_muted)
5320 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
5321 pthread_mutex_unlock(&out->latch_lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005322 }
5323 }
5324
5325 pthread_mutex_unlock(&adev->lock);
5326 pthread_mutex_unlock(&out->lock);
5327
5328 /*handles device and call state changes*/
5329 audio_extn_extspk_update(adev->extspk);
5330
Revathi Uddaraju4255a632021-12-02 05:11:13 -08005331 clear_devices(&new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005332error:
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005333 ALOGV("%s: exit: code(%d)", __func__, ret);
5334 return ret;
5335}
5336
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005337static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
5338{
5339 struct stream_out *out = (struct stream_out *)stream;
5340 struct audio_device *adev = out->dev;
5341 struct str_parms *parms;
5342 char value[32];
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005343 int ret = 0, err;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005344 int ext_controller = -1;
5345 int ext_stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005346
sangwoobc677242013-08-08 16:53:43 +09005347 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005348 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005349 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305350 if (!parms)
5351 goto error;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005352
5353 err = platform_get_controller_stream_from_params(parms, &ext_controller,
5354 &ext_stream);
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08005355 if (err == 0) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005356 out->extconn.cs.controller = ext_controller;
5357 out->extconn.cs.stream = ext_stream;
5358 ALOGD("%s: usecase(%s) new controller/stream (%d/%d)", __func__,
5359 use_case_table[out->usecase], out->extconn.cs.controller,
5360 out->extconn.cs.stream);
5361 }
5362
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005363 if (out == adev->primary_output) {
5364 pthread_mutex_lock(&adev->lock);
5365 audio_extn_set_parameters(adev, parms);
5366 pthread_mutex_unlock(&adev->lock);
5367 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005368 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005369 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005370 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005371
5372 audio_extn_dts_create_state_notifier_node(out->usecase);
5373 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5374 popcount(out->channel_mask),
5375 out->playback_started);
5376
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08005377 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005378 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005379
Surendar Karkaf51b5842018-04-26 11:28:38 +05305380 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
5381 sizeof(value));
5382 if (err >= 0) {
5383 if (!strncmp("true", value, sizeof("true")) || atoi(value))
5384 audio_extn_send_dual_mono_mixing_coefficients(out);
5385 }
5386
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305387 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5388 if (err >= 0) {
5389 strlcpy(out->profile, value, sizeof(out->profile));
5390 ALOGV("updating stream profile with value '%s'", out->profile);
5391 lock_output_stream(out);
5392 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
5393 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005394 &out->device_list, out->flags,
5395 out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305396 out->sample_rate, out->bit_width,
5397 out->channel_mask, out->profile,
5398 &out->app_type_cfg);
5399 pthread_mutex_unlock(&out->lock);
5400 }
5401
Alexy Joseph98988832017-01-13 14:56:59 -08005402 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005403 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
5404 // and vendor.audio.hal.output.suspend.supported is set to true
5405 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08005406 //check suspend parameter only for low latency and if the property
5407 //is enabled
5408 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
5409 ALOGI("%s: got suspend_playback %s", __func__, value);
5410 lock_output_stream(out);
5411 if (!strncmp(value, "false", 5)) {
5412 //suspend_playback=false is supposed to set QOS value back to 75%
5413 //the mixer control sent with value Enable will achieve that
5414 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5415 } else if (!strncmp (value, "true", 4)) {
5416 //suspend_playback=true is supposed to remove QOS value
5417 //resetting the mixer control will set the default value
5418 //for the mixer control which is Disable and this removes the QOS vote
5419 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5420 } else {
5421 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
5422 " got %s", __func__, value);
5423 ret = -1;
5424 }
5425
5426 if (ret != 0) {
5427 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
5428 __func__, out->pm_qos_mixer_path, ret);
5429 }
5430
5431 pthread_mutex_unlock(&out->lock);
5432 }
5433 }
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005434
Alexy Joseph98988832017-01-13 14:56:59 -08005435 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005436 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305437error:
Eric Laurent994a6932013-07-17 11:51:42 -07005438 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005439 return ret;
5440}
5441
Paul McLeana50b7332018-12-17 08:24:21 -07005442static int in_set_microphone_direction(const struct audio_stream_in *stream,
5443 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07005444 struct stream_in *in = (struct stream_in *)stream;
5445
5446 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
5447
5448 in->direction = dir;
5449
5450 if (in->standby)
5451 return 0;
5452
5453 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07005454}
5455
5456static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07005457 struct stream_in *in = (struct stream_in *)stream;
5458
5459 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
5460
5461 if (zoom > 1.0 || zoom < -1.0)
5462 return -EINVAL;
5463
5464 in->zoom = zoom;
5465
5466 if (in->standby)
5467 return 0;
5468
5469 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07005470}
5471
5472
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005473static bool stream_get_parameter_channels(struct str_parms *query,
5474 struct str_parms *reply,
5475 audio_channel_mask_t *supported_channel_masks) {
5476 int ret = -1;
5477 char value[512];
5478 bool first = true;
5479 size_t i, j;
5480
5481 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
5482 ret = 0;
5483 value[0] = '\0';
5484 i = 0;
5485 while (supported_channel_masks[i] != 0) {
5486 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5487 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
5488 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305489 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005490
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305491 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005492 first = false;
5493 break;
5494 }
5495 }
5496 i++;
5497 }
5498 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5499 }
5500 return ret == 0;
5501}
5502
5503static bool stream_get_parameter_formats(struct str_parms *query,
5504 struct str_parms *reply,
5505 audio_format_t *supported_formats) {
5506 int ret = -1;
5507 char value[256];
5508 size_t i, j;
5509 bool first = true;
5510
5511 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
5512 ret = 0;
5513 value[0] = '\0';
5514 i = 0;
5515 while (supported_formats[i] != 0) {
5516 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5517 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
5518 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305519 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005520 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305521 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005522 first = false;
5523 break;
5524 }
5525 }
5526 i++;
5527 }
5528 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
5529 }
5530 return ret == 0;
5531}
5532
5533static bool stream_get_parameter_rates(struct str_parms *query,
5534 struct str_parms *reply,
5535 uint32_t *supported_sample_rates) {
5536
5537 int i;
5538 char value[256];
5539 int ret = -1;
5540 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
5541 ret = 0;
5542 value[0] = '\0';
5543 i=0;
5544 int cursor = 0;
5545 while (supported_sample_rates[i]) {
5546 int avail = sizeof(value) - cursor;
5547 ret = snprintf(value + cursor, avail, "%s%d",
5548 cursor > 0 ? "|" : "",
5549 supported_sample_rates[i]);
5550 if (ret < 0 || ret >= avail) {
5551 // if cursor is at the last element of the array
5552 // overwrite with \0 is duplicate work as
5553 // snprintf already put a \0 in place.
5554 // else
5555 // we had space to write the '|' at value[cursor]
5556 // (which will be overwritten) or no space to fill
5557 // the first element (=> cursor == 0)
5558 value[cursor] = '\0';
5559 break;
5560 }
5561 cursor += ret;
5562 ++i;
5563 }
5564 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
5565 value);
5566 }
5567 return ret >= 0;
5568}
5569
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005570static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
5571{
5572 struct stream_out *out = (struct stream_out *)stream;
5573 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005574 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005575 char value[256];
5576 struct str_parms *reply = str_parms_create();
5577 size_t i, j;
5578 int ret;
5579 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005580
5581 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005582 if (reply) {
5583 str_parms_destroy(reply);
5584 }
5585 if (query) {
5586 str_parms_destroy(query);
5587 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005588 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
5589 return NULL;
5590 }
5591
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005592 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005593 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
5594 if (ret >= 0) {
5595 value[0] = '\0';
5596 i = 0;
5597 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005598 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5599 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005600 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005601 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005602 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005603 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005604 first = false;
5605 break;
5606 }
5607 }
5608 i++;
5609 }
5610 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5611 str = str_parms_to_str(reply);
5612 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005613 voice_extn_out_get_parameters(out, query, reply);
5614 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005615 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005616
Alexy Joseph62142aa2015-11-16 15:10:34 -08005617
5618 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
5619 if (ret >= 0) {
5620 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05305621 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
5622 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08005623 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305624 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005625 } else {
5626 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05305627 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005628 }
5629 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005630 if (str)
5631 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08005632 str = str_parms_to_str(reply);
5633 }
5634
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005635 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
5636 if (ret >= 0) {
5637 value[0] = '\0';
5638 i = 0;
5639 first = true;
5640 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005641 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5642 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005643 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005644 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005645 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005646 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005647 first = false;
5648 break;
5649 }
5650 }
5651 i++;
5652 }
5653 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005654 if (str)
5655 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005656 str = str_parms_to_str(reply);
5657 }
Mingming Yin3a941d42016-02-17 18:08:05 -08005658
5659 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
5660 if (ret >= 0) {
5661 value[0] = '\0';
5662 i = 0;
5663 first = true;
5664 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005665 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
5666 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005667 if (!first) {
5668 strlcat(value, "|", sizeof(value));
5669 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005670 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08005671 first = false;
5672 break;
5673 }
5674 }
5675 i++;
5676 }
5677 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
5678 if (str)
5679 free(str);
5680 str = str_parms_to_str(reply);
5681 }
5682
Alexy Joseph98988832017-01-13 14:56:59 -08005683 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
5684 //only low latency track supports suspend_resume
5685 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005686 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08005687 if (str)
5688 free(str);
5689 str = str_parms_to_str(reply);
5690 }
5691
5692
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005693 str_parms_destroy(query);
5694 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07005695 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005696 return str;
5697}
5698
5699static uint32_t out_get_latency(const struct audio_stream_out *stream)
5700{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005701 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005702 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08005703 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005704
Alexy Josephaa54c872014-12-03 02:46:47 -08005705 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05305706 lock_output_stream(out);
5707 latency = audio_extn_utils_compress_get_dsp_latency(out);
5708 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005709 } else if ((out->realtime) ||
5710 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005711 // since the buffer won't be filled up faster than realtime,
5712 // return a smaller number
5713 if (out->config.rate)
5714 period_ms = (out->af_period_multiplier * out->config.period_size *
5715 1000) / (out->config.rate);
5716 else
5717 period_ms = 0;
George Gao9ba8a142020-07-23 14:30:03 -07005718 latency = period_ms + platform_render_latency(out) / 1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005719 } else {
5720 latency = (out->config.period_count * out->config.period_size * 1000) /
Mingshu Pangf69a88d2021-04-30 16:14:39 +08005721 (out->config.rate);
pavanisra2d95d82022-02-09 18:55:58 +05305722 if (out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5723 out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY)
Mingshu Pangf69a88d2021-04-30 16:14:39 +08005724 latency += platform_render_latency(out)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005725 }
5726
Zhou Songd2537a02020-06-11 22:04:46 +08005727 if (!out->standby && is_a2dp_out_device_type(&out->device_list))
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08005728 latency += audio_extn_a2dp_get_encoder_latency();
5729
Anish Kumar50ebcbf2014-12-09 04:01:39 +05305730 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08005731 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005732}
5733
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305734static float AmpToDb(float amplification)
5735{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305736 float db = DSD_VOLUME_MIN_DB;
5737 if (amplification > 0) {
5738 db = 20 * log10(amplification);
5739 if(db < DSD_VOLUME_MIN_DB)
5740 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305741 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305742 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305743}
5744
Krishna Kishor Jha10ad39f2022-02-21 17:02:47 +05305745#ifdef SOFT_VOLUME
5746static int out_set_soft_volume_params(struct audio_stream_out *stream)
5747{
5748 struct stream_out *out = (struct stream_out *)stream;
5749 int ret = 0;
5750 char mixer_ctl_name[128];
5751 struct audio_device *adev = out->dev;
5752 struct mixer_ctl *ctl = NULL;
5753 struct soft_step_volume_params *volume_params = NULL;
5754
5755 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5756 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Soft Vol Params", pcm_device_id);
5757 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5758 if (!ctl) {
5759 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5760 return -EINVAL;
5761 }
5762
5763 volume_params =(struct soft_step_volume_params * ) malloc(sizeof(struct soft_step_volume_params));
5764 if (volume_params == NULL){
5765 ALOGE("%s : malloc is failed for volume params", __func__);
5766 return -EINVAL;
5767 } else {
5768 ret = platform_get_soft_step_volume_params(volume_params,out->usecase);
5769 if (ret < 0) {
5770 ALOGE("%s : platform_get_soft_step_volume_params is fialed", __func__);
Karan Naidu28b335a2022-05-18 23:00:08 +05305771 ret = -EINVAL;
5772 goto ERR_EXIT;
Krishna Kishor Jha10ad39f2022-02-21 17:02:47 +05305773 }
5774
5775 }
5776 ret = mixer_ctl_set_array(ctl, volume_params, sizeof(struct soft_step_volume_params)/sizeof(int));
5777 if (ret < 0) {
5778 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
Karan Naidu28b335a2022-05-18 23:00:08 +05305779 ret = -EINVAL;
5780 goto ERR_EXIT;
5781 }
5782
5783 if (volume_params) {
5784 free(volume_params);
Krishna Kishor Jha10ad39f2022-02-21 17:02:47 +05305785 }
5786 return 0;
Karan Naidu28b335a2022-05-18 23:00:08 +05305787
5788ERR_EXIT:
5789 if (volume_params) {
5790 free(volume_params);
5791 }
5792 return ret;
Krishna Kishor Jha10ad39f2022-02-21 17:02:47 +05305793}
5794#endif
5795
Arun Mirpuri5d170872019-03-26 13:21:31 -07005796static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
5797 float right)
5798{
5799 struct stream_out *out = (struct stream_out *)stream;
5800 long volume = 0;
5801 char mixer_ctl_name[128] = "";
5802 struct audio_device *adev = out->dev;
5803 struct mixer_ctl *ctl = NULL;
5804 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5805 PCM_PLAYBACK);
5806
5807 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5808 "Playback %d Volume", pcm_device_id);
5809 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5810 if (!ctl) {
5811 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5812 __func__, mixer_ctl_name);
5813 return -EINVAL;
5814 }
5815 if (left != right)
5816 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
5817 __func__, left, right);
5818 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
5819 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
5820 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
5821 __func__, mixer_ctl_name, volume);
5822 return -EINVAL;
5823 }
5824 return 0;
5825}
5826
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305827static int out_set_compr_volume(struct audio_stream_out *stream, float left,
5828 float right)
5829{
5830 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305831 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305832 char mixer_ctl_name[128];
5833 struct audio_device *adev = out->dev;
5834 struct mixer_ctl *ctl;
5835 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5836 PCM_PLAYBACK);
5837
5838 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5839 "Compress Playback %d Volume", pcm_device_id);
5840 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5841 if (!ctl) {
5842 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5843 __func__, mixer_ctl_name);
5844 return -EINVAL;
5845 }
5846 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
5847 __func__, mixer_ctl_name, left, right);
5848 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
5849 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
5850 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5851
5852 return 0;
5853}
5854
Zhou Song2b8f28f2017-09-11 10:51:38 +08005855static int out_set_voip_volume(struct audio_stream_out *stream, float left,
5856 float right)
5857{
5858 struct stream_out *out = (struct stream_out *)stream;
5859 char mixer_ctl_name[] = "App Type Gain";
5860 struct audio_device *adev = out->dev;
5861 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305862 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08005863
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07005864 if (!is_valid_volume(left, right)) {
5865 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
5866 __func__, left, right);
5867 return -EINVAL;
5868 }
5869
Zhou Song2b8f28f2017-09-11 10:51:38 +08005870 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5871 if (!ctl) {
5872 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5873 __func__, mixer_ctl_name);
5874 return -EINVAL;
5875 }
5876
5877 set_values[0] = 0; //0: Rx Session 1:Tx Session
5878 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305879 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
5880 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005881
5882 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
5883 return 0;
5884}
5885
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305886static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
5887 float right)
5888{
5889 struct stream_out *out = (struct stream_out *)stream;
5890 /* Volume control for pcm playback */
5891 if (left != right) {
5892 return -EINVAL;
5893 } else {
5894 char mixer_ctl_name[128];
5895 struct audio_device *adev = out->dev;
5896 struct mixer_ctl *ctl;
5897 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5898 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
5899 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5900 if (!ctl) {
5901 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5902 return -EINVAL;
5903 }
5904
5905 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
5906 int ret = mixer_ctl_set_value(ctl, 0, volume);
5907 if (ret < 0) {
5908 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
5909 return -EINVAL;
5910 }
5911
5912 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
5913
5914 return 0;
5915 }
5916}
5917
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005918static int out_set_volume(struct audio_stream_out *stream, float left,
5919 float right)
5920{
Eric Laurenta9024de2013-04-04 09:19:12 -07005921 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005922 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305923 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005924
Arun Mirpuri5d170872019-03-26 13:21:31 -07005925 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07005926 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
5927 /* only take left channel into account: the API is for stereo anyway */
5928 out->muted = (left == 0.0f);
5929 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005930 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305931 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005932 /*
5933 * Set mute or umute on HDMI passthrough stream.
5934 * Only take left channel into account.
5935 * Mute is 0 and unmute 1
5936 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305937 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305938 } else if (out->format == AUDIO_FORMAT_DSD){
5939 char mixer_ctl_name[128] = "DSD Volume";
5940 struct audio_device *adev = out->dev;
5941 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5942
5943 if (!ctl) {
5944 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5945 __func__, mixer_ctl_name);
5946 return -EINVAL;
5947 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05305948 volume[0] = (long)(AmpToDb(left));
5949 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305950 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5951 return 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005952 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS) &&
Derek Chendf05eea2019-08-01 13:57:49 -07005953 (out->car_audio_stream == CAR_AUDIO_STREAM_MEDIA)) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005954 ALOGD("%s: Overriding offload set volume for media bus stream", __func__);
5955 struct listnode *node = NULL;
5956 list_for_each(node, &adev->active_outputs_list) {
5957 streams_output_ctxt_t *out_ctxt = node_to_item(node,
5958 streams_output_ctxt_t,
5959 list);
5960 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
5961 out->volume_l = out_ctxt->output->volume_l;
5962 out->volume_r = out_ctxt->output->volume_r;
5963 }
5964 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08005965 pthread_mutex_lock(&out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +08005966 if (!out->a2dp_muted) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005967 ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5968 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08005969 pthread_mutex_unlock(&out->latch_lock);
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005970 return ret;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005971 } else {
Weiyin Jiang280ea742020-09-08 20:28:22 +08005972 pthread_mutex_lock(&out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +08005973 ALOGV("%s: compress mute %d", __func__, out->a2dp_muted);
5974 if (!out->a2dp_muted)
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305975 ret = out_set_compr_volume(stream, left, right);
5976 out->volume_l = left;
5977 out->volume_r = right;
Weiyin Jiang280ea742020-09-08 20:28:22 +08005978 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305979 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005980 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005981 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005982 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
5983 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Songbaddf9f2020-11-20 13:57:39 +08005984 pthread_mutex_lock(&out->latch_lock);
Aalique Grahame22e49102018-12-18 14:23:57 -08005985 if (!out->standby) {
5986 audio_extn_utils_send_app_type_gain(out->dev,
5987 out->app_type_cfg.app_type,
5988 &out->app_type_cfg.gain[0]);
Zhou Songbaddf9f2020-11-20 13:57:39 +08005989 if (!out->a2dp_muted)
5990 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08005991 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08005992 out->volume_l = left;
5993 out->volume_r = right;
Zhou Songbaddf9f2020-11-20 13:57:39 +08005994 pthread_mutex_unlock(&out->latch_lock);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005995 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005996 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5997 ALOGV("%s: MMAP set volume called", __func__);
5998 if (!out->standby)
5999 ret = out_set_mmap_volume(stream, left, right);
6000 out->volume_l = left;
6001 out->volume_r = right;
6002 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05306003 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05306004 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
6005 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Zhou Songbaddf9f2020-11-20 13:57:39 +08006006 pthread_mutex_lock(&out->latch_lock);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05306007 /* Volume control for pcm playback */
Zhou Songbaddf9f2020-11-20 13:57:39 +08006008 if (!out->standby && !out->a2dp_muted)
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05306009 ret = out_set_pcm_volume(stream, left, right);
6010 else
6011 out->apply_volume = true;
6012
6013 out->volume_l = left;
6014 out->volume_r = right;
Zhou Songbaddf9f2020-11-20 13:57:39 +08006015 pthread_mutex_unlock(&out->latch_lock);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05306016 return ret;
Derek Chenf13dd492018-11-13 14:53:51 -08006017 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
6018 ALOGV("%s: bus device set volume called", __func__);
Zhou Songbaddf9f2020-11-20 13:57:39 +08006019 pthread_mutex_lock(&out->latch_lock);
6020 if (!out->standby && !out->a2dp_muted)
Derek Chenf13dd492018-11-13 14:53:51 -08006021 ret = out_set_pcm_volume(stream, left, right);
6022 out->volume_l = left;
6023 out->volume_r = right;
Zhou Songbaddf9f2020-11-20 13:57:39 +08006024 pthread_mutex_unlock(&out->latch_lock);
Derek Chenf13dd492018-11-13 14:53:51 -08006025 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07006026 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006027
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006028 return -ENOSYS;
6029}
6030
Zhou Songc9672822017-08-16 16:01:39 +08006031static void update_frames_written(struct stream_out *out, size_t bytes)
6032{
6033 size_t bpf = 0;
6034
6035 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
6036 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
6037 bpf = 1;
6038 else if (!is_offload_usecase(out->usecase))
6039 bpf = audio_bytes_per_sample(out->format) *
6040 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08006041
6042 pthread_mutex_lock(&out->position_query_lock);
6043 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08006044 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08006045 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
6046 }
6047 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08006048}
6049
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006050int split_and_write_audio_haptic_data(struct stream_out *out,
6051 const void *buffer, size_t bytes_to_write)
6052{
6053 struct audio_device *adev = out->dev;
6054
6055 int ret = 0;
6056 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
6057 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
6058 size_t frame_size = channel_count * bytes_per_sample;
6059 size_t frame_count = bytes_to_write / frame_size;
6060
6061 bool force_haptic_path =
6062 property_get_bool("vendor.audio.test_haptic", false);
6063
6064 // extract Haptics data from Audio buffer
6065 bool alloc_haptic_buffer = false;
6066 int haptic_channel_count = adev->haptics_config.channels;
6067 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
6068 size_t audio_frame_size = frame_size - haptic_frame_size;
6069 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
6070
6071 if (adev->haptic_buffer == NULL) {
6072 alloc_haptic_buffer = true;
6073 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
6074 free(adev->haptic_buffer);
6075 adev->haptic_buffer_size = 0;
6076 alloc_haptic_buffer = true;
6077 }
6078
6079 if (alloc_haptic_buffer) {
6080 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08006081 if(adev->haptic_buffer == NULL) {
6082 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
6083 return -ENOMEM;
6084 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006085 adev->haptic_buffer_size = total_haptic_buffer_size;
6086 }
6087
6088 size_t src_index = 0, aud_index = 0, hap_index = 0;
6089 uint8_t *audio_buffer = (uint8_t *)buffer;
6090 uint8_t *haptic_buffer = adev->haptic_buffer;
6091
6092 // This is required for testing only. This works for stereo data only.
6093 // One channel is fed to audio stream and other to haptic stream for testing.
6094 if (force_haptic_path)
6095 audio_frame_size = haptic_frame_size = bytes_per_sample;
6096
6097 for (size_t i = 0; i < frame_count; i++) {
6098 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
6099 audio_frame_size);
6100 aud_index += audio_frame_size;
6101 src_index += audio_frame_size;
6102
6103 if (adev->haptic_pcm)
6104 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
6105 haptic_frame_size);
6106 hap_index += haptic_frame_size;
6107 src_index += haptic_frame_size;
6108
6109 // This is required for testing only.
6110 // Discard haptic channel data.
6111 if (force_haptic_path)
6112 src_index += haptic_frame_size;
6113 }
6114
6115 // write to audio pipeline
6116 ret = pcm_write(out->pcm, (void *)audio_buffer,
6117 frame_count * audio_frame_size);
6118
6119 // write to haptics pipeline
6120 if (adev->haptic_pcm)
6121 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
6122 frame_count * haptic_frame_size);
6123
6124 return ret;
6125}
6126
Aalique Grahame22e49102018-12-18 14:23:57 -08006127#ifdef NO_AUDIO_OUT
6128static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
6129 const void *buffer __unused, size_t bytes)
6130{
6131 struct stream_out *out = (struct stream_out *)stream;
6132
6133 /* No Output device supported other than BT for playback.
6134 * Sleep for the amount of buffer duration
6135 */
6136 lock_output_stream(out);
6137 usleep(bytes * 1000000 / audio_stream_out_frame_size(
6138 (const struct audio_stream_out *)&out->stream) /
6139 out_get_sample_rate(&out->stream.common));
6140 pthread_mutex_unlock(&out->lock);
6141 return bytes;
6142}
6143#endif
6144
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006145static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
6146 size_t bytes)
6147{
6148 struct stream_out *out = (struct stream_out *)stream;
6149 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07006150 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05306151 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006152 const size_t frame_size = audio_stream_out_frame_size(stream);
6153 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05306154 struct audio_usecase *usecase = NULL;
Meng Wang4c32fb42020-01-16 17:57:11 +08006155 uint32_t compr_passthr = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006156
Haynes Mathew George380745d2017-10-04 15:27:45 -07006157 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006158 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306159
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05006160 if (CARD_STATUS_OFFLINE == out->card_status ||
6161 POWER_POLICY_STATUS_OFFLINE == adev->out_power_policy) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08006162
Dhananjay Kumarac341582017-02-23 23:42:25 +05306163 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306164 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05306165 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
6166 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006167 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05306168 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05306169 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05306170 ALOGD(" %s: sound card is not active/SSR state", __func__);
6171 ret= -EIO;
6172 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306173 }
6174 }
6175
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306176 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05306177 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05306178 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306179 goto exit;
6180 }
6181
Haynes Mathew George16081042017-05-31 17:16:49 -07006182 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
6183 ret = -EINVAL;
6184 goto exit;
6185 }
6186
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006187 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306188 !out->is_iec61937_info_available) {
6189
6190 if (!audio_extn_passthru_is_passthrough_stream(out)) {
6191 out->is_iec61937_info_available = true;
6192 } else if (audio_extn_passthru_is_enabled()) {
6193 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05306194 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05306195
6196 if((out->format == AUDIO_FORMAT_DTS) ||
6197 (out->format == AUDIO_FORMAT_DTS_HD)) {
6198 ret = audio_extn_passthru_update_dts_stream_configuration(out,
6199 buffer, bytes);
6200 if (ret) {
6201 if (ret != -ENOSYS) {
6202 out->is_iec61937_info_available = false;
6203 ALOGD("iec61937 transmission info not yet updated retry");
6204 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306205 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05306206 /* if stream has started and after that there is
6207 * stream config change (iec transmission config)
6208 * then trigger select_device to update backend configuration.
6209 */
6210 out->stream_config_changed = true;
6211 pthread_mutex_lock(&adev->lock);
6212 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306213 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08006214 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306215 ret = -EINVAL;
6216 goto exit;
6217 }
Manish Dewangan671a4202017-08-18 17:30:46 +05306218 pthread_mutex_unlock(&adev->lock);
6219 out->stream_config_changed = false;
6220 out->is_iec61937_info_available = true;
6221 }
6222 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05306223
Meng Wang4c32fb42020-01-16 17:57:11 +08006224#ifdef AUDIO_GKI_ENABLED
6225 /* out->compr_config.codec->reserved[0] is for compr_passthr */
6226 compr_passthr = out->compr_config.codec->reserved[0];
6227#else
6228 compr_passthr = out->compr_config.codec->compr_passthr;
6229#endif
6230
Garmond Leung317cbf12017-09-13 16:20:50 -07006231 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Meng Wang4c32fb42020-01-16 17:57:11 +08006232 (compr_passthr == PASSTHROUGH) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05306233 (out->is_iec61937_info_available == true)) {
6234 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
6235 ret = -EINVAL;
6236 goto exit;
6237 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05306238 }
6239 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306240
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006241 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02006242 (audio_extn_a2dp_source_is_suspended())) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006243 if (!(compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER) ||
6244 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Zhou Songd01e7a22020-09-23 22:49:01 +08006245 if (!is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306246 ret = -EIO;
6247 goto exit;
6248 }
6249 }
6250 }
6251
Weiyin Jiangabedea32020-12-09 12:49:19 +08006252 if (is_usb_out_device_type(&out->device_list) &&
6253 !audio_extn_usb_connected(NULL)) {
6254 ret = -EIO;
6255 goto exit;
6256 }
6257
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006258 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07006259 out->standby = false;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006260 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
6261
Eric Laurent150dbfe2013-02-27 14:31:02 -08006262 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006263 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
6264 ret = voice_extn_compress_voip_start_output_stream(out);
6265 else
6266 ret = start_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006267 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006268 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07006269 out->standby = true;
Weiyin Jiangac2bae82020-07-29 17:23:53 +08006270 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006271 goto exit;
6272 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306273 out->started = 1;
Andy Hunga1f48fa2019-07-01 18:14:53 -07006274 out->last_fifo_valid = false; // we're coming out of standby, last_fifo isn't valid.
Weiyin Jiangac2bae82020-07-29 17:23:53 +08006275
6276 if ((last_known_cal_step != -1) && (adev->platform != NULL)) {
vivek mehtab72d08d2016-04-29 03:16:47 -07006277 ALOGD("%s: retry previous failed cal level set", __func__);
Weiyin Jiangac2bae82020-07-29 17:23:53 +08006278 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05306279 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07006280 }
Weiyin Jiangac2bae82020-07-29 17:23:53 +08006281 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306282
6283 if ((out->is_iec61937_info_available == true) &&
6284 (audio_extn_passthru_is_passthrough_stream(out))&&
6285 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
6286 ret = -EINVAL;
6287 goto exit;
6288 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05306289 if (out->set_dual_mono)
6290 audio_extn_send_dual_mono_mixing_coefficients(out);
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006291
Dechen Chai22768452021-07-30 09:29:16 +05306292#ifndef LINUX_ENABLED
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006293 // log startup time in ms.
6294 simple_stats_log(
6295 &out->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Dechen Chai22768452021-07-30 09:29:16 +05306296#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006297 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006298
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006299 if (adev->is_channel_status_set == false &&
6300 compare_device_type(&out->device_list,
6301 AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Alexy Josephb1379942016-01-29 15:49:38 -08006302 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05306303 adev->is_channel_status_set = true;
6304 }
6305
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05306306 if ((adev->use_old_pspd_mix_ctrl == true) &&
6307 (out->pspd_coeff_sent == false)) {
6308 /*
6309 * Need to resend pspd coefficients after stream started for
6310 * older kernel version as it does not save the coefficients
6311 * and also stream has to be started for coeff to apply.
6312 */
6313 usecase = get_usecase_from_list(adev, out->usecase);
6314 if (usecase != NULL) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05306315 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05306316 out->pspd_coeff_sent = true;
6317 }
6318 }
6319
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006320 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08006321 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006322 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006323 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006324 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
6325 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05306326 if (out->send_next_track_params && out->is_compr_metadata_avail) {
6327 ALOGD("copl(%p):send next track params in gapless", out);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08006328 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05306329 out->send_next_track_params = false;
6330 out->is_compr_metadata_avail = false;
6331 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006332 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05306333 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306334 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006335
Ashish Jain83a6cc22016-06-28 14:34:17 +05306336 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05306337 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05306338 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05306339 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006340 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05306341 return -EINVAL;
6342 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05306343 audio_format_t dst_format = out->hal_op_format;
6344 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306345
Dieter Luecking5d57def2018-09-07 14:23:37 +02006346 /* prevent division-by-zero */
6347 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
6348 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
6349 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
6350 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05306351 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006352 ATRACE_END();
6353 return -EINVAL;
6354 }
6355
Ashish Jainf1eaa582016-05-23 20:54:24 +05306356 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
6357 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
6358
Ashish Jain83a6cc22016-06-28 14:34:17 +05306359 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05306360 dst_format,
6361 buffer,
6362 src_format,
6363 frames);
6364
Ashish Jain83a6cc22016-06-28 14:34:17 +05306365 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05306366 bytes_to_write);
6367
6368 /*Convert written bytes in audio flinger format*/
6369 if (ret > 0)
6370 ret = ((ret * format_to_bitwidth_table[out->format]) /
6371 format_to_bitwidth_table[dst_format]);
6372 }
6373 } else
6374 ret = compress_write(out->compr, buffer, bytes);
6375
Zhou Songc9672822017-08-16 16:01:39 +08006376 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
6377 update_frames_written(out, bytes);
6378
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306379 if (ret < 0)
6380 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08006381 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05306382 /*msg to cb thread only if non blocking write is enabled*/
6383 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05306384 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006385 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05306386 } else if (-ENETRESET == ret) {
6387 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306388 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05306389 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05306390 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006391 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05306392 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006393 }
Ashish Jain5106d362016-05-11 19:23:33 +05306394
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05306395 /* Call compr start only when non-zero bytes of data is there to be rendered */
6396 if (!out->playback_started && ret > 0) {
6397 int status = compress_start(out->compr);
6398 if (status < 0) {
6399 ret = status;
6400 ALOGE("%s: compr start failed with err %d", __func__, errno);
6401 goto exit;
6402 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07006403 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006404 out->playback_started = 1;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006405 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006406 out->offload_state = OFFLOAD_STATE_PLAYING;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006407 pthread_mutex_unlock(&out->latch_lock);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006408
6409 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6410 popcount(out->channel_mask),
6411 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006412 }
6413 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006414 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006415 return ret;
6416 } else {
6417 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006418 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006419 if (out->muted)
6420 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006421 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
6422 __func__, frames, frame_size, bytes_to_write);
6423
Aalique Grahame22e49102018-12-18 14:23:57 -08006424 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07006425 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
6426 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
6427 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006428 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
6429 int16_t *src = (int16_t *)buffer;
6430 int16_t *dst = (int16_t *)buffer;
6431
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006432 LOG_ALWAYS_FATAL_IF(channel_count > 2 ||
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006433 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08006434 "out_write called for %s use case with wrong properties",
6435 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006436
6437 /*
6438 * FIXME: this can be removed once audio flinger mixer supports
6439 * mono output
6440 */
6441
6442 /*
6443 * Code below goes over each frame in the buffer and adds both
6444 * L and R samples and then divides by 2 to convert to mono
6445 */
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006446 if (channel_count == 2) {
6447 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
6448 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
6449 }
6450 bytes_to_write /= 2;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006451 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006452 }
Andy Hunga1f48fa2019-07-01 18:14:53 -07006453
6454 // Note: since out_get_presentation_position() is called alternating with out_write()
6455 // by AudioFlinger, we can check underruns using the prior timestamp read.
6456 // (Alternately we could check if the buffer is empty using pcm_get_htimestamp().
6457 if (out->last_fifo_valid) {
6458 // compute drain to see if there is an underrun.
6459 const int64_t current_ns = systemTime(SYSTEM_TIME_MONOTONIC); // sys call
Dhananjay Kumara4429632020-07-11 02:53:37 +05306460 int64_t time_diff_ns = current_ns - out->last_fifo_time_ns;
6461 int64_t frames_by_time =
6462 ((time_diff_ns > 0) && (time_diff_ns < (INT64_MAX / out->config.rate))) ?
6463 (time_diff_ns * out->config.rate / NANOS_PER_SECOND) : 0;
Andy Hunga1f48fa2019-07-01 18:14:53 -07006464 const int64_t underrun = frames_by_time - out->last_fifo_frames_remaining;
6465
6466 if (underrun > 0) {
Dechen Chai22768452021-07-30 09:29:16 +05306467#ifndef LINUX_ENABLED
Andy Hunga1f48fa2019-07-01 18:14:53 -07006468 simple_stats_log(&out->fifo_underruns, underrun);
Dechen Chai22768452021-07-30 09:29:16 +05306469#endif
Andy Hunga1f48fa2019-07-01 18:14:53 -07006470
6471 ALOGW("%s: underrun(%lld) "
6472 "frames_by_time(%lld) > out->last_fifo_frames_remaining(%lld)",
6473 __func__,
6474 (long long)out->fifo_underruns.n,
6475 (long long)frames_by_time,
6476 (long long)out->last_fifo_frames_remaining);
6477 }
6478 out->last_fifo_valid = false; // we're writing below, mark fifo info as stale.
6479 }
6480
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306481 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006482
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006483 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006484
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006485 if (out->config.rate)
6486 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
6487 out->config.rate;
6488
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006489 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006490 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
6491
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006492 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006493 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006494 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306495 out->convert_buffer != NULL) {
6496
6497 memcpy_by_audio_format(out->convert_buffer,
6498 out->hal_op_format,
6499 buffer,
6500 out->hal_ip_format,
6501 out->config.period_size * out->config.channels);
6502
6503 ret = pcm_write(out->pcm, out->convert_buffer,
6504 (out->config.period_size *
6505 out->config.channels *
6506 format_to_bitwidth_table[out->hal_op_format]));
6507 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05306508 /*
6509 * To avoid underrun in DSP when the application is not pumping
6510 * data at required rate, check for the no. of bytes and ignore
6511 * pcm_write if it is less than actual buffer size.
6512 * It is a work around to a change in compress VOIP driver.
6513 */
6514 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
6515 bytes < (out->config.period_size * out->config.channels *
6516 audio_bytes_per_sample(out->format))) {
6517 size_t voip_buf_size =
6518 out->config.period_size * out->config.channels *
6519 audio_bytes_per_sample(out->format);
6520 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
6521 __func__, bytes, voip_buf_size);
6522 usleep(((uint64_t)voip_buf_size - bytes) *
6523 1000000 / audio_stream_out_frame_size(stream) /
6524 out_get_sample_rate(&out->stream.common));
6525 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006526 } else {
6527 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
6528 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
6529 else
6530 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
6531 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306532 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006533
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006534 release_out_focus(out);
6535
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306536 if (ret < 0)
6537 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08006538 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05306539 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006540 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006541 }
6542
6543exit:
Zhou Songc9672822017-08-16 16:01:39 +08006544 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306545 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306546 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306547 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006548 pthread_mutex_unlock(&out->lock);
6549
6550 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006551 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08006552 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306553 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306554 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306555 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306556 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306557 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306558 out->standby = true;
6559 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306560 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006561 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
6562 /* prevent division-by-zero */
6563 uint32_t stream_size = audio_stream_out_frame_size(stream);
6564 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006565
Dieter Luecking5d57def2018-09-07 14:23:37 +02006566 if ((stream_size == 0) || (srate == 0)) {
6567 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
6568 ATRACE_END();
6569 return -EINVAL;
6570 }
6571 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
6572 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006573 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05306574 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006575 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006576 return ret;
6577 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006578 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07006579 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006580 return bytes;
6581}
6582
6583static int out_get_render_position(const struct audio_stream_out *stream,
6584 uint32_t *dsp_frames)
6585{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006586 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08006587
6588 if (dsp_frames == NULL)
6589 return -EINVAL;
6590
6591 *dsp_frames = 0;
6592 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08006593 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05306594
6595 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
6596 * this operation and adev_close_output_stream(where out gets reset).
6597 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05306598 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006599 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05306600 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006601 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05306602 return 0;
6603 }
6604
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006605 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05306606 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306607 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006608 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306609 if (ret < 0)
6610 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006611 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05306612 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006613 }
Naresh Tanniru80659832014-06-04 18:17:56 +05306614 if (-ENETRESET == ret) {
6615 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306616 out->card_status = CARD_STATUS_OFFLINE;
6617 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306618 } else if(ret < 0) {
6619 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306620 ret = -EINVAL;
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05006621 } else if (out->card_status == CARD_STATUS_OFFLINE ||
6622 adev->out_power_policy == POWER_POLICY_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05306623 /*
6624 * Handle corner case where compress session is closed during SSR
6625 * and timestamp is queried
6626 */
6627 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306628 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306629 } else if (out->prev_card_status_offline) {
6630 ALOGE("ERROR: previously sound card was offline,return error");
6631 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306632 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306633 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006634 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05306635 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306636 pthread_mutex_unlock(&out->lock);
6637 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08006638 } else if (audio_is_linear_pcm(out->format)) {
6639 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006640 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08006641 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006642 } else
6643 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006644}
6645
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006646static int out_add_audio_effect(const struct audio_stream *stream __unused,
6647 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006648{
6649 return 0;
6650}
6651
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006652static int out_remove_audio_effect(const struct audio_stream *stream __unused,
6653 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006654{
6655 return 0;
6656}
6657
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006658static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
6659 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006660{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05306661 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006662}
6663
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006664static int out_get_presentation_position(const struct audio_stream_out *stream,
6665 uint64_t *frames, struct timespec *timestamp)
6666{
6667 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05306668 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07006669 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006670
Ashish Jain5106d362016-05-11 19:23:33 +05306671 /* below piece of code is not guarded against any lock because audioFliner serializes
6672 * this operation and adev_close_output_stream( where out gets reset).
6673 */
6674 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05306675 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006676 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05306677 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
6678 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
6679 return 0;
6680 }
6681
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006682 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006683
Ashish Jain5106d362016-05-11 19:23:33 +05306684 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
6685 ret = compress_get_tstamp(out->compr, &dsp_frames,
6686 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08006687 // Adjustment accounts for A2dp encoder latency with offload usecases
6688 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006689 if (is_a2dp_out_device_type(&out->device_list)) {
yidongh0515e042017-07-06 15:00:34 +08006690 unsigned long offset =
6691 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
6692 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
6693 }
Ashish Jain5106d362016-05-11 19:23:33 +05306694 ALOGVV("%s rendered frames %ld sample_rate %d",
6695 __func__, dsp_frames, out->sample_rate);
6696 *frames = dsp_frames;
6697 if (ret < 0)
6698 ret = -errno;
6699 if (-ENETRESET == ret) {
6700 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306701 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05306702 ret = -EINVAL;
6703 } else
6704 ret = 0;
6705 /* this is the best we can do */
6706 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07006707 } else {
6708 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08006709 unsigned int avail;
6710 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
George Gao62ebc722019-07-29 16:29:44 -07006711 uint64_t signed_frames = 0;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006712 uint64_t frames_temp = 0;
George Gao62ebc722019-07-29 16:29:44 -07006713
Andy Hunga1f48fa2019-07-01 18:14:53 -07006714 if (out->kernel_buffer_size > avail) {
6715 frames_temp = out->last_fifo_frames_remaining = out->kernel_buffer_size - avail;
6716 } else {
6717 ALOGW("%s: avail:%u > kernel_buffer_size:%zu clamping!",
6718 __func__, avail, out->kernel_buffer_size);
6719 avail = out->kernel_buffer_size;
6720 frames_temp = out->last_fifo_frames_remaining = 0;
6721 }
6722 out->last_fifo_valid = true;
6723 out->last_fifo_time_ns = audio_utils_ns_from_timespec(timestamp);
6724
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006725 if (out->written >= frames_temp)
6726 signed_frames = out->written - frames_temp;
George Gao62ebc722019-07-29 16:29:44 -07006727
Andy Hunga1f48fa2019-07-01 18:14:53 -07006728 ALOGVV("%s: frames:%lld avail:%u kernel_buffer_size:%zu",
6729 __func__, (long long)signed_frames, avail, out->kernel_buffer_size);
6730
Weiyin Jiangd4633762018-03-16 12:05:03 +08006731 // This adjustment accounts for buffering after app processor.
6732 // It is based on estimated DSP latency per use case, rather than exact.
George Gao9ba8a142020-07-23 14:30:03 -07006733 frames_temp = platform_render_latency(out) *
Robert Lee58215542019-07-15 20:55:12 +08006734 out->sample_rate / 1000000LL;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006735 if (signed_frames >= frames_temp)
6736 signed_frames -= frames_temp;
Aniket Kumar Lataff613152017-07-18 18:19:21 -07006737
Weiyin Jiangd4633762018-03-16 12:05:03 +08006738 // Adjustment accounts for A2dp encoder latency with non offload usecases
6739 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006740 if (is_a2dp_out_device_type(&out->device_list)) {
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006741 frames_temp = audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000;
6742 if (signed_frames >= frames_temp)
6743 signed_frames -= frames_temp;
Weiyin Jiangd4633762018-03-16 12:05:03 +08006744 }
6745
6746 // It would be unusual for this value to be negative, but check just in case ...
George Gao62ebc722019-07-29 16:29:44 -07006747 *frames = signed_frames;
6748 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006749 }
Eric Laurenta7a33042019-07-10 16:20:22 -07006750 } else if (out->card_status == CARD_STATUS_OFFLINE ||
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05006751 adev->out_power_policy == POWER_POLICY_STATUS_OFFLINE ||
Eric Laurenta7a33042019-07-10 16:20:22 -07006752 // audioflinger still needs position updates when A2DP is suspended
Jasmine Cha5c2517f2019-09-09 11:07:28 +08006753 (is_a2dp_out_device_type(&out->device_list) && audio_extn_a2dp_source_is_suspended())) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306754 *frames = out->written;
6755 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306756 if (is_offload_usecase(out->usecase))
6757 ret = -EINVAL;
6758 else
6759 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006760 }
6761 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006762 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006763 return ret;
6764}
6765
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006766static int out_set_callback(struct audio_stream_out *stream,
6767 stream_callback_t callback, void *cookie)
6768{
6769 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006770 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006771
6772 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006773 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006774 out->client_callback = callback;
6775 out->client_cookie = cookie;
6776 if (out->adsp_hdlr_stream_handle) {
6777 ret = audio_extn_adsp_hdlr_stream_set_callback(
6778 out->adsp_hdlr_stream_handle,
6779 callback,
6780 cookie);
6781 if (ret)
6782 ALOGW("%s:adsp hdlr callback registration failed %d",
6783 __func__, ret);
6784 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006785 pthread_mutex_unlock(&out->lock);
6786 return 0;
6787}
6788
6789static int out_pause(struct audio_stream_out* stream)
6790{
6791 struct stream_out *out = (struct stream_out *)stream;
6792 int status = -ENOSYS;
6793 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006794 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006795 ALOGD("copl(%p):pause compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306796 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006797 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006798 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006799 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306800 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05306801 status = compress_pause(out->compr);
6802
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006803 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006804
Mingming Yin21854652016-04-13 11:54:02 -07006805 if (audio_extn_passthru_is_active()) {
6806 ALOGV("offload use case, pause passthru");
6807 audio_extn_passthru_on_pause(out);
6808 }
6809
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306810 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006811 audio_extn_dts_notify_playback_state(out->usecase, 0,
6812 out->sample_rate, popcount(out->channel_mask),
6813 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006814 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08006815 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006816 pthread_mutex_unlock(&out->lock);
6817 }
6818 return status;
6819}
6820
6821static int out_resume(struct audio_stream_out* stream)
6822{
6823 struct stream_out *out = (struct stream_out *)stream;
6824 int status = -ENOSYS;
6825 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006826 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006827 ALOGD("copl(%p):resume compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306828 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006829 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006830 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006831 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306832 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306833 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07006834 }
6835 if (!status) {
6836 out->offload_state = OFFLOAD_STATE_PLAYING;
6837 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306838 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006839 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6840 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006841 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08006842 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006843 pthread_mutex_unlock(&out->lock);
6844 }
6845 return status;
6846}
6847
6848static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
6849{
6850 struct stream_out *out = (struct stream_out *)stream;
6851 int status = -ENOSYS;
6852 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006853 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006854 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006855 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
6856 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
6857 else
6858 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
6859 pthread_mutex_unlock(&out->lock);
6860 }
6861 return status;
6862}
6863
6864static int out_flush(struct audio_stream_out* stream)
6865{
6866 struct stream_out *out = (struct stream_out *)stream;
6867 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006868 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006869 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006870 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006871 pthread_mutex_lock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006872 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
Gautam Manam14c198b2020-12-24 14:08:04 +05306873 pthread_mutex_unlock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006874 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006875 } else {
6876 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
Gautam Manam14c198b2020-12-24 14:08:04 +05306877 pthread_mutex_unlock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006878 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08006879 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006880 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006881 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006882 return 0;
6883 }
6884 return -ENOSYS;
6885}
6886
Haynes Mathew George16081042017-05-31 17:16:49 -07006887static int out_stop(const struct audio_stream_out* stream)
6888{
6889 struct stream_out *out = (struct stream_out *)stream;
6890 struct audio_device *adev = out->dev;
6891 int ret = -ENOSYS;
6892
6893 ALOGV("%s", __func__);
6894 pthread_mutex_lock(&adev->lock);
6895 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6896 out->playback_started && out->pcm != NULL) {
6897 pcm_stop(out->pcm);
6898 ret = stop_output_stream(out);
6899 out->playback_started = false;
6900 }
6901 pthread_mutex_unlock(&adev->lock);
6902 return ret;
6903}
6904
6905static int out_start(const struct audio_stream_out* stream)
6906{
6907 struct stream_out *out = (struct stream_out *)stream;
6908 struct audio_device *adev = out->dev;
6909 int ret = -ENOSYS;
6910
6911 ALOGV("%s", __func__);
6912 pthread_mutex_lock(&adev->lock);
6913 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6914 !out->playback_started && out->pcm != NULL) {
6915 ret = start_output_stream(out);
6916 if (ret == 0) {
6917 out->playback_started = true;
6918 }
6919 }
6920 pthread_mutex_unlock(&adev->lock);
6921 return ret;
6922}
6923
6924/*
6925 * Modify config->period_count based on min_size_frames
6926 */
6927static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
6928{
6929 int periodCountRequested = (min_size_frames + config->period_size - 1)
6930 / config->period_size;
6931 int periodCount = MMAP_PERIOD_COUNT_MIN;
6932
6933 ALOGV("%s original config.period_size = %d config.period_count = %d",
6934 __func__, config->period_size, config->period_count);
6935
6936 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
6937 periodCount *= 2;
6938 }
6939 config->period_count = periodCount;
6940
6941 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
6942}
6943
Phil Burkfe17efd2019-03-25 10:23:35 -07006944// Read offset for the positional timestamp from a persistent vendor property.
6945// This is to workaround apparent inaccuracies in the timing information that
6946// is used by the AAudio timing model. The inaccuracies can cause glitches.
6947static int64_t get_mmap_out_time_offset() {
6948 const int32_t kDefaultOffsetMicros = 0;
6949 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006950 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07006951 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
6952 return mmap_time_offset_micros * (int64_t)1000;
6953}
6954
Haynes Mathew George16081042017-05-31 17:16:49 -07006955static int out_create_mmap_buffer(const struct audio_stream_out *stream,
6956 int32_t min_size_frames,
6957 struct audio_mmap_buffer_info *info)
6958{
6959 struct stream_out *out = (struct stream_out *)stream;
6960 struct audio_device *adev = out->dev;
6961 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07006962 unsigned int offset1 = 0;
6963 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006964 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006965 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006966 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07006967
Arun Mirpuri5d170872019-03-26 13:21:31 -07006968 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306969 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07006970 pthread_mutex_lock(&adev->lock);
6971
Sharad Sanglec6f32552018-05-04 16:15:38 +05306972 if (CARD_STATUS_OFFLINE == out->card_status ||
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05006973 CARD_STATUS_OFFLINE == adev->card_status ||
6974 POWER_POLICY_STATUS_OFFLINE == adev->out_power_policy) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306975 ALOGW("out->card_status or adev->card_status offline, try again");
6976 ret = -EIO;
6977 goto exit;
6978 }
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306979 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07006980 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
6981 ret = -EINVAL;
6982 goto exit;
6983 }
6984 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
6985 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
6986 ret = -ENOSYS;
6987 goto exit;
6988 }
6989 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
6990 if (out->pcm_device_id < 0) {
6991 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6992 __func__, out->pcm_device_id, out->usecase);
6993 ret = -EINVAL;
6994 goto exit;
6995 }
6996
6997 adjust_mmap_period_count(&out->config, min_size_frames);
6998
Arun Mirpuri5d170872019-03-26 13:21:31 -07006999 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07007000 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
7001 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
7002 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307003 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307004 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7005 out->card_status = CARD_STATUS_OFFLINE;
7006 adev->card_status = CARD_STATUS_OFFLINE;
7007 ret = -EIO;
7008 goto exit;
7009 }
7010
Haynes Mathew George16081042017-05-31 17:16:49 -07007011 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
7012 step = "open";
7013 ret = -ENODEV;
7014 goto exit;
7015 }
7016 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
7017 if (ret < 0) {
7018 step = "begin";
7019 goto exit;
7020 }
juyuchen626833d2019-06-04 16:48:02 +08007021
7022 info->flags = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007023 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07007024 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07007025 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07007026 ret = platform_get_mmap_data_fd(adev->platform,
7027 out->pcm_device_id, 0 /*playback*/,
7028 &info->shared_memory_fd,
7029 &mmap_size);
7030 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07007031 // Fall back to non exclusive mode
7032 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
7033 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07007034 out->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
7035 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, out->mmap_shared_memory_fd);
7036
Arun Mirpuri5d170872019-03-26 13:21:31 -07007037 if (mmap_size < buffer_size) {
7038 step = "mmap";
7039 goto exit;
7040 }
juyuchen626833d2019-06-04 16:48:02 +08007041 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07007042 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007043 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07007044 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07007045
7046 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
7047 if (ret < 0) {
7048 step = "commit";
7049 goto exit;
7050 }
7051
Phil Burkfe17efd2019-03-25 10:23:35 -07007052 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
7053
Haynes Mathew George16081042017-05-31 17:16:49 -07007054 out->standby = false;
7055 ret = 0;
7056
Arun Mirpuri5d170872019-03-26 13:21:31 -07007057 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07007058 __func__, info->shared_memory_address, info->buffer_size_frames);
7059
7060exit:
7061 if (ret != 0) {
7062 if (out->pcm == NULL) {
7063 ALOGE("%s: %s - %d", __func__, step, ret);
7064 } else {
7065 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
7066 pcm_close(out->pcm);
7067 out->pcm = NULL;
7068 }
7069 }
7070 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05307071 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07007072 return ret;
7073}
7074
7075static int out_get_mmap_position(const struct audio_stream_out *stream,
7076 struct audio_mmap_position *position)
7077{
7078 struct stream_out *out = (struct stream_out *)stream;
7079 ALOGVV("%s", __func__);
7080 if (position == NULL) {
7081 return -EINVAL;
7082 }
7083 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08007084 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07007085 return -ENOSYS;
7086 }
7087 if (out->pcm == NULL) {
7088 return -ENOSYS;
7089 }
7090
7091 struct timespec ts = { 0, 0 };
7092 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
7093 if (ret < 0) {
7094 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
7095 return ret;
7096 }
Phil Burkfe17efd2019-03-25 10:23:35 -07007097 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7098 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07007099 return 0;
7100}
7101
7102
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007103/** audio_stream_in implementation **/
7104static uint32_t in_get_sample_rate(const struct audio_stream *stream)
7105{
7106 struct stream_in *in = (struct stream_in *)stream;
7107
7108 return in->config.rate;
7109}
7110
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007111static int in_set_sample_rate(struct audio_stream *stream __unused,
7112 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007113{
7114 return -ENOSYS;
7115}
7116
7117static size_t in_get_buffer_size(const struct audio_stream *stream)
7118{
7119 struct stream_in *in = (struct stream_in *)stream;
7120
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007121 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
7122 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07007123 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
7124 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307125 else if(audio_extn_cin_attached_usecase(in))
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307126 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007127
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007128 return in->config.period_size * in->af_period_multiplier *
7129 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007130}
7131
7132static uint32_t in_get_channels(const struct audio_stream *stream)
7133{
7134 struct stream_in *in = (struct stream_in *)stream;
7135
7136 return in->channel_mask;
7137}
7138
7139static audio_format_t in_get_format(const struct audio_stream *stream)
7140{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007141 struct stream_in *in = (struct stream_in *)stream;
7142
7143 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007144}
7145
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007146static int in_set_format(struct audio_stream *stream __unused,
7147 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007148{
7149 return -ENOSYS;
7150}
7151
7152static int in_standby(struct audio_stream *stream)
7153{
7154 struct stream_in *in = (struct stream_in *)stream;
7155 struct audio_device *adev = in->dev;
7156 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307157 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
7158 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07007159 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307160
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007161 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007162 if (!in->standby && in->is_st_session) {
7163 ALOGD("%s: sound trigger pcm stop lab", __func__);
7164 audio_extn_sound_trigger_stop_lab(in);
George Gao3018ede2019-10-23 13:23:00 -07007165 if (adev->num_va_sessions > 0)
7166 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007167 in->standby = 1;
7168 }
7169
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007170 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007171 if (adev->adm_deregister_stream)
7172 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
7173
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08007174 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007175 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08007176 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08007177 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08007178 voice_extn_compress_voip_close_input_stream(stream);
7179 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07007180 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
7181 do_stop = in->capture_started;
7182 in->capture_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07007183 if (in->mmap_shared_memory_fd >= 0) {
7184 ALOGV("%s: closing mmap_shared_memory_fd = %d",
7185 __func__, in->mmap_shared_memory_fd);
7186 close(in->mmap_shared_memory_fd);
7187 in->mmap_shared_memory_fd = -1;
7188 }
Zhou Songa8895042016-07-05 17:54:22 +08007189 } else {
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307190 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05307191 audio_extn_cin_close_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08007192 }
7193
Arun Mirpuri5d170872019-03-26 13:21:31 -07007194 if (in->pcm) {
7195 ATRACE_BEGIN("pcm_in_close");
7196 pcm_close(in->pcm);
7197 ATRACE_END();
7198 in->pcm = NULL;
7199 }
7200
Carter Hsu2e429db2019-05-14 18:50:52 +08007201 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08007202 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08007203
George Gao3018ede2019-10-23 13:23:00 -07007204 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
7205 if (adev->num_va_sessions > 0)
7206 adev->num_va_sessions--;
7207 }
Quinn Malef6050362019-01-30 15:55:40 -08007208
Eric Laurent150dbfe2013-02-27 14:31:02 -08007209 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007210 }
7211 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07007212 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007213 return status;
7214}
7215
Aalique Grahame22e49102018-12-18 14:23:57 -08007216static int in_dump(const struct audio_stream *stream,
7217 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007218{
Aalique Grahame22e49102018-12-18 14:23:57 -08007219 struct stream_in *in = (struct stream_in *)stream;
7220
7221 // We try to get the lock for consistency,
7222 // but it isn't necessary for these variables.
7223 // If we're not in standby, we may be blocked on a read.
7224 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
7225 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
7226 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
7227 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
Dechen Chai22768452021-07-30 09:29:16 +05307228#ifndef LINUX_ENABLED
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007229 char buffer[256]; // for statistics formatting
7230 if (in->start_latency_ms.n > 0) {
7231 simple_stats_to_string(&in->start_latency_ms, buffer, sizeof(buffer));
7232 dprintf(fd, " Start latency ms: %s\n", buffer);
7233 }
Dechen Chai22768452021-07-30 09:29:16 +05307234#endif
Aalique Grahame22e49102018-12-18 14:23:57 -08007235 if (locked) {
7236 pthread_mutex_unlock(&in->lock);
7237 }
Dechen Chai22768452021-07-30 09:29:16 +05307238#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -08007239 // dump error info
7240 (void)error_log_dump(
7241 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Dechen Chai22768452021-07-30 09:29:16 +05307242#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007243 return 0;
7244}
7245
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307246static void in_snd_mon_cb(void * stream, struct str_parms * parms)
7247{
7248 if (!stream || !parms)
7249 return;
7250
7251 struct stream_in *in = (struct stream_in *)stream;
7252 struct audio_device *adev = in->dev;
7253
7254 card_status_t status;
7255 int card;
7256 if (parse_snd_card_status(parms, &card, &status) < 0)
7257 return;
7258
7259 pthread_mutex_lock(&adev->lock);
7260 bool valid_cb = (card == adev->snd_card);
7261 pthread_mutex_unlock(&adev->lock);
7262
7263 if (!valid_cb)
7264 return;
7265
7266 lock_input_stream(in);
7267 if (in->card_status != status)
7268 in->card_status = status;
7269 pthread_mutex_unlock(&in->lock);
7270
7271 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
7272 use_case_table[in->usecase],
7273 status == CARD_STATUS_OFFLINE ? "offline" : "online");
7274
7275 // a better solution would be to report error back to AF and let
7276 // it put the stream to standby
7277 if (status == CARD_STATUS_OFFLINE)
7278 in_standby(&in->stream.common);
7279
7280 return;
7281}
7282
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007283int route_input_stream(struct stream_in *in,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007284 struct listnode *devices,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007285 audio_source_t source)
7286{
7287 struct audio_device *adev = in->dev;
7288 int ret = 0;
7289
7290 lock_input_stream(in);
7291 pthread_mutex_lock(&adev->lock);
7292
7293 /* no audio source uses val == 0 */
7294 if ((in->source != source) && (source != AUDIO_SOURCE_DEFAULT)) {
7295 in->source = source;
7296 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
7297 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
7298 (voice_extn_compress_voip_is_format_supported(in->format)) &&
7299 (in->config.rate == 8000 || in->config.rate == 16000 ||
7300 in->config.rate == 32000 || in->config.rate == 48000 ) &&
7301 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
7302 ret = voice_extn_compress_voip_open_input_stream(in);
7303 if (ret != 0) {
7304 ALOGE("%s: Compress voip input cannot be opened, error:%d",
7305 __func__, ret);
7306 }
7307 }
7308 }
7309
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007310 if (!compare_devices(&in->device_list, devices) && !list_empty(devices) &&
7311 is_audio_in_device_type(devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007312 // Workaround: If routing to an non existing usb device, fail gracefully
7313 // The routing request will otherwise block during 10 second
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007314 struct str_parms *usb_addr =
7315 str_parms_create_str(get_usb_device_address(devices));
7316 if (is_usb_in_device_type(devices) && usb_addr &&
Weiyin Jiangabedea32020-12-09 12:49:19 +08007317 !audio_extn_usb_connected(NULL)) {
7318 ALOGW("%s: ignoring rerouting to non existing USB", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007319 ret = -ENOSYS;
7320 } else {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007321 /* If recording is in progress, change the tx device to new device */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007322 assign_devices(&in->device_list, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007323 if (!in->standby && !in->is_st_session) {
7324 ALOGV("update input routing change");
7325 // inform adm before actual routing to prevent glitches.
7326 if (adev->adm_on_routing_change) {
7327 adev->adm_on_routing_change(adev->adm_data,
7328 in->capture_handle);
7329 ret = select_devices(adev, in->usecase);
7330 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7331 adev->adm_routing_changed = true;
7332 }
7333 }
7334 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007335 if (usb_addr)
7336 str_parms_destroy(usb_addr);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007337 }
7338 pthread_mutex_unlock(&adev->lock);
7339 pthread_mutex_unlock(&in->lock);
7340
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07007341 ALOGV("%s: exit: status(%d)", __func__, ret);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007342 return ret;
7343}
7344
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007345static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
7346{
7347 struct stream_in *in = (struct stream_in *)stream;
7348 struct audio_device *adev = in->dev;
7349 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007350 char value[32];
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307351 int err = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007352
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307353 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007354 parms = str_parms_create_str(kvpairs);
7355
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307356 if (!parms)
7357 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007358 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08007359 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007360
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307361 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
7362 if (err >= 0) {
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307363 strlcpy(in->profile, value, sizeof(in->profile));
7364 ALOGV("updating stream profile with value '%s'", in->profile);
7365 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
7366 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007367 &in->device_list, in->flags, in->format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307368 in->sample_rate, in->bit_width,
7369 in->profile, &in->app_type_cfg);
7370 }
7371
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007372 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08007373 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007374
7375 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307376error:
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307377 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007378}
7379
7380static char* in_get_parameters(const struct audio_stream *stream,
7381 const char *keys)
7382{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007383 struct stream_in *in = (struct stream_in *)stream;
7384 struct str_parms *query = str_parms_create_str(keys);
7385 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007386 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007387
7388 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08007389 if (reply) {
7390 str_parms_destroy(reply);
7391 }
7392 if (query) {
7393 str_parms_destroy(query);
7394 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007395 ALOGE("in_get_parameters: failed to create query or reply");
7396 return NULL;
7397 }
7398
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007399 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007400
7401 voice_extn_in_get_parameters(in, query, reply);
7402
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007403 stream_get_parameter_channels(query, reply,
7404 &in->supported_channel_masks[0]);
7405 stream_get_parameter_formats(query, reply,
7406 &in->supported_formats[0]);
7407 stream_get_parameter_rates(query, reply,
7408 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007409 str = str_parms_to_str(reply);
7410 str_parms_destroy(query);
7411 str_parms_destroy(reply);
7412
7413 ALOGV("%s: exit: returns - %s", __func__, str);
7414 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007415}
7416
Aalique Grahame22e49102018-12-18 14:23:57 -08007417static int in_set_gain(struct audio_stream_in *stream,
7418 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007419{
Aalique Grahame22e49102018-12-18 14:23:57 -08007420 struct stream_in *in = (struct stream_in *)stream;
7421 char mixer_ctl_name[128];
7422 struct mixer_ctl *ctl;
7423 int ctl_value;
7424
7425 ALOGV("%s: gain %f", __func__, gain);
7426
7427 if (stream == NULL)
7428 return -EINVAL;
7429
7430 /* in_set_gain() only used to silence MMAP capture for now */
7431 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
7432 return -ENOSYS;
7433
7434 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
7435
7436 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
7437 if (!ctl) {
7438 ALOGW("%s: Could not get ctl for mixer cmd - %s",
7439 __func__, mixer_ctl_name);
7440 return -ENOSYS;
7441 }
7442
7443 if (gain < RECORD_GAIN_MIN)
7444 gain = RECORD_GAIN_MIN;
7445 else if (gain > RECORD_GAIN_MAX)
7446 gain = RECORD_GAIN_MAX;
7447 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
7448
7449 mixer_ctl_set_value(ctl, 0, ctl_value);
7450
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007451 return 0;
7452}
7453
7454static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
7455 size_t bytes)
7456{
7457 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05307458
7459 if (in == NULL) {
7460 ALOGE("%s: stream_in ptr is NULL", __func__);
7461 return -EINVAL;
7462 }
7463
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007464 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05307465 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307466 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007467
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007468 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05307469
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007470 if (in->is_st_session) {
7471 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
7472 /* Read from sound trigger HAL */
7473 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08007474 if (in->standby) {
George Gao3018ede2019-10-23 13:23:00 -07007475 if (adev->num_va_sessions < UINT_MAX)
7476 adev->num_va_sessions++;
Quinn Malef6050362019-01-30 15:55:40 -08007477 in->standby = 0;
7478 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007479 pthread_mutex_unlock(&in->lock);
7480 return bytes;
7481 }
7482
Haynes Mathew George16081042017-05-31 17:16:49 -07007483 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
7484 ret = -ENOSYS;
7485 goto exit;
7486 }
7487
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007488 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
7489 !in->standby && adev->adm_routing_changed) {
7490 ret = -ENOSYS;
7491 goto exit;
7492 }
7493
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007494 if (in->standby) {
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007495 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
7496
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007497 pthread_mutex_lock(&adev->lock);
7498 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
7499 ret = voice_extn_compress_voip_start_input_stream(in);
7500 else
7501 ret = start_input_stream(in);
George Gao3018ede2019-10-23 13:23:00 -07007502 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
7503 if (adev->num_va_sessions < UINT_MAX)
7504 adev->num_va_sessions++;
7505 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007506 pthread_mutex_unlock(&adev->lock);
7507 if (ret != 0) {
7508 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007509 }
7510 in->standby = 0;
Dechen Chai22768452021-07-30 09:29:16 +05307511#ifndef LINUX_ENABLED
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007512 // log startup time in ms.
7513 simple_stats_log(
7514 &in->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Dechen Chai22768452021-07-30 09:29:16 +05307515#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007516 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007517
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05307518 /* Avoid read if capture_stopped is set */
7519 if (android_atomic_acquire_load(&(in->capture_stopped)) > 0) {
7520 ALOGD("%s: force stopped catpure session, ignoring read request", __func__);
7521 ret = -EINVAL;
7522 goto exit;
7523 }
7524
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007525 // what's the duration requested by the client?
7526 long ns = 0;
7527
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307528 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007529 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
7530 in->config.rate;
7531
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007532 ret = request_in_focus(in, ns);
7533 if (ret != 0)
7534 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007535 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007536
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307537 if (audio_extn_cin_attached_usecase(in)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307538 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
7539 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307540 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007541 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307542 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07007543 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007544 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007545 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07007546 } else if (audio_extn_ffv_get_stream() == in) {
7547 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307548 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007549 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307550 /* data from DSP comes in 24_8 format, convert it to 8_24 */
7551 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
7552 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
7553 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307554 ret = -EINVAL;
7555 goto exit;
7556 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307557 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307558 ret = -errno;
7559 }
7560 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307561 /* bytes read is always set to bytes for non compress usecases */
7562 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007563 }
7564
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007565 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007566
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007567 /*
Quinn Malef6050362019-01-30 15:55:40 -08007568 * Instead of writing zeroes here, we could trust the hardware to always
7569 * provide zeroes when muted. This is also muted with voice recognition
7570 * usecases so that other clients do not have access to voice recognition
7571 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007572 */
Quinn Malef6050362019-01-30 15:55:40 -08007573 if ((ret == 0 && voice_get_mic_mute(adev) &&
7574 !voice_is_in_call_rec_stream(in) &&
Zhou Song62ea0282020-03-22 19:53:01 +08007575 (in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY &&
7576 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY2)) ||
Quinn Malef6050362019-01-30 15:55:40 -08007577 (adev->num_va_sessions &&
7578 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
7579 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
7580 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007581 memset(buffer, 0, bytes);
7582
7583exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307584 frame_size = audio_stream_in_frame_size(stream);
7585 if (frame_size > 0)
7586 in->frames_read += bytes_read/frame_size;
7587
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007588 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307589 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007590 pthread_mutex_unlock(&in->lock);
7591
7592 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307593 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307594 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307595 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307596 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307597 in->standby = true;
7598 }
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307599 if (!audio_extn_cin_attached_usecase(in)) {
Sharad Sangled17c9122017-03-20 15:58:52 +05307600 bytes_read = bytes;
7601 memset(buffer, 0, bytes);
7602 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007603 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007604 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7605 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007606 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05307607 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05307608 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007609 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307610 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007611}
7612
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007613static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007614{
7615 return 0;
7616}
7617
Aalique Grahame22e49102018-12-18 14:23:57 -08007618static int in_get_capture_position(const struct audio_stream_in *stream,
7619 int64_t *frames, int64_t *time)
7620{
7621 if (stream == NULL || frames == NULL || time == NULL) {
7622 return -EINVAL;
7623 }
7624 struct stream_in *in = (struct stream_in *)stream;
7625 int ret = -ENOSYS;
7626
7627 lock_input_stream(in);
7628 // note: ST sessions do not close the alsa pcm driver synchronously
7629 // on standby. Therefore, we may return an error even though the
7630 // pcm stream is still opened.
7631 if (in->standby) {
7632 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
7633 "%s stream in standby but pcm not NULL for non ST session", __func__);
7634 goto exit;
7635 }
7636 if (in->pcm) {
7637 struct timespec timestamp;
7638 unsigned int avail;
7639 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
7640 *frames = in->frames_read + avail;
Robert Lee58215542019-07-15 20:55:12 +08007641 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec
George Gao9ba8a142020-07-23 14:30:03 -07007642 - platform_capture_latency(in) * 1000LL;
Kakanaboina Ramanjaneyulu8cedb092021-03-15 15:55:29 +05307643 //Adjustment accounts for A2dp decoder latency for recording usecase
7644 // Note: decoder latency is returned in ms, while platform_capture_latency in ns.
7645 if (is_a2dp_in_device_type(&in->device_list))
7646 *time -= audio_extn_a2dp_get_decoder_latency() * 1000000LL;
Aalique Grahame22e49102018-12-18 14:23:57 -08007647 ret = 0;
7648 }
7649 }
7650exit:
7651 pthread_mutex_unlock(&in->lock);
7652 return ret;
7653}
7654
Carter Hsu2e429db2019-05-14 18:50:52 +08007655static int in_update_effect_list(bool add, effect_handle_t effect,
7656 struct listnode *head)
7657{
7658 struct listnode *node;
7659 struct in_effect_list *elist = NULL;
7660 struct in_effect_list *target = NULL;
7661 int ret = 0;
7662
7663 if (!head)
7664 return ret;
7665
7666 list_for_each(node, head) {
7667 elist = node_to_item(node, struct in_effect_list, list);
7668 if (elist->handle == effect) {
7669 target = elist;
7670 break;
7671 }
7672 }
7673
7674 if (add) {
7675 if (target) {
7676 ALOGD("effect %p already exist", effect);
7677 return ret;
7678 }
7679
7680 target = (struct in_effect_list *)
7681 calloc(1, sizeof(struct in_effect_list));
7682
7683 if (!target) {
7684 ALOGE("%s:fail to allocate memory", __func__);
7685 return -ENOMEM;
7686 }
7687
7688 target->handle = effect;
7689 list_add_tail(head, &target->list);
7690 } else {
7691 if (target) {
7692 list_remove(&target->list);
7693 free(target);
7694 }
7695 }
7696
7697 return ret;
7698}
7699
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007700static int add_remove_audio_effect(const struct audio_stream *stream,
7701 effect_handle_t effect,
7702 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007703{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007704 struct stream_in *in = (struct stream_in *)stream;
7705 int status = 0;
7706 effect_descriptor_t desc;
7707
7708 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007709 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
7710
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007711 if (status != 0)
7712 return status;
7713
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007714 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007715 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08007716 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08007717 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
7718 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007719 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08007720
7721 in_update_effect_list(enable, effect, &in->aec_list);
7722 enable = !list_empty(&in->aec_list);
7723 if (enable == in->enable_aec)
7724 goto exit;
7725
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007726 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007727 ALOGD("AEC enable %d", enable);
7728
Aalique Grahame22e49102018-12-18 14:23:57 -08007729 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7730 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
7731 in->dev->enable_voicerx = enable;
7732 struct audio_usecase *usecase;
7733 struct listnode *node;
7734 list_for_each(node, &in->dev->usecase_list) {
7735 usecase = node_to_item(node, struct audio_usecase, list);
7736 if (usecase->type == PCM_PLAYBACK)
7737 select_devices(in->dev, usecase->id);
7738 }
7739 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007740 if (!in->standby) {
7741 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
7742 select_devices(in->dev, in->usecase);
7743 }
7744
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007745 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007746 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
7747
7748 in_update_effect_list(enable, effect, &in->ns_list);
7749 enable = !list_empty(&in->ns_list);
7750 if (enable == in->enable_ns)
7751 goto exit;
7752
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007753 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007754 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007755 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08007756 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Ramu Gottipatifa5be522021-12-28 19:18:21 +05307757 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
kunleizd96526c2018-04-09 11:12:32 +08007758 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007759 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
7760 select_devices(in->dev, in->usecase);
7761 } else
7762 select_devices(in->dev, in->usecase);
7763 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007764 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007765exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007766 pthread_mutex_unlock(&in->dev->lock);
7767 pthread_mutex_unlock(&in->lock);
7768
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007769 return 0;
7770}
7771
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007772static int in_add_audio_effect(const struct audio_stream *stream,
7773 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007774{
Eric Laurent994a6932013-07-17 11:51:42 -07007775 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007776 return add_remove_audio_effect(stream, effect, true);
7777}
7778
7779static int in_remove_audio_effect(const struct audio_stream *stream,
7780 effect_handle_t effect)
7781{
Eric Laurent994a6932013-07-17 11:51:42 -07007782 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007783 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007784}
7785
Haynes Mathew George16081042017-05-31 17:16:49 -07007786static int in_stop(const struct audio_stream_in* stream)
7787{
7788 struct stream_in *in = (struct stream_in *)stream;
7789 struct audio_device *adev = in->dev;
7790
7791 int ret = -ENOSYS;
7792 ALOGV("%s", __func__);
7793 pthread_mutex_lock(&adev->lock);
7794 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7795 in->capture_started && in->pcm != NULL) {
7796 pcm_stop(in->pcm);
7797 ret = stop_input_stream(in);
7798 in->capture_started = false;
7799 }
7800 pthread_mutex_unlock(&adev->lock);
7801 return ret;
7802}
7803
7804static int in_start(const struct audio_stream_in* stream)
7805{
7806 struct stream_in *in = (struct stream_in *)stream;
7807 struct audio_device *adev = in->dev;
7808 int ret = -ENOSYS;
7809
7810 ALOGV("%s in %p", __func__, in);
7811 pthread_mutex_lock(&adev->lock);
7812 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7813 !in->capture_started && in->pcm != NULL) {
7814 if (!in->capture_started) {
7815 ret = start_input_stream(in);
7816 if (ret == 0) {
7817 in->capture_started = true;
7818 }
7819 }
7820 }
7821 pthread_mutex_unlock(&adev->lock);
7822 return ret;
7823}
7824
Phil Burke0a86d12019-02-16 22:28:11 -08007825// Read offset for the positional timestamp from a persistent vendor property.
7826// This is to workaround apparent inaccuracies in the timing information that
7827// is used by the AAudio timing model. The inaccuracies can cause glitches.
7828static int64_t in_get_mmap_time_offset() {
7829 const int32_t kDefaultOffsetMicros = 0;
7830 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08007831 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08007832 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
7833 return mmap_time_offset_micros * (int64_t)1000;
7834}
7835
Haynes Mathew George16081042017-05-31 17:16:49 -07007836static int in_create_mmap_buffer(const struct audio_stream_in *stream,
7837 int32_t min_size_frames,
7838 struct audio_mmap_buffer_info *info)
7839{
7840 struct stream_in *in = (struct stream_in *)stream;
7841 struct audio_device *adev = in->dev;
7842 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07007843 unsigned int offset1 = 0;
7844 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007845 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07007846 uint32_t mmap_size = 0;
7847 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007848
7849 pthread_mutex_lock(&adev->lock);
7850 ALOGV("%s in %p", __func__, in);
7851
Sharad Sanglec6f32552018-05-04 16:15:38 +05307852 if (CARD_STATUS_OFFLINE == in->card_status||
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05007853 CARD_STATUS_OFFLINE == adev->card_status ||
7854 POWER_POLICY_STATUS_OFFLINE == adev->in_power_policy) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307855 ALOGW("in->card_status or adev->card_status offline, try again");
7856 ret = -EIO;
7857 goto exit;
7858 }
7859
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307860 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07007861 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
7862 ret = -EINVAL;
7863 goto exit;
7864 }
7865 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
7866 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
7867 ALOGV("%s in %p", __func__, in);
7868 ret = -ENOSYS;
7869 goto exit;
7870 }
7871 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
7872 if (in->pcm_device_id < 0) {
7873 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
7874 __func__, in->pcm_device_id, in->usecase);
7875 ret = -EINVAL;
7876 goto exit;
7877 }
7878
7879 adjust_mmap_period_count(&in->config, min_size_frames);
7880
7881 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
7882 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
7883 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
7884 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307885 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307886 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7887 in->card_status = CARD_STATUS_OFFLINE;
7888 adev->card_status = CARD_STATUS_OFFLINE;
7889 ret = -EIO;
7890 goto exit;
7891 }
7892
Haynes Mathew George16081042017-05-31 17:16:49 -07007893 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
7894 step = "open";
7895 ret = -ENODEV;
7896 goto exit;
7897 }
7898
7899 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
7900 if (ret < 0) {
7901 step = "begin";
7902 goto exit;
7903 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007904
juyuchen626833d2019-06-04 16:48:02 +08007905 info->flags = 0;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007906 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
7907 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
7908 info->burst_size_frames = in->config.period_size;
7909 ret = platform_get_mmap_data_fd(adev->platform,
7910 in->pcm_device_id, 1 /*capture*/,
7911 &info->shared_memory_fd,
7912 &mmap_size);
7913 if (ret < 0) {
7914 // Fall back to non exclusive mode
7915 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
7916 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07007917 in->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
7918 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, in->mmap_shared_memory_fd);
7919
Arun Mirpuri5d170872019-03-26 13:21:31 -07007920 if (mmap_size < buffer_size) {
7921 step = "mmap";
7922 goto exit;
7923 }
juyuchen626833d2019-06-04 16:48:02 +08007924 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007925 }
7926
7927 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07007928
7929 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
7930 if (ret < 0) {
7931 step = "commit";
7932 goto exit;
7933 }
7934
Phil Burke0a86d12019-02-16 22:28:11 -08007935 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
7936
Haynes Mathew George16081042017-05-31 17:16:49 -07007937 in->standby = false;
7938 ret = 0;
7939
7940 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
7941 __func__, info->shared_memory_address, info->buffer_size_frames);
7942
7943exit:
7944 if (ret != 0) {
7945 if (in->pcm == NULL) {
7946 ALOGE("%s: %s - %d", __func__, step, ret);
7947 } else {
7948 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
7949 pcm_close(in->pcm);
7950 in->pcm = NULL;
7951 }
7952 }
7953 pthread_mutex_unlock(&adev->lock);
7954 return ret;
7955}
7956
7957static int in_get_mmap_position(const struct audio_stream_in *stream,
7958 struct audio_mmap_position *position)
7959{
7960 struct stream_in *in = (struct stream_in *)stream;
7961 ALOGVV("%s", __func__);
7962 if (position == NULL) {
7963 return -EINVAL;
7964 }
Gautam Manam34d1f542021-01-05 20:24:37 +05307965 lock_input_stream(in);
Haynes Mathew George16081042017-05-31 17:16:49 -07007966 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
Gautam Manam34d1f542021-01-05 20:24:37 +05307967 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07007968 return -ENOSYS;
7969 }
7970 if (in->pcm == NULL) {
Gautam Manam34d1f542021-01-05 20:24:37 +05307971 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07007972 return -ENOSYS;
7973 }
7974 struct timespec ts = { 0, 0 };
7975 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
7976 if (ret < 0) {
7977 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
Gautam Manam34d1f542021-01-05 20:24:37 +05307978 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07007979 return ret;
7980 }
Phil Burke0a86d12019-02-16 22:28:11 -08007981 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7982 + in->mmap_time_offset_nanos;
Gautam Manam34d1f542021-01-05 20:24:37 +05307983 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07007984 return 0;
7985}
7986
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307987static int in_get_active_microphones(const struct audio_stream_in *stream,
7988 struct audio_microphone_characteristic_t *mic_array,
7989 size_t *mic_count) {
7990 struct stream_in *in = (struct stream_in *)stream;
7991 struct audio_device *adev = in->dev;
7992 ALOGVV("%s", __func__);
7993
7994 lock_input_stream(in);
7995 pthread_mutex_lock(&adev->lock);
7996 int ret = platform_get_active_microphones(adev->platform,
7997 audio_channel_count_from_in_mask(in->channel_mask),
7998 in->usecase, mic_array, mic_count);
7999 pthread_mutex_unlock(&adev->lock);
8000 pthread_mutex_unlock(&in->lock);
8001
8002 return ret;
8003}
8004
8005static int adev_get_microphones(const struct audio_hw_device *dev,
8006 struct audio_microphone_characteristic_t *mic_array,
8007 size_t *mic_count) {
8008 struct audio_device *adev = (struct audio_device *)dev;
8009 ALOGVV("%s", __func__);
8010
8011 pthread_mutex_lock(&adev->lock);
8012 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
8013 pthread_mutex_unlock(&adev->lock);
8014
8015 return ret;
8016}
juyuchendb308c22019-01-21 11:57:17 -07008017
8018static void in_update_sink_metadata(struct audio_stream_in *stream,
8019 const struct sink_metadata *sink_metadata) {
8020
8021 if (stream == NULL
8022 || sink_metadata == NULL
8023 || sink_metadata->tracks == NULL) {
8024 return;
8025 }
8026
8027 int error = 0;
8028 struct stream_in *in = (struct stream_in *)stream;
8029 struct audio_device *adev = in->dev;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008030 struct listnode devices;
8031
8032 list_init(&devices);
juyuchendb308c22019-01-21 11:57:17 -07008033
8034 if (sink_metadata->track_count != 0)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008035 reassign_device_list(&devices, sink_metadata->tracks->dest_device, "");
juyuchendb308c22019-01-21 11:57:17 -07008036
8037 lock_input_stream(in);
8038 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008039 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, get_device_types(&devices));
juyuchendb308c22019-01-21 11:57:17 -07008040
Zhou Song503196b2021-07-23 17:31:05 +08008041 if ((in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY ||
8042 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2) &&
8043 !list_empty(&devices) &&
8044 adev->voice_tx_output != NULL) {
juyuchendb308c22019-01-21 11:57:17 -07008045 /* Use the rx device from afe-proxy record to route voice call because
8046 there is no routing if tx device is on primary hal and rx device
8047 is on other hal during voice call. */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008048 assign_devices(&adev->voice_tx_output->device_list, &devices);
juyuchendb308c22019-01-21 11:57:17 -07008049
8050 if (!voice_is_call_state_active(adev)) {
8051 if (adev->mode == AUDIO_MODE_IN_CALL) {
8052 adev->current_call_output = adev->voice_tx_output;
8053 error = voice_start_call(adev);
8054 if (error != 0)
8055 ALOGE("%s: start voice call failed %d", __func__, error);
8056 }
8057 } else {
8058 adev->current_call_output = adev->voice_tx_output;
8059 voice_update_devices_for_all_voice_usecases(adev);
8060 }
8061 }
8062
8063 pthread_mutex_unlock(&adev->lock);
8064 pthread_mutex_unlock(&in->lock);
8065}
8066
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308067int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07008068 audio_io_handle_t handle,
8069 audio_devices_t devices,
8070 audio_output_flags_t flags,
8071 struct audio_config *config,
8072 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04008073 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008074{
8075 struct audio_device *adev = (struct audio_device *)dev;
8076 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05308077 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008078 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008079 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05308080 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008081 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
8082 bool is_usb_dev = audio_is_usb_out_device(devices) &&
8083 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
8084 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008085 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07008086 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
8087 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008088 bool force_haptic_path =
8089 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07008090 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008091#ifdef AUDIO_GKI_ENABLED
8092 __s32 *generic_dec;
8093#endif
Weiyin Jiang906db3c2021-03-02 13:17:04 +08008094 pthread_mutexattr_t latch_attr;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008095
kunleizdff872d2018-08-20 14:40:33 +08008096 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08008097 is_usb_dev = false;
8098 devices = AUDIO_DEVICE_OUT_SPEAKER;
8099 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
8100 __func__, devices);
Mingshu Pangdbd20562019-11-25 18:04:39 +08008101 if (config->format == AUDIO_FORMAT_DEFAULT)
8102 config->format = AUDIO_FORMAT_PCM_16_BIT;
8103 if (config->sample_rate == 0)
8104 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8105 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8106 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
kunleizd6a9e0c2018-07-30 15:38:52 +08008107 }
8108
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008109 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05308110
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008111 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
8112
Mingming Yin3a941d42016-02-17 18:08:05 -08008113 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04008114 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
8115 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308116
8117
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008118 if (!out) {
8119 return -ENOMEM;
8120 }
8121
Haynes Mathew George204045b2015-02-25 20:32:03 -08008122 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07008123 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Weiyin Jiang906db3c2021-03-02 13:17:04 +08008124 pthread_mutexattr_init(&latch_attr);
8125 pthread_mutexattr_settype(&latch_attr, PTHREAD_MUTEX_RECURSIVE);
8126 pthread_mutex_init(&out->latch_lock, &latch_attr);
8127 pthread_mutexattr_destroy(&latch_attr);
Zhou Song48453a02018-01-10 17:50:59 +08008128 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08008129 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
8130
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008131 if (devices == AUDIO_DEVICE_NONE)
8132 devices = AUDIO_DEVICE_OUT_SPEAKER;
8133
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008134 out->flags = flags;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008135 list_init(&out->device_list);
8136 update_device_list(&out->device_list, devices, address, true /* add devices */);
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07008137 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07008138 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008139 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05308140 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05308141 if (out->channel_mask == AUDIO_CHANNEL_NONE)
8142 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
8143 else
8144 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07008145 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07008146 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08008147 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308148 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308149 out->started = 0;
Zhou Songbaddf9f2020-11-20 13:57:39 +08008150 out->a2dp_muted = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008151 out->hal_output_suspend_supported = 0;
8152 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05308153 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05308154 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05308155 out->pspd_coeff_sent = false;
Phil Burkd898ba62019-06-20 12:49:01 -07008156 out->mmap_shared_memory_fd = -1; // not open
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008157
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05308158 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05308159 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07008160 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
8161
Aalique Grahame22e49102018-12-18 14:23:57 -08008162 if (direct_dev &&
8163 (audio_is_linear_pcm(out->format) ||
8164 config->format == AUDIO_FORMAT_DEFAULT) &&
8165 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
8166 audio_format_t req_format = config->format;
8167 audio_channel_mask_t req_channel_mask = config->channel_mask;
8168 uint32_t req_sample_rate = config->sample_rate;
8169
8170 pthread_mutex_lock(&adev->lock);
8171 if (is_hdmi) {
8172 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
8173 ret = read_hdmi_sink_caps(out);
8174 if (config->sample_rate == 0)
8175 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8176 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8177 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
8178 if (config->format == AUDIO_FORMAT_DEFAULT)
8179 config->format = AUDIO_FORMAT_PCM_16_BIT;
8180 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008181 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
8182 &config->format,
8183 &out->supported_formats[0],
8184 MAX_SUPPORTED_FORMATS,
8185 &config->channel_mask,
8186 &out->supported_channel_masks[0],
8187 MAX_SUPPORTED_CHANNEL_MASKS,
8188 &config->sample_rate,
8189 &out->supported_sample_rates[0],
8190 MAX_SUPPORTED_SAMPLE_RATES);
8191 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008192 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008193
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008194 pthread_mutex_unlock(&adev->lock);
8195 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08008196 if (ret == -ENOSYS) {
8197 /* ignore and go with default */
8198 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08008199 }
8200 // For MMAP NO IRQ, allow conversions in ADSP
8201 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
8202 goto error_open;
8203 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008204 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08008205 goto error_open;
8206 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008207
8208 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
8209 config->sample_rate = req_sample_rate;
8210 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
8211 config->channel_mask = req_channel_mask;
8212 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
8213 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08008214 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008215
8216 out->sample_rate = config->sample_rate;
8217 out->channel_mask = config->channel_mask;
8218 out->format = config->format;
8219 if (is_hdmi) {
8220 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
8221 out->config = pcm_config_hdmi_multi;
8222 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8223 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8224 out->config = pcm_config_mmap_playback;
8225 out->stream.start = out_start;
8226 out->stream.stop = out_stop;
8227 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8228 out->stream.get_mmap_position = out_get_mmap_position;
8229 } else {
8230 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
8231 out->config = pcm_config_hifi;
8232 }
8233
8234 out->config.rate = out->sample_rate;
8235 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
8236 if (is_hdmi) {
8237 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
8238 audio_bytes_per_sample(out->format));
8239 }
8240 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08008241 }
8242
Derek Chenf6318be2017-06-12 17:16:24 -04008243 /* validate bus device address */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008244 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008245 /* extract car audio stream index */
8246 out->car_audio_stream =
8247 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
8248 if (out->car_audio_stream < 0) {
8249 ALOGE("%s: invalid car audio stream %x",
8250 __func__, out->car_audio_stream);
8251 ret = -EINVAL;
8252 goto error_open;
8253 }
Derek Chen5f67a942020-02-24 23:08:13 -08008254 ALOGV("%s: car_audio_stream %x", __func__, out->car_audio_stream);
Derek Chenf6318be2017-06-12 17:16:24 -04008255 }
8256
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008257 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07008258 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008259 if (!voice_extn_is_compress_voip_supported()) {
8260 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
8261 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07008262 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
Lakshman Chaluvarajue7fc9482020-05-30 14:29:29 +05308263 config->channel_mask : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008264 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
8265 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07008266 out->volume_l = INVALID_OUT_VOLUME;
8267 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07008268
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008269 out->config = default_pcm_config_voip_copp;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008270 out->config.rate = out->sample_rate;
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07008271 uint32_t channel_count =
8272 audio_channel_count_from_out_mask(out->channel_mask);
Ramjee Singh968858a2020-08-06 16:30:48 +05308273 out->config.channels = channel_count;
8274
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07008275 uint32_t buffer_size = get_stream_buffer_size(DEFAULT_VOIP_BUF_DURATION_MS,
8276 out->sample_rate, out->format,
8277 channel_count, false);
8278 uint32_t frame_size = audio_bytes_per_sample(out->format) * channel_count;
8279 if (frame_size != 0)
8280 out->config.period_size = buffer_size / frame_size;
8281 else
8282 ALOGW("%s: frame size is 0 for format %#x", __func__, out->format);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008283 }
8284 } else {
8285 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
8286 voice_extn_compress_voip_is_active(out->dev)) &&
8287 (voice_extn_compress_voip_is_config_supported(config))) {
8288 ret = voice_extn_compress_voip_open_output_stream(out);
8289 if (ret != 0) {
8290 ALOGE("%s: Compress voip output cannot be opened, error:%d",
8291 __func__, ret);
8292 goto error_open;
8293 }
Sujin Panicker19027262019-09-16 18:28:06 +05308294 } else {
8295 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8296 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008297 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008298 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008299 } else if (audio_is_linear_pcm(out->format) &&
8300 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
8301 out->channel_mask = config->channel_mask;
8302 out->sample_rate = config->sample_rate;
8303 out->format = config->format;
8304 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
8305 // does this change?
8306 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
8307 out->config.rate = config->sample_rate;
8308 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
8309 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
8310 audio_bytes_per_sample(config->format));
8311 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07008312 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308313 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308314 pthread_mutex_lock(&adev->lock);
8315 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
8316 pthread_mutex_unlock(&adev->lock);
8317
8318 // reject offload during card offline to allow
8319 // fallback to s/w paths
8320 if (offline) {
8321 ret = -ENODEV;
8322 goto error_open;
8323 }
vivek mehta0ea887a2015-08-26 14:01:20 -07008324
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008325 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
8326 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
8327 ALOGE("%s: Unsupported Offload information", __func__);
8328 ret = -EINVAL;
8329 goto error_open;
8330 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008331
Atul Khare3fa6e542017-08-09 00:56:17 +05308332 if (config->offload_info.format == 0)
8333 config->offload_info.format = config->format;
8334 if (config->offload_info.sample_rate == 0)
8335 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008336
Mingming Yin90310102013-11-13 16:57:00 -08008337 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308338 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07008339 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008340 ret = -EINVAL;
8341 goto error_open;
8342 }
8343
Ben Romberger0f8c87b2017-05-24 17:41:11 -07008344 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
8345 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
8346 (audio_extn_passthru_is_passthrough_stream(out)) &&
8347 !((config->sample_rate == 48000) ||
8348 (config->sample_rate == 96000) ||
8349 (config->sample_rate == 192000))) {
8350 ALOGE("%s: Unsupported sample rate %d for audio format %x",
8351 __func__, config->sample_rate, config->offload_info.format);
8352 ret = -EINVAL;
8353 goto error_open;
8354 }
8355
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008356 out->compr_config.codec = (struct snd_codec *)
8357 calloc(1, sizeof(struct snd_codec));
8358
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008359 if (!out->compr_config.codec) {
8360 ret = -ENOMEM;
8361 goto error_open;
8362 }
8363
Dhananjay Kumarac341582017-02-23 23:42:25 +05308364 out->stream.pause = out_pause;
8365 out->stream.resume = out_resume;
8366 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05308367 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05308368 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07008369 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05308370 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07008371 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05308372 } else {
8373 out->usecase = get_offload_usecase(adev, false /* is_compress */);
8374 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07008375 }
vivek mehta446c3962015-09-14 10:57:35 -07008376
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308377 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8378 ALOGD("%s: Setting latency mode to true", __func__);
Meng Wang4c32fb42020-01-16 17:57:11 +08008379#ifdef AUDIO_GKI_ENABLED
8380 /* out->compr_config.codec->reserved[1] is for flags */
8381 out->compr_config.codec->reserved[1] |= audio_extn_utils_get_perf_mode_flag();
8382#else
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308383 out->compr_config.codec->flags |= audio_extn_utils_get_perf_mode_flag();
Meng Wang4c32fb42020-01-16 17:57:11 +08008384#endif
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308385 }
8386
vivek mehta446c3962015-09-14 10:57:35 -07008387 if (out->usecase == USECASE_INVALID) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008388 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Mingming Yin3a941d42016-02-17 18:08:05 -08008389 config->format == 0 && config->sample_rate == 0 &&
8390 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07008391 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08008392 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
8393 } else {
8394 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
8395 ret = -EEXIST;
8396 goto error_open;
8397 }
vivek mehta446c3962015-09-14 10:57:35 -07008398 }
8399
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008400 if (config->offload_info.channel_mask)
8401 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008402 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008403 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008404 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008405 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05308406 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008407 ret = -EINVAL;
8408 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008409 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008410
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008411 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008412 out->sample_rate = config->offload_info.sample_rate;
8413
Mingming Yin3ee55c62014-08-04 14:23:35 -07008414 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008415
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308416 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05308417 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308418 audio_extn_dolby_send_ddp_endp_params(adev);
8419 audio_extn_dolby_set_dmid(adev);
8420 }
vivek mehta0ea887a2015-08-26 14:01:20 -07008421
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008422 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08008423 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008424 out->compr_config.codec->bit_rate =
8425 config->offload_info.bit_rate;
8426 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05308427 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008428 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05308429 /* Update bit width only for non passthrough usecases.
8430 * For passthrough usecases, the output will always be opened @16 bit
8431 */
8432 if (!audio_extn_passthru_is_passthrough_stream(out))
8433 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308434
8435 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
Meng Wang4c32fb42020-01-16 17:57:11 +08008436#ifdef AUDIO_GKI_ENABLED
8437 /* out->compr_config.codec->reserved[1] is for flags */
8438 out->compr_config.codec->reserved[1] |= COMPRESSED_TIMESTAMP_FLAG;
8439 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->reserved[1]);
8440#else
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308441 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
8442 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
Meng Wang4c32fb42020-01-16 17:57:11 +08008443#endif
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308444
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008445 /*TODO: Do we need to change it for passthrough */
8446 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008447
Manish Dewangana6fc5442015-08-24 20:30:31 +05308448 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
8449 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308450 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05308451 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308452 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
8453 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308454
8455 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
8456 AUDIO_FORMAT_PCM) {
8457
8458 /*Based on platform support, configure appropriate alsa format for corresponding
8459 *hal input format.
8460 */
8461 out->compr_config.codec->format = hal_format_to_alsa(
8462 config->offload_info.format);
8463
Ashish Jain83a6cc22016-06-28 14:34:17 +05308464 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05308465 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308466 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308467
Dhananjay Kumarac341582017-02-23 23:42:25 +05308468 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05308469 *hal input format and alsa format might differ based on platform support.
8470 */
8471 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05308472 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308473
8474 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
8475
Deeraj Soman93155a62019-09-30 19:00:37 +05308476 if (property_get_bool("vendor.audio.offload.buffer.duration.enabled", false)) {
8477 if ((config->offload_info.duration_us >= MIN_OFFLOAD_BUFFER_DURATION_MS * 1000) &&
8478 (config->offload_info.duration_us <= MAX_OFFLOAD_BUFFER_DURATION_MS * 1000))
8479 out->info.duration_us = (int64_t)config->offload_info.duration_us;
8480 }
Deeraj Soman65358ab2019-02-07 15:40:49 +05308481
Ashish Jainf1eaa582016-05-23 20:54:24 +05308482 /* Check if alsa session is configured with the same format as HAL input format,
8483 * if not then derive correct fragment size needed to accomodate the
8484 * conversion of HAL input format to alsa format.
8485 */
8486 audio_extn_utils_update_direct_pcm_fragment_size(out);
8487
8488 /*if hal input and output fragment size is different this indicates HAL input format is
8489 *not same as the alsa format
8490 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308491 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05308492 /*Allocate a buffer to convert input data to the alsa configured format.
8493 *size of convert buffer is equal to the size required to hold one fragment size
8494 *worth of pcm data, this is because flinger does not write more than fragment_size
8495 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308496 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
8497 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05308498 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
8499 ret = -ENOMEM;
8500 goto error_open;
8501 }
8502 }
8503 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
8504 out->compr_config.fragment_size =
8505 audio_extn_passthru_get_buffer_size(&config->offload_info);
8506 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8507 } else {
8508 out->compr_config.fragment_size =
8509 platform_get_compress_offload_buffer_size(&config->offload_info);
8510 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8511 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008512
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308513 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8514 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
8515 }
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008516 if (config->offload_info.format == AUDIO_FORMAT_FLAC) {
8517#ifdef AUDIO_GKI_ENABLED
8518 generic_dec =
8519 &(out->compr_config.codec->options.generic.reserved[1]);
8520 ((struct snd_generic_dec_flac *)generic_dec)->sample_size =
8521 AUDIO_OUTPUT_BIT_WIDTH;
8522#else
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05308523 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008524#endif
8525 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008526
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05308527 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
8528 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
8529 }
8530
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008531 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
8532 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008533
Manish Dewangan69426c82017-01-30 17:35:36 +05308534 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
8535 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
8536 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
8537 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8538 out->render_mode = RENDER_MODE_AUDIO_MASTER;
8539 } else {
8540 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
8541 }
Alexy Josephaa54c872014-12-03 02:46:47 -08008542
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05308543 memset(&out->channel_map_param, 0,
8544 sizeof(struct audio_out_channel_map_param));
8545
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008546 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05308547 out->send_next_track_params = false;
8548 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008549 out->offload_state = OFFLOAD_STATE_IDLE;
8550 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08008551 out->writeAt.tv_sec = 0;
8552 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008553
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008554 audio_extn_dts_create_state_notifier_node(out->usecase);
8555
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008556 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
8557 __func__, config->offload_info.version,
8558 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05308559
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308560 /* Check if DSD audio format is supported in codec
8561 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308562 */
8563
8564 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308565 (!platform_check_codec_dsd_support(adev->platform) ||
8566 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308567 ret = -EINVAL;
8568 goto error_open;
8569 }
8570
Ashish Jain5106d362016-05-11 19:23:33 +05308571 /* Disable gapless if any of the following is true
8572 * passthrough playback
8573 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05308574 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05308575 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308576 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308577 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07008578 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308579 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308580 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05308581 check_and_set_gapless_mode(adev, false);
8582 } else
8583 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07008584
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308585 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07008586 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
8587 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308588 if (config->format == AUDIO_FORMAT_DSD) {
8589 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
Meng Wang4c32fb42020-01-16 17:57:11 +08008590#ifdef AUDIO_GKI_ENABLED
8591 /* out->compr_config.codec->reserved[0] is for compr_passthr */
8592 out->compr_config.codec->reserved[0] = PASSTHROUGH_DSD;
8593#else
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308594 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
Meng Wang4c32fb42020-01-16 17:57:11 +08008595#endif
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308596 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07008597
8598 create_offload_callback_thread(out);
8599
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008600 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008601 switch (config->sample_rate) {
8602 case 0:
8603 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8604 break;
8605 case 8000:
8606 case 16000:
8607 case 48000:
8608 out->sample_rate = config->sample_rate;
8609 break;
8610 default:
8611 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
8612 config->sample_rate);
8613 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8614 ret = -EINVAL;
8615 goto error_open;
8616 }
8617 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8618 switch (config->channel_mask) {
8619 case AUDIO_CHANNEL_NONE:
8620 case AUDIO_CHANNEL_OUT_STEREO:
8621 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8622 break;
8623 default:
8624 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
8625 config->channel_mask);
8626 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8627 ret = -EINVAL;
8628 goto error_open;
8629 }
8630 switch (config->format) {
8631 case AUDIO_FORMAT_DEFAULT:
8632 case AUDIO_FORMAT_PCM_16_BIT:
8633 out->format = AUDIO_FORMAT_PCM_16_BIT;
8634 break;
8635 default:
8636 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
8637 config->format);
8638 config->format = AUDIO_FORMAT_PCM_16_BIT;
8639 ret = -EINVAL;
8640 goto error_open;
8641 }
8642
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05308643 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008644 if (ret != 0) {
8645 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008646 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008647 goto error_open;
8648 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008649 } else if (is_single_device_type_equal(&out->device_list,
8650 AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08008651 switch (config->sample_rate) {
8652 case 0:
8653 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
8654 break;
8655 case 8000:
8656 case 16000:
8657 case 48000:
8658 out->sample_rate = config->sample_rate;
8659 break;
8660 default:
8661 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
8662 config->sample_rate);
8663 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8664 ret = -EINVAL;
8665 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008666 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008667 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8668 switch (config->channel_mask) {
8669 case AUDIO_CHANNEL_NONE:
8670 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8671 break;
8672 case AUDIO_CHANNEL_OUT_STEREO:
8673 out->channel_mask = config->channel_mask;
8674 break;
8675 default:
8676 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
8677 config->channel_mask);
8678 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8679 ret = -EINVAL;
8680 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008681 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008682 switch (config->format) {
8683 case AUDIO_FORMAT_DEFAULT:
8684 out->format = AUDIO_FORMAT_PCM_16_BIT;
8685 break;
8686 case AUDIO_FORMAT_PCM_16_BIT:
8687 out->format = config->format;
8688 break;
8689 default:
8690 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
8691 config->format);
8692 config->format = AUDIO_FORMAT_PCM_16_BIT;
8693 ret = -EINVAL;
8694 break;
8695 }
8696 if (ret != 0)
8697 goto error_open;
8698
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008699 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
8700 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08008701 out->config.rate = out->sample_rate;
8702 out->config.channels =
8703 audio_channel_count_from_out_mask(out->channel_mask);
8704 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008705 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008706 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05308707 unsigned int channels = 0;
8708 /*Update config params to default if not set by the caller*/
8709 if (config->sample_rate == 0)
8710 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8711 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8712 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8713 if (config->format == AUDIO_FORMAT_DEFAULT)
8714 config->format = AUDIO_FORMAT_PCM_16_BIT;
8715
8716 channels = audio_channel_count_from_out_mask(out->channel_mask);
8717
Varun Balaraje49253e2017-07-06 19:48:56 +05308718 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
8719 out->usecase = get_interactive_usecase(adev);
8720 out->config = pcm_config_low_latency;
8721 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05308722 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008723 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
8724 out->flags);
8725 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07008726 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8727 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8728 out->config = pcm_config_mmap_playback;
8729 out->stream.start = out_start;
8730 out->stream.stop = out_stop;
8731 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8732 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308733 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8734 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008735 out->hal_output_suspend_supported =
8736 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
8737 out->dynamic_pm_qos_config_supported =
8738 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
8739 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08008740 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
8741 } else {
8742 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
8743 //the mixer path will be a string similar to "low-latency-playback resume"
8744 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
8745 strlcat(out->pm_qos_mixer_path,
8746 " resume", MAX_MIXER_PATH_LEN);
8747 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
8748 out->pm_qos_mixer_path);
8749 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308750 out->config = pcm_config_low_latency;
8751 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
8752 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
8753 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05308754 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
8755 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
8756 if (out->config.period_size <= 0) {
8757 ALOGE("Invalid configuration period size is not valid");
8758 ret = -EINVAL;
8759 goto error_open;
8760 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008761 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
8762 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
8763 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008764 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
8765 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
8766 out->config = pcm_config_haptics_audio;
8767 if (force_haptic_path)
8768 adev->haptics_config = pcm_config_haptics_audio;
8769 else
8770 adev->haptics_config = pcm_config_haptics;
8771
Meng Wangd08ce322020-04-02 08:59:20 +08008772 channels =
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008773 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
8774
8775 if (force_haptic_path) {
8776 out->config.channels = 1;
8777 adev->haptics_config.channels = 1;
8778 } else
8779 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 -08008780 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008781 ret = audio_extn_auto_hal_open_output_stream(out);
8782 if (ret) {
8783 ALOGE("%s: Failed to open output stream for bus device", __func__);
8784 ret = -EINVAL;
8785 goto error_open;
8786 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308787 } else {
8788 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008789 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8790 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308791 }
8792 out->hal_ip_format = format = out->format;
8793 out->config.format = hal_format_to_pcm(out->hal_ip_format);
8794 out->hal_op_format = pcm_format_to_hal(out->config.format);
8795 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
8796 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008797 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05308798 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308799 if (out->hal_ip_format != out->hal_op_format) {
8800 uint32_t buffer_size = out->config.period_size *
8801 format_to_bitwidth_table[out->hal_op_format] *
8802 out->config.channels;
8803 out->convert_buffer = calloc(1, buffer_size);
8804 if (out->convert_buffer == NULL){
8805 ALOGE("Allocation failed for convert buffer for size %d",
8806 out->compr_config.fragment_size);
8807 ret = -ENOMEM;
8808 goto error_open;
8809 }
8810 ALOGD("Convert buffer allocated of size %d", buffer_size);
8811 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008812 }
8813
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008814 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
8815 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308816
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008817 /* TODO remove this hardcoding and check why width is zero*/
8818 if (out->bit_width == 0)
8819 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308820 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008821 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008822 &out->device_list, out->flags,
8823 out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05308824 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05308825 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08008826 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08008827 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
8828 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008829 if(adev->primary_output == NULL)
8830 adev->primary_output = out;
8831 else {
8832 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008833 ret = -EEXIST;
8834 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008835 }
8836 }
8837
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008838 /* Check if this usecase is already existing */
8839 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07008840 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
8841 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008842 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008843 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008844 ret = -EEXIST;
8845 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008846 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008847
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008848 pthread_mutex_unlock(&adev->lock);
8849
8850 out->stream.common.get_sample_rate = out_get_sample_rate;
8851 out->stream.common.set_sample_rate = out_set_sample_rate;
8852 out->stream.common.get_buffer_size = out_get_buffer_size;
8853 out->stream.common.get_channels = out_get_channels;
8854 out->stream.common.get_format = out_get_format;
8855 out->stream.common.set_format = out_set_format;
8856 out->stream.common.standby = out_standby;
8857 out->stream.common.dump = out_dump;
8858 out->stream.common.set_parameters = out_set_parameters;
8859 out->stream.common.get_parameters = out_get_parameters;
8860 out->stream.common.add_audio_effect = out_add_audio_effect;
8861 out->stream.common.remove_audio_effect = out_remove_audio_effect;
8862 out->stream.get_latency = out_get_latency;
8863 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08008864#ifdef NO_AUDIO_OUT
8865 out->stream.write = out_write_for_no_output;
8866#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008867 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08008868#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008869 out->stream.get_render_position = out_get_render_position;
8870 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008871 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008872
Haynes Mathew George16081042017-05-31 17:16:49 -07008873 if (out->realtime)
8874 out->af_period_multiplier = af_period_multiplier;
8875 else
8876 out->af_period_multiplier = 1;
8877
Andy Hunga1f48fa2019-07-01 18:14:53 -07008878 out->kernel_buffer_size = out->config.period_size * out->config.period_count;
8879
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008880 out->standby = 1;
Zhou Songbaddf9f2020-11-20 13:57:39 +08008881 out->volume_l = PLAYBACK_GAIN_MAX;
8882 out->volume_r = PLAYBACK_GAIN_MAX;
Eric Laurenta9024de2013-04-04 09:19:12 -07008883 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008884 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008885
8886 config->format = out->stream.common.get_format(&out->stream.common);
8887 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
8888 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308889 register_format(out->format, out->supported_formats);
8890 register_channel_mask(out->channel_mask, out->supported_channel_masks);
8891 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008892
Dechen Chai22768452021-07-30 09:29:16 +05308893#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -08008894 out->error_log = error_log_create(
8895 ERROR_LOG_ENTRIES,
8896 1000000000 /* aggregate consecutive identical errors within one second in ns */);
Dechen Chai22768452021-07-30 09:29:16 +05308897#endif
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308898 /*
8899 By locking output stream before registering, we allow the callback
8900 to update stream's state only after stream's initial state is set to
8901 adev state.
8902 */
8903 lock_output_stream(out);
8904 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
8905 pthread_mutex_lock(&adev->lock);
8906 out->card_status = adev->card_status;
8907 pthread_mutex_unlock(&adev->lock);
8908 pthread_mutex_unlock(&out->lock);
8909
Aalique Grahame22e49102018-12-18 14:23:57 -08008910 stream_app_type_cfg_init(&out->app_type_cfg);
8911
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008912 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308913 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07008914 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008915
8916 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
8917 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
8918 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008919 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05308920 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008921 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07008922 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05308923 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
8924 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008925 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
8926 out->usecase, PCM_PLAYBACK);
8927 hdlr_stream_cfg.flags = out->flags;
8928 hdlr_stream_cfg.type = PCM_PLAYBACK;
8929 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
8930 &hdlr_stream_cfg);
8931 if (ret) {
8932 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
8933 out->adsp_hdlr_stream_handle = NULL;
8934 }
8935 }
Gangadhar Sb0210342019-02-22 17:39:41 +05308936 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
8937 is_direct_passthough, false);
8938 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
8939 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07008940 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07008941 if (ret < 0) {
8942 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
8943 out->ip_hdlr_handle = NULL;
8944 }
8945 }
Derek Chenf939fb72018-11-13 13:34:41 -08008946
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008947 ret = io_streams_map_insert(adev, &out->stream.common,
8948 out->handle, AUDIO_PATCH_HANDLE_NONE);
8949 if (ret != 0)
8950 goto error_open;
8951
Susan Wang6dd13092021-01-25 10:27:11 -05008952 out->out_ctxt.output = out;
Derek Chenf939fb72018-11-13 13:34:41 -08008953
8954 pthread_mutex_lock(&adev->lock);
Susan Wang6dd13092021-01-25 10:27:11 -05008955 list_add_tail(&adev->active_outputs_list, &out->out_ctxt.list);
Derek Chenf939fb72018-11-13 13:34:41 -08008956 pthread_mutex_unlock(&adev->lock);
8957
Eric Laurent994a6932013-07-17 11:51:42 -07008958 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008959 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008960
8961error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05308962 if (out->convert_buffer)
8963 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008964 free(out);
8965 *stream_out = NULL;
8966 ALOGD("%s: exit: ret %d", __func__, ret);
8967 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008968}
8969
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308970void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008971 struct audio_stream_out *stream)
8972{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008973 struct stream_out *out = (struct stream_out *)stream;
8974 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008975 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008976
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008977 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308978
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008979 io_streams_map_remove(adev, out->handle);
8980
Susan Wang6dd13092021-01-25 10:27:11 -05008981 // remove out_ctxt early to prevent the stream
8982 // being opened in a race condition
8983 pthread_mutex_lock(&adev->lock);
8984 list_remove(&out->out_ctxt.list);
8985 pthread_mutex_unlock(&adev->lock);
8986
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308987 // must deregister from sndmonitor first to prevent races
8988 // between the callback and close_stream
8989 audio_extn_snd_mon_unregister_listener(out);
8990
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008991 /* close adsp hdrl session before standby */
8992 if (out->adsp_hdlr_stream_handle) {
8993 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
8994 if (ret)
8995 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
8996 out->adsp_hdlr_stream_handle = NULL;
8997 }
8998
Manish Dewangan21a850a2017-08-14 12:03:55 +05308999 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07009000 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
9001 out->ip_hdlr_handle = NULL;
9002 }
9003
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009004 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309005 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009006 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05309007 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309008 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009009 if(ret != 0)
9010 ALOGE("%s: Compress voip output cannot be closed, error:%d",
9011 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009012 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009013 out_standby(&stream->common);
9014
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07009015 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08009016 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07009017 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07009018 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07009019 if (out->compr_config.codec != NULL)
9020 free(out->compr_config.codec);
9021 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009022
Zhou Songbaddf9f2020-11-20 13:57:39 +08009023 out->a2dp_muted = false;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05309024
Varun Balaraje49253e2017-07-06 19:48:56 +05309025 if (is_interactive_usecase(out->usecase))
9026 free_interactive_usecase(adev, out->usecase);
9027
Ashish Jain83a6cc22016-06-28 14:34:17 +05309028 if (out->convert_buffer != NULL) {
9029 free(out->convert_buffer);
9030 out->convert_buffer = NULL;
9031 }
9032
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009033 if (adev->voice_tx_output == out)
9034 adev->voice_tx_output = NULL;
9035
Dechen Chai22768452021-07-30 09:29:16 +05309036#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -08009037 error_log_destroy(out->error_log);
9038 out->error_log = NULL;
Dechen Chai22768452021-07-30 09:29:16 +05309039#endif
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05309040 if (adev->primary_output == out)
9041 adev->primary_output = NULL;
9042
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07009043 pthread_cond_destroy(&out->cond);
9044 pthread_mutex_destroy(&out->lock);
Weiyin Jiang280ea742020-09-08 20:28:22 +08009045 pthread_mutex_destroy(&out->pre_lock);
9046 pthread_mutex_destroy(&out->latch_lock);
9047 pthread_mutex_destroy(&out->position_query_lock);
Derek Chenf939fb72018-11-13 13:34:41 -08009048
9049 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009050 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08009051 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07009052 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009053}
9054
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05009055void in_set_power_policy(uint8_t enable)
9056{
9057 struct listnode *node;
9058
9059 ALOGD("%s: Enter, state %d", __func__, enable);
9060
9061 pthread_mutex_lock(&adev->lock);
9062 adev->in_power_policy = enable ? POWER_POLICY_STATUS_ONLINE : POWER_POLICY_STATUS_OFFLINE;
9063 pthread_mutex_unlock(&adev->lock);
9064
9065 if (!enable) {
9066 list_for_each(node, &adev->active_inputs_list) {
9067 streams_input_ctxt_t *in_ctxt = node_to_item(node,
9068 streams_input_ctxt_t,
9069 list);
9070 struct stream_in *in = in_ctxt->input;
9071 in_standby(&in->stream.common);
9072 }
9073 }
9074
9075 ALOGD("%s: Exit", __func__);
9076}
9077
9078void out_set_power_policy(uint8_t enable)
9079{
9080 struct listnode *node;
9081
9082 ALOGD("%s: Enter, state %d", __func__, enable);
9083
9084 pthread_mutex_lock(&adev->lock);
E V Ravi317be872022-02-23 19:08:15 +05309085 adev->out_power_policy = enable ? POWER_POLICY_STATUS_ONLINE : POWER_POLICY_STATUS_OFFLINE;
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05009086 pthread_mutex_unlock(&adev->lock);
9087
9088 if (!enable) {
9089 list_for_each(node, &adev->active_outputs_list) {
9090 streams_output_ctxt_t *out_ctxt = node_to_item(node,
9091 streams_output_ctxt_t,
9092 list);
9093 struct stream_out *out = out_ctxt->output;
9094 out_on_error(&out->stream.common);
9095 }
9096 }
9097
9098 ALOGD("%s: Exit", __func__);
9099}
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009100static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
9101{
9102 struct audio_device *adev = (struct audio_device *)dev;
9103 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009104 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07009105 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009106 int ret;
9107 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08009108 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08009109 struct listnode *node;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07009110 int controller = -1, stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009111
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009112 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009113 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009114
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05309115 if (!parms)
9116 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05309117
Derek Chen6f293672019-04-01 01:40:24 -07009118 /* notify adev and input/output streams on the snd card status */
9119 adev_snd_mon_cb((void *)adev, parms);
9120
Weiyin Jiang24f55292020-12-22 14:35:46 +08009121 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
9122 if (ret >= 0) {
9123 list_for_each(node, &adev->active_outputs_list) {
9124 streams_output_ctxt_t *out_ctxt = node_to_item(node,
9125 streams_output_ctxt_t,
9126 list);
9127 out_snd_mon_cb((void *)out_ctxt->output, parms);
9128 }
Derek Chen6f293672019-04-01 01:40:24 -07009129
Weiyin Jiang24f55292020-12-22 14:35:46 +08009130 list_for_each(node, &adev->active_inputs_list) {
9131 streams_input_ctxt_t *in_ctxt = node_to_item(node,
9132 streams_input_ctxt_t,
9133 list);
9134 in_snd_mon_cb((void *)in_ctxt->input, parms);
9135 }
Derek Chen6f293672019-04-01 01:40:24 -07009136 }
9137
Zhou Songd6d71752019-05-21 18:08:51 +08009138 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05309139 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
9140 if (ret >= 0) {
9141 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08009142 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05309143 adev->bt_sco_on = true;
Shalini Manjunatha3a2e06e2021-02-01 12:23:49 +05309144 /*
9145 * When ever BT_SCO=ON arrives, make sure to route
9146 * all use cases to SCO device, otherwise due to delay in
9147 * BT_SCO=ON and lack of synchronization with create audio patch
9148 * request for SCO device, some times use case not routed properly to
9149 * SCO device
9150 */
9151 struct audio_usecase *usecase;
9152 struct listnode *node;
9153 list_for_each(node, &adev->usecase_list) {
9154 usecase = node_to_item(node, struct audio_usecase, list);
Anver sadhiquef0efca32021-09-03 15:25:44 +05309155 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
Anver sadhique93f3c912021-08-11 11:19:45 +05309156 (!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 +05309157 ALOGD("BT_SCO ON, switch all in use case to it");
9158 select_devices(adev, usecase->id);
9159 }
Mingshu Pangef517202021-04-22 10:35:00 +08009160 if (usecase->stream.out && (usecase->type == PCM_PLAYBACK ||
9161 usecase->type == VOICE_CALL) &&
Anver sadhique93f3c912021-08-11 11:19:45 +05309162 (!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 +05309163 ALOGD("BT_SCO ON, switch all out use case to it");
9164 select_devices(adev, usecase->id);
9165 }
9166 }
9167 }
9168 else {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05309169 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08009170 audio_extn_sco_reset_configuration();
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08009171 }
9172 }
9173
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009174 status = voice_set_parameters(adev, parms);
9175 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08009176 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009177
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009178 status = platform_set_parameters(adev->platform, parms);
9179 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08009180 goto done;
9181
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009182 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
9183 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07009184 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009185 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
9186 adev->bluetooth_nrec = true;
9187 else
9188 adev->bluetooth_nrec = false;
9189 }
9190
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009191 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
9192 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009193 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
9194 adev->screen_off = false;
9195 else
9196 adev->screen_off = true;
Quinn Male70f20f32019-06-26 16:50:26 -07009197 audio_extn_sound_trigger_update_screen_status(adev->screen_off);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009198 }
9199
Eric Laurent4b084132018-10-19 17:33:43 -07009200 ret = str_parms_get_int(parms, "rotation", &val);
9201 if (ret >= 0) {
9202 bool reverse_speakers = false;
9203 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
9204 switch (val) {
9205 // FIXME: note that the code below assumes that the speakers are in the correct placement
9206 // relative to the user when the device is rotated 90deg from its default rotation. This
9207 // assumption is device-specific, not platform-specific like this code.
9208 case 270:
9209 reverse_speakers = true;
9210 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
9211 break;
9212 case 0:
9213 case 180:
9214 camera_rotation = CAMERA_ROTATION_PORTRAIT;
9215 break;
9216 case 90:
9217 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
9218 break;
9219 default:
9220 ALOGE("%s: unexpected rotation of %d", __func__, val);
9221 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07009222 }
Eric Laurent4b084132018-10-19 17:33:43 -07009223 if (status == 0) {
9224 // check and set swap
9225 // - check if orientation changed and speaker active
9226 // - set rotation and cache the rotation value
9227 adev->camera_orientation =
9228 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
9229 if (!audio_extn_is_maxx_audio_enabled())
9230 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
9231 }
9232 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07009233
Mingming Yin514a8bc2014-07-29 15:22:21 -07009234 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
9235 if (ret >= 0) {
9236 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
9237 adev->bt_wb_speech_enabled = true;
9238 else
9239 adev->bt_wb_speech_enabled = false;
9240 }
9241
Zhou Song12c29502019-03-16 10:37:18 +08009242 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
9243 if (ret >= 0) {
9244 val = atoi(value);
9245 adev->swb_speech_mode = val;
9246 }
9247
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07009248 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
9249 if (ret >= 0) {
9250 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309251 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08009252 if (audio_is_output_device(val) &&
9253 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07009254 ALOGV("cache new ext disp type and edid");
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07009255 platform_get_controller_stream_from_params(parms, &controller, &stream);
9256 platform_set_ext_display_device_v2(adev->platform, controller, stream);
9257 ret = platform_get_ext_disp_type_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07009258 if (ret < 0) {
9259 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05309260 } else {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07009261 platform_cache_edid_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07009262 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309263 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07009264 /*
9265 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
9266 * Per AudioPolicyManager, USB device is higher priority than WFD.
9267 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
9268 * If WFD use case occupies AFE proxy, it may result unintended behavior while
9269 * starting voice call on USB
9270 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08009271 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309272 if (ret >= 0)
9273 audio_extn_usb_add_device(device, atoi(value));
9274
Zhou Song6f862822017-11-06 17:27:57 +08009275 if (!audio_extn_usb_is_tunnel_supported()) {
9276 ALOGV("detected USB connect .. disable proxy");
9277 adev->allow_afe_proxy_usage = false;
9278 }
Zhou Song503196b2021-07-23 17:31:05 +08009279 } else if (audio_is_hearing_aid_out_device(device) &&
9280 property_get_bool("persist.vendor.audio.ha_proxy.enabled", false)) {
9281 adev->ha_proxy_enable = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07009282 }
9283 }
9284
9285 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
9286 if (ret >= 0) {
9287 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309288 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07009289 /*
9290 * The HDMI / Displayport disconnect handling has been moved to
9291 * audio extension to ensure that its parameters are not
9292 * invalidated prior to updating sysfs of the disconnect event
9293 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
9294 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309295 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08009296 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309297 if (ret >= 0)
9298 audio_extn_usb_remove_device(device, atoi(value));
9299
Zhou Song6f862822017-11-06 17:27:57 +08009300 if (!audio_extn_usb_is_tunnel_supported()) {
9301 ALOGV("detected USB disconnect .. enable proxy");
9302 adev->allow_afe_proxy_usage = true;
9303 }
Zhou Song503196b2021-07-23 17:31:05 +08009304 } else if (audio_is_hearing_aid_out_device(device)) {
9305 adev->ha_proxy_enable = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07009306 }
9307 }
9308
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009309 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08009310
9311 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08009312 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309313 struct audio_usecase *usecase;
9314 struct listnode *node;
9315 list_for_each(node, &adev->usecase_list) {
9316 usecase = node_to_item(node, struct audio_usecase, list);
Weiyin Jiangff56ff32020-05-08 14:32:21 +08009317 if ((usecase->stream.out == NULL) || (usecase->type != PCM_PLAYBACK))
9318 continue;
9319
9320 if (is_a2dp_out_device_type(&usecase->device_list)) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309321 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05309322 audio_extn_a2dp_set_handoff_mode(true);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05309323 ALOGD("Switching to speaker and muting the stream before select_devices");
9324 check_a2dp_restore_l(adev, usecase->stream.out, false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309325 //force device switch to re configure encoder
9326 select_devices(adev, usecase->id);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05309327 ALOGD("Unmuting the stream after select_devices");
Zhou Songbaddf9f2020-11-20 13:57:39 +08009328 check_a2dp_restore_l(adev, usecase->stream.out, true);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05309329 audio_extn_a2dp_set_handoff_mode(false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309330 break;
Zhou Songd01e7a22020-09-23 22:49:01 +08009331 } else if (is_offload_usecase(usecase->stream.out->usecase)) {
Weiyin Jiang280ea742020-09-08 20:28:22 +08009332 pthread_mutex_lock(&usecase->stream.out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +08009333 if (usecase->stream.out->a2dp_muted) {
Weiyin Jiang280ea742020-09-08 20:28:22 +08009334 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
9335 reassign_device_list(&usecase->stream.out->device_list,
9336 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, "");
9337 check_a2dp_restore_l(adev, usecase->stream.out, true);
9338 break;
9339 }
9340 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309341 }
9342 }
9343 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009344
9345 //handle vr audio setparam
9346 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9347 value, sizeof(value));
9348 if (ret >= 0) {
9349 ALOGI("Setting vr mode to be %s", value);
9350 if (!strncmp(value, "true", 4)) {
9351 adev->vr_audio_mode_enabled = true;
9352 ALOGI("Setting vr mode to true");
9353 } else if (!strncmp(value, "false", 5)) {
9354 adev->vr_audio_mode_enabled = false;
9355 ALOGI("Setting vr mode to false");
9356 } else {
9357 ALOGI("wrong vr mode set");
9358 }
9359 }
9360
Eric Laurent4b084132018-10-19 17:33:43 -07009361 //FIXME: to be replaced by proper video capture properties API
9362 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
9363 if (ret >= 0) {
9364 int camera_facing = CAMERA_FACING_BACK;
9365 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
9366 camera_facing = CAMERA_FACING_FRONT;
9367 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
9368 camera_facing = CAMERA_FACING_BACK;
9369 else {
9370 ALOGW("%s: invalid camera facing value: %s", __func__, value);
9371 goto done;
9372 }
9373 adev->camera_orientation =
9374 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
9375 struct audio_usecase *usecase;
9376 struct listnode *node;
9377 list_for_each(node, &adev->usecase_list) {
9378 usecase = node_to_item(node, struct audio_usecase, list);
9379 struct stream_in *in = usecase->stream.in;
9380 if (usecase->type == PCM_CAPTURE && in != NULL &&
9381 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
9382 select_devices(adev, in->usecase);
9383 }
9384 }
9385 }
9386
Naresh Tannirucd2353e2016-08-19 00:37:25 +05309387 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08009388done:
9389 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009390 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05309391error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009392 ALOGV("%s: exit with code(%d)", __func__, status);
9393 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009394}
9395
9396static char* adev_get_parameters(const struct audio_hw_device *dev,
9397 const char *keys)
9398{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05309399 ALOGD("%s:%s", __func__, keys);
9400
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009401 struct audio_device *adev = (struct audio_device *)dev;
9402 struct str_parms *reply = str_parms_create();
9403 struct str_parms *query = str_parms_create_str(keys);
9404 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05309405 char value[256] = {0};
9406 int ret = 0;
9407
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009408 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08009409 if (reply) {
9410 str_parms_destroy(reply);
9411 }
9412 if (query) {
9413 str_parms_destroy(query);
9414 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009415 ALOGE("adev_get_parameters: failed to create query or reply");
9416 return NULL;
9417 }
9418
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009419 //handle vr audio getparam
9420
9421 ret = str_parms_get_str(query,
9422 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9423 value, sizeof(value));
9424
9425 if (ret >= 0) {
9426 bool vr_audio_enabled = false;
9427 pthread_mutex_lock(&adev->lock);
9428 vr_audio_enabled = adev->vr_audio_mode_enabled;
9429 pthread_mutex_unlock(&adev->lock);
9430
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07009431 ALOGV("getting vr mode to %d", vr_audio_enabled);
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009432
9433 if (vr_audio_enabled) {
9434 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9435 "true");
9436 goto exit;
9437 } else {
9438 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9439 "false");
9440 goto exit;
9441 }
9442 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009443
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009444 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009445 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08009446 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08009447 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009448 platform_get_parameters(adev->platform, query, reply);
justinwengd5395152019-11-04 12:23:09 +08009449 audio_extn_ma_get_parameters(adev, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05309450 pthread_mutex_unlock(&adev->lock);
9451
Naresh Tannirud7205b62014-06-20 02:54:48 +05309452exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009453 str = str_parms_to_str(reply);
9454 str_parms_destroy(query);
9455 str_parms_destroy(reply);
9456
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07009457 ALOGV("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009458 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009459}
9460
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009461static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009462{
9463 return 0;
9464}
9465
9466static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
9467{
Haynes Mathew George5191a852013-09-11 14:19:36 -07009468 int ret;
9469 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08009470
9471 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
9472
Haynes Mathew George5191a852013-09-11 14:19:36 -07009473 pthread_mutex_lock(&adev->lock);
9474 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07009475 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07009476 pthread_mutex_unlock(&adev->lock);
9477 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009478}
9479
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009480static int adev_set_master_volume(struct audio_hw_device *dev __unused,
9481 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009482{
9483 return -ENOSYS;
9484}
9485
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009486static int adev_get_master_volume(struct audio_hw_device *dev __unused,
9487 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009488{
9489 return -ENOSYS;
9490}
9491
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009492static int adev_set_master_mute(struct audio_hw_device *dev __unused,
9493 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009494{
9495 return -ENOSYS;
9496}
9497
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009498static int adev_get_master_mute(struct audio_hw_device *dev __unused,
9499 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009500{
9501 return -ENOSYS;
9502}
9503
9504static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
9505{
9506 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07009507 struct listnode *node;
9508 struct audio_usecase *usecase = NULL;
9509 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08009510
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009511 pthread_mutex_lock(&adev->lock);
9512 if (adev->mode != mode) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309513 ALOGD("%s: mode %d , prev_mode %d \n", __func__, mode , adev->mode);
9514 adev->prev_mode = adev->mode; /* prev_mode is kept to handle voip concurrency*/
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009515 adev->mode = mode;
Weiyin Jiang96b96f72020-09-22 16:48:19 +08009516 if (mode == AUDIO_MODE_CALL_SCREEN) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309517 adev->current_call_output = adev->primary_output;
9518 voice_start_call(adev);
9519 } else if (voice_is_in_call_or_call_screen(adev) &&
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08009520 (mode == AUDIO_MODE_NORMAL ||
9521 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07009522 list_for_each(node, &adev->usecase_list) {
9523 usecase = node_to_item(node, struct audio_usecase, list);
9524 if (usecase->type == VOICE_CALL)
9525 break;
9526 }
9527 if (usecase &&
9528 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
9529 ret = audio_extn_usb_check_and_set_svc_int(usecase,
9530 true);
9531 if (ret != 0) {
9532 /* default service interval was successfully updated,
9533 reopen USB backend with new service interval */
9534 check_usecases_codec_backend(adev,
9535 usecase,
9536 usecase->out_snd_device);
9537 }
9538 }
9539
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009540 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07009541 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009542 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08009543 // restore device for other active usecases after stop call
9544 list_for_each(node, &adev->usecase_list) {
9545 usecase = node_to_item(node, struct audio_usecase, list);
9546 select_devices(adev, usecase->id);
9547 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009548 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009549 }
9550 pthread_mutex_unlock(&adev->lock);
9551 return 0;
9552}
9553
9554static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
9555{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009556 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08009557 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009558
9559 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08009560 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009561 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009562
Derek Chend2530072014-11-24 12:39:14 -08009563 if (adev->ext_hw_plugin)
9564 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009565
9566 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009567 pthread_mutex_unlock(&adev->lock);
9568
9569 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009570}
9571
9572static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
9573{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009574 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009575 return 0;
9576}
9577
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009578static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009579 const struct audio_config *config)
9580{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009581 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009582
Aalique Grahame22e49102018-12-18 14:23:57 -08009583 /* Don't know if USB HIFI in this context so use true to be conservative */
9584 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9585 true /*is_usb_hifi */) != 0)
9586 return 0;
9587
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009588 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
9589 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009590}
9591
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009592static bool adev_input_allow_hifi_record(struct audio_device *adev,
9593 audio_devices_t devices,
9594 audio_input_flags_t flags,
9595 audio_source_t source) {
9596 const bool allowed = true;
9597
9598 if (!audio_is_usb_in_device(devices))
9599 return !allowed;
9600
9601 switch (flags) {
9602 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009603 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07009604 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
9605 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009606 default:
9607 return !allowed;
9608 }
9609
9610 switch (source) {
9611 case AUDIO_SOURCE_DEFAULT:
9612 case AUDIO_SOURCE_MIC:
9613 case AUDIO_SOURCE_UNPROCESSED:
9614 break;
9615 default:
9616 return !allowed;
9617 }
9618
9619 switch (adev->mode) {
9620 case 0:
9621 break;
9622 default:
9623 return !allowed;
9624 }
9625
9626 return allowed;
9627}
9628
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009629static int adev_update_voice_comm_input_stream(struct stream_in *in,
9630 struct audio_config *config)
9631{
9632 bool valid_rate = (config->sample_rate == 8000 ||
9633 config->sample_rate == 16000 ||
9634 config->sample_rate == 32000 ||
9635 config->sample_rate == 48000);
9636 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
9637
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009638 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08009639 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009640 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9641 in->config = default_pcm_config_voip_copp;
9642 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
9643 DEFAULT_VOIP_BUF_DURATION_MS,
9644 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009645 } else {
9646 ALOGW("%s No valid input in voip, use defaults"
9647 "sample rate %u, channel mask 0x%X",
9648 __func__, config->sample_rate, in->channel_mask);
9649 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009650 in->config.rate = config->sample_rate;
9651 in->sample_rate = config->sample_rate;
9652 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009653 //XXX needed for voice_extn_compress_voip_open_input_stream
9654 in->config.rate = config->sample_rate;
9655 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
Shalini Manjunathaa763cc42019-08-23 15:13:46 +05309656 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009657 voice_extn_compress_voip_is_active(in->dev)) &&
9658 (voice_extn_compress_voip_is_format_supported(in->format)) &&
9659 valid_rate && valid_ch) {
9660 voice_extn_compress_voip_open_input_stream(in);
9661 // update rate entries to match config from AF
9662 in->config.rate = config->sample_rate;
9663 in->sample_rate = config->sample_rate;
9664 } else {
9665 ALOGW("%s compress voip not active, use defaults", __func__);
9666 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009667 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009668 return 0;
9669}
9670
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009671static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07009672 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009673 audio_devices_t devices,
9674 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009675 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309676 audio_input_flags_t flags,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009677 const char *address,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009678 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009679{
9680 struct audio_device *adev = (struct audio_device *)dev;
9681 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009682 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009683 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009684 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05309685 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009686 bool is_usb_dev = audio_is_usb_in_device(devices);
9687 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
9688 devices,
9689 flags,
9690 source);
Andy Hung94320602018-10-29 18:31:12 -07009691 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
9692 " sample_rate %u, channel_mask %#x, format %#x",
9693 __func__, flags, is_usb_dev, may_use_hifi_record,
9694 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309695
kunleizdff872d2018-08-20 14:40:33 +08009696 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08009697 is_usb_dev = false;
9698 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
9699 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
9700 __func__, devices);
9701 }
9702
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009703 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009704
9705 if (!(is_usb_dev && may_use_hifi_record)) {
9706 if (config->sample_rate == 0)
9707 config->sample_rate = 48000;
9708 if (config->channel_mask == AUDIO_CHANNEL_NONE)
9709 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9710 if (config->format == AUDIO_FORMAT_DEFAULT)
9711 config->format = AUDIO_FORMAT_PCM_16_BIT;
9712
9713 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
9714
Aalique Grahame22e49102018-12-18 14:23:57 -08009715 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9716 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009717 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05309718 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009719
9720 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009721
9722 if (!in) {
9723 ALOGE("failed to allocate input stream");
9724 return -ENOMEM;
9725 }
9726
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309727 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05309728 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
9729 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009730 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07009731 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009732
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009733 in->stream.common.get_sample_rate = in_get_sample_rate;
9734 in->stream.common.set_sample_rate = in_set_sample_rate;
9735 in->stream.common.get_buffer_size = in_get_buffer_size;
9736 in->stream.common.get_channels = in_get_channels;
9737 in->stream.common.get_format = in_get_format;
9738 in->stream.common.set_format = in_set_format;
9739 in->stream.common.standby = in_standby;
9740 in->stream.common.dump = in_dump;
9741 in->stream.common.set_parameters = in_set_parameters;
9742 in->stream.common.get_parameters = in_get_parameters;
9743 in->stream.common.add_audio_effect = in_add_audio_effect;
9744 in->stream.common.remove_audio_effect = in_remove_audio_effect;
9745 in->stream.set_gain = in_set_gain;
9746 in->stream.read = in_read;
9747 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08009748 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309749 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07009750 in->stream.set_microphone_direction = in_set_microphone_direction;
9751 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07009752 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009753
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009754 list_init(&in->device_list);
9755 update_device_list(&in->device_list, devices, address, true);
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009756 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009757 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009758 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009759 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009760 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07009761 in->bit_width = 16;
9762 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07009763 in->direction = MIC_DIRECTION_UNSPECIFIED;
9764 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08009765 list_init(&in->aec_list);
9766 list_init(&in->ns_list);
Phil Burkd898ba62019-06-20 12:49:01 -07009767 in->mmap_shared_memory_fd = -1; // not open
Haynes Mathew George46740472017-10-27 18:40:12 -07009768
Andy Hung94320602018-10-29 18:31:12 -07009769 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08009770 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
9771 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
9772 /* Force channel config requested to mono if incall
9773 record is being requested for only uplink/downlink */
9774 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
9775 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9776 ret = -EINVAL;
9777 goto err_open;
9778 }
9779 }
9780
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009781 if (is_usb_dev && may_use_hifi_record) {
9782 /* HiFi record selects an appropriate format, channel, rate combo
9783 depending on sink capabilities*/
9784 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
9785 &config->format,
9786 &in->supported_formats[0],
9787 MAX_SUPPORTED_FORMATS,
9788 &config->channel_mask,
9789 &in->supported_channel_masks[0],
9790 MAX_SUPPORTED_CHANNEL_MASKS,
9791 &config->sample_rate,
9792 &in->supported_sample_rates[0],
9793 MAX_SUPPORTED_SAMPLE_RATES);
9794 if (ret != 0) {
9795 ret = -EINVAL;
9796 goto err_open;
9797 }
9798 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009799 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309800 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05309801 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
9802 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
9803 in->config.format = PCM_FORMAT_S32_LE;
9804 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309805 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
9806 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
9807 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
9808 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
9809 bool ret_error = false;
9810 in->bit_width = 24;
9811 /* 24 bit is restricted to UNPROCESSED source only,also format supported
9812 from HAL is 24_packed and 8_24
9813 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
9814 24_packed return error indicating supported format is 24_packed
9815 *> In case of any other source requesting 24 bit or float return error
9816 indicating format supported is 16 bit only.
9817
9818 on error flinger will retry with supported format passed
9819 */
9820 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
9821 (source != AUDIO_SOURCE_CAMCORDER)) {
9822 config->format = AUDIO_FORMAT_PCM_16_BIT;
9823 if (config->sample_rate > 48000)
9824 config->sample_rate = 48000;
9825 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07009826 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
9827 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309828 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
9829 ret_error = true;
9830 }
9831
9832 if (ret_error) {
9833 ret = -EINVAL;
9834 goto err_open;
9835 }
9836 }
9837
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009838 in->channel_mask = config->channel_mask;
9839 in->format = config->format;
9840
9841 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309842
Huicheng Liu1404ba12020-09-11 01:03:25 -04009843 /* validate bus device address */
9844 if (compare_device_type(&in->device_list, AUDIO_DEVICE_IN_BUS)) {
9845 /* extract car audio stream index */
9846 in->car_audio_stream =
9847 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
9848 if (in->car_audio_stream < 0) {
9849 ALOGE("%s: invalid car audio stream %x",
9850 __func__, in->car_audio_stream);
9851 ret = -EINVAL;
9852 goto err_open;
9853 }
9854 ALOGV("%s: car_audio_stream 0x%x", __func__, in->car_audio_stream);
Huicheng Liuea4fd422021-01-12 18:34:50 -05009855 ret = audio_extn_auto_hal_open_input_stream(in);
9856 if (ret) {
9857 ALOGE("%s: Failed to open input stream for bus device", __func__);
9858 ret = -EINVAL;
9859 goto err_open;
9860 }
Huicheng Liu1404ba12020-09-11 01:03:25 -04009861 }
9862
Susan Wange3959562021-03-11 11:50:26 -05009863 /* reassign use case for echo reference stream on automotive platforms */
9864 if (in->source == AUDIO_SOURCE_ECHO_REFERENCE) {
9865 ret = audio_extn_auto_hal_open_echo_reference_stream(in);
9866 }
9867
Kogara Naveen Kumar379ff692022-01-31 11:56:51 +05309868 if ((in->source == AUDIO_SOURCE_FM_TUNER) || (devices == AUDIO_DEVICE_IN_FM_TUNER)) {
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309869 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
9870 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
9871 else {
9872 ret = -EINVAL;
9873 goto err_open;
9874 }
9875 }
9876
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +05309877 if ((config->sample_rate == 48000 ||
9878 config->sample_rate == 32000 ||
9879 config->sample_rate == 24000 ||
9880 config->sample_rate == 16000 ||
9881 config->sample_rate == 8000)&&
Deeraj Somanfa377bf2019-02-06 12:57:59 +05309882 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
9883 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009884 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
9885 is_low_latency = true;
9886#if LOW_LATENCY_CAPTURE_USE_CASE
Revathi Uddarajud9f23d92020-07-27 10:55:06 +05309887 if ((flags & AUDIO_INPUT_FLAG_VOIP_TX) != 0)
9888 in->usecase = USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY;
9889 else
9890 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009891#endif
9892 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08009893 if (!in->realtime) {
9894 in->config = pcm_config_audio_capture;
9895 frame_size = audio_stream_in_frame_size(&in->stream);
9896 buffer_size = get_input_buffer_size(config->sample_rate,
9897 config->format,
9898 channel_count,
9899 is_low_latency);
9900 in->config.period_size = buffer_size / frame_size;
9901 in->config.rate = config->sample_rate;
9902 in->af_period_multiplier = 1;
9903 } else {
9904 // period size is left untouched for rt mode playback
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +05309905 switch(config->sample_rate)
9906 {
9907 case 48000:
9908 in->config = pcm_config_audio_capture_rt_48KHz;
9909 break;
9910 case 32000:
9911 in->config = pcm_config_audio_capture_rt_32KHz;
9912 break;
9913 case 24000:
9914 in->config = pcm_config_audio_capture_rt_24KHz;
9915 break;
9916 case 16000:
9917 in->config = pcm_config_audio_capture_rt_16KHz;
9918 break;
9919 case 8000:
9920 in->config = pcm_config_audio_capture_rt_8KHz;
9921 break;
9922 default:
9923 in->config = pcm_config_audio_capture_rt_48KHz;
9924 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009925 in->af_period_multiplier = af_period_multiplier;
9926 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009927 }
9928
Susan Wangb803cb52021-10-14 12:03:36 -04009929 /* Additional sample rates added below must also be present
9930 in audio_policy_configuration.xml for mmap_no_irq_in */
9931 bool valid_mmap_record_rate = (config->sample_rate == 8000 ||
9932 config->sample_rate == 16000 ||
Susan Wang89da9042021-10-14 12:03:36 -04009933 config->sample_rate == 24000 ||
Susan Wangb803cb52021-10-14 12:03:36 -04009934 config->sample_rate == 32000 ||
9935 config->sample_rate == 48000);
9936 if (valid_mmap_record_rate &&
9937 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009938 in->realtime = 0;
9939 in->usecase = USECASE_AUDIO_RECORD_MMAP;
9940 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07009941 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009942 in->stream.start = in_start;
9943 in->stream.stop = in_stop;
9944 in->stream.create_mmap_buffer = in_create_mmap_buffer;
9945 in->stream.get_mmap_position = in_get_mmap_position;
Ramjee Singhbcb3b6c2021-11-17 13:19:16 +05309946 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009947 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
Haynes Mathew George46740472017-10-27 18:40:12 -07009948 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009949 in->usecase = USECASE_AUDIO_RECORD_HIFI;
9950 in->config = pcm_config_audio_capture;
9951 frame_size = audio_stream_in_frame_size(&in->stream);
9952 buffer_size = get_input_buffer_size(config->sample_rate,
9953 config->format,
9954 channel_count,
9955 false /*is_low_latency*/);
9956 in->config.period_size = buffer_size / frame_size;
9957 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009958 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07009959 switch (config->format) {
9960 case AUDIO_FORMAT_PCM_32_BIT:
9961 in->bit_width = 32;
9962 break;
9963 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
9964 case AUDIO_FORMAT_PCM_8_24_BIT:
9965 in->bit_width = 24;
9966 break;
9967 default:
9968 in->bit_width = 16;
9969 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009970 } else if (is_single_device_type_equal(&in->device_list,
9971 AUDIO_DEVICE_IN_TELEPHONY_RX) ||
9972 is_single_device_type_equal(&in->device_list,
9973 AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009974 if (config->sample_rate == 0)
9975 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9976 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
9977 config->sample_rate != 8000) {
9978 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9979 ret = -EINVAL;
9980 goto err_open;
9981 }
9982 if (config->format == AUDIO_FORMAT_DEFAULT)
9983 config->format = AUDIO_FORMAT_PCM_16_BIT;
9984 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
9985 config->format = AUDIO_FORMAT_PCM_16_BIT;
9986 ret = -EINVAL;
9987 goto err_open;
9988 }
9989
9990 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
Zhou Song62ea0282020-03-22 19:53:01 +08009991 if (adev->ha_proxy_enable &&
9992 is_single_device_type_equal(&in->device_list,
9993 AUDIO_DEVICE_IN_TELEPHONY_RX))
9994 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY2;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009995 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009996 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08009997 in->af_period_multiplier = 1;
9998 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
Shalini Manjunathaac412b32020-01-03 15:00:14 +05309999 (!voice_extn_is_compress_voip_supported()) &&
Aalique Grahame22e49102018-12-18 14:23:57 -080010000 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
10001 (config->sample_rate == 8000 ||
10002 config->sample_rate == 16000 ||
10003 config->sample_rate == 32000 ||
10004 config->sample_rate == 48000) &&
10005 channel_count == 1) {
10006 in->usecase = USECASE_AUDIO_RECORD_VOIP;
10007 in->config = pcm_config_audio_capture;
10008 frame_size = audio_stream_in_frame_size(&in->stream);
10009 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
10010 config->sample_rate,
10011 config->format,
10012 channel_count, false /*is_low_latency*/);
10013 in->config.period_size = buffer_size / frame_size;
10014 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
10015 in->config.rate = config->sample_rate;
10016 in->af_period_multiplier = 1;
Mingshu Pangc2d65042021-01-14 16:19:10 +080010017 } else if (in->realtime) {
Kogara Naveen Kumara688a812022-04-27 16:45:59 +053010018 switch(config->sample_rate)
10019 {
10020 case 48000:
10021 in->config = pcm_config_audio_capture_rt_48KHz;
10022 break;
10023 case 32000:
10024 in->config = pcm_config_audio_capture_rt_32KHz;
10025 break;
10026 case 24000:
10027 in->config = pcm_config_audio_capture_rt_24KHz;
10028 break;
10029 case 16000:
10030 in->config = pcm_config_audio_capture_rt_16KHz;
10031 break;
10032 case 8000:
10033 in->config = pcm_config_audio_capture_rt_8KHz;
10034 break;
10035 default:
10036 in->config = pcm_config_audio_capture_rt_48KHz;
10037 }
Mingshu Pangc2d65042021-01-14 16:19:10 +080010038 in->config.format = pcm_format_from_audio_format(config->format);
10039 in->af_period_multiplier = af_period_multiplier;
Haynes Mathew George46740472017-10-27 18:40:12 -070010040 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +053010041 int ret_val;
10042 pthread_mutex_lock(&adev->lock);
10043 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
10044 in, config, &channel_mask_updated);
10045 pthread_mutex_unlock(&adev->lock);
10046
10047 if (!ret_val) {
10048 if (channel_mask_updated == true) {
10049 ALOGD("%s: return error to retry with updated channel mask (%#x)",
10050 __func__, config->channel_mask);
10051 ret = -EINVAL;
10052 goto err_open;
10053 }
10054 ALOGD("%s: created multi-channel session succesfully",__func__);
10055 } else if (audio_extn_compr_cap_enabled() &&
10056 audio_extn_compr_cap_format_supported(config->format) &&
10057 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
10058 audio_extn_compr_cap_init(in);
10059 } else if (audio_extn_cin_applicable_stream(in)) {
Deeraj Soman14230922019-01-30 16:39:30 +053010060 ret = audio_extn_cin_configure_input_stream(in, config);
Revathi Uddarajud2634032017-12-07 14:42:34 +053010061 if (ret)
10062 goto err_open;
10063 } else {
10064 in->config = pcm_config_audio_capture;
10065 in->config.rate = config->sample_rate;
10066 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +053010067 in->format = config->format;
10068 frame_size = audio_stream_in_frame_size(&in->stream);
10069 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -070010070 config->format,
10071 channel_count,
10072 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +020010073 /* prevent division-by-zero */
10074 if (frame_size == 0) {
10075 ALOGE("%s: Error frame_size==0", __func__);
10076 ret = -EINVAL;
10077 goto err_open;
10078 }
10079
Revathi Uddarajud2634032017-12-07 14:42:34 +053010080 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -080010081 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -080010082
Revathi Uddarajud2634032017-12-07 14:42:34 +053010083 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
10084 /* optionally use VOIP usecase depending on config(s) */
10085 ret = adev_update_voice_comm_input_stream(in, config);
10086 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -080010087
Revathi Uddarajud2634032017-12-07 14:42:34 +053010088 if (ret) {
10089 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
10090 goto err_open;
10091 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -080010092 }
Jaideep Sharmad305a4a2020-02-27 14:29:04 +053010093
10094 /* assign concurrent capture usecase if record has to caried out from
10095 * actual hardware input source */
10096 if (audio_extn_is_concurrent_capture_enabled() &&
10097 !audio_is_virtual_input_source(in->source)) {
Samyak Jainc37062f2019-04-25 18:41:06 +053010098 /* Acquire lock to avoid two concurrent use cases initialized to
10099 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +080010100
Samyak Jainc37062f2019-04-25 18:41:06 +053010101 if (in->usecase == USECASE_AUDIO_RECORD) {
10102 pthread_mutex_lock(&adev->lock);
10103 if (!(adev->pcm_record_uc_state)) {
10104 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
10105 adev->pcm_record_uc_state = 1;
10106 pthread_mutex_unlock(&adev->lock);
Krishna Kishor Jha0f4d8482022-02-18 10:56:05 +053010107 } else if (audio_extn_is_concurrent_pcm_record_enabled()) {
10108 in->usecase = get_record_usecase(adev);
10109 pthread_mutex_unlock(&adev->lock);
Samyak Jainc37062f2019-04-25 18:41:06 +053010110 } else {
10111 pthread_mutex_unlock(&adev->lock);
10112 /* Assign compress record use case for second record */
10113 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
10114 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
10115 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
10116 if (audio_extn_cin_applicable_stream(in)) {
10117 in->sample_rate = config->sample_rate;
Deeraj Soman14230922019-01-30 16:39:30 +053010118 ret = audio_extn_cin_configure_input_stream(in, config);
Samyak Jainc37062f2019-04-25 18:41:06 +053010119 if (ret)
10120 goto err_open;
10121 }
10122 }
10123 }
kunleiz28c73e72019-03-27 17:24:04 +080010124 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -070010125 }
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +053010126
Ramjee Singh82fd0c12019-08-21 16:31:33 +053010127 if (audio_extn_ssr_get_stream() != in)
10128 in->config.channels = channel_count;
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -070010129
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -070010130 in->sample_rate = in->config.rate;
10131
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010132 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
10133 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010134 &in->device_list, flags, in->format,
Haynes Mathew George4ffef292017-11-21 15:08:02 -080010135 in->sample_rate, in->bit_width,
10136 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +053010137 register_format(in->format, in->supported_formats);
10138 register_channel_mask(in->channel_mask, in->supported_channel_masks);
10139 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010140
Dechen Chai22768452021-07-30 09:29:16 +053010141#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -080010142 in->error_log = error_log_create(
10143 ERROR_LOG_ENTRIES,
10144 1000000000 /* aggregate consecutive identical errors within one second */);
Dechen Chai22768452021-07-30 09:29:16 +053010145#endif
Aalique Grahame22e49102018-12-18 14:23:57 -080010146
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010147 /* This stream could be for sound trigger lab,
10148 get sound trigger pcm if present */
10149 audio_extn_sound_trigger_check_and_get_session(in);
10150
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010151 lock_input_stream(in);
10152 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
10153 pthread_mutex_lock(&adev->lock);
10154 in->card_status = adev->card_status;
10155 pthread_mutex_unlock(&adev->lock);
10156 pthread_mutex_unlock(&in->lock);
10157
Aalique Grahame22e49102018-12-18 14:23:57 -080010158 stream_app_type_cfg_init(&in->app_type_cfg);
10159
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010160 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -080010161
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010162 ret = io_streams_map_insert(adev, &in->stream.common,
10163 handle, AUDIO_PATCH_HANDLE_NONE);
10164 if (ret != 0)
10165 goto err_open;
10166
Susan Wang6dd13092021-01-25 10:27:11 -050010167 in->in_ctxt.input = in;
Derek Chenf939fb72018-11-13 13:34:41 -080010168
10169 pthread_mutex_lock(&adev->lock);
Susan Wang6dd13092021-01-25 10:27:11 -050010170 list_add_tail(&adev->active_inputs_list, &in->in_ctxt.list);
Derek Chenf939fb72018-11-13 13:34:41 -080010171 pthread_mutex_unlock(&adev->lock);
10172
Eric Laurent994a6932013-07-17 11:51:42 -070010173 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -080010174 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010175
10176err_open:
Krishna Kishor Jha0f4d8482022-02-18 10:56:05 +053010177 if (audio_extn_is_concurrent_pcm_record_enabled() && is_pcm_record_usecase(in->usecase)) {
10178 free_record_usecase(adev, in->usecase);
10179 } else if (in->usecase == USECASE_AUDIO_RECORD) {
Samyak Jainc37062f2019-04-25 18:41:06 +053010180 pthread_mutex_lock(&adev->lock);
10181 adev->pcm_record_uc_state = 0;
10182 pthread_mutex_unlock(&adev->lock);
10183 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010184 free(in);
10185 *stream_in = NULL;
10186 return ret;
10187}
10188
10189static void adev_close_input_stream(struct audio_hw_device *dev,
10190 struct audio_stream_in *stream)
10191{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080010192 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -070010193 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -070010194 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +053010195
Sidipotu Ashokf43018c2014-05-02 16:21:50 +053010196 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080010197
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010198 if (in == NULL) {
10199 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
10200 return;
10201 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010202 io_streams_map_remove(adev, in->capture_handle);
10203
Susan Wang6dd13092021-01-25 10:27:11 -050010204 // remove out_ctxt early to prevent the stream
10205 // being opened in a race condition
10206 pthread_mutex_lock(&adev->lock);
10207 list_remove(&in->in_ctxt.list);
10208 pthread_mutex_unlock(&adev->lock);
10209
kunleiz70e57612018-12-28 17:50:23 +080010210 /* must deregister from sndmonitor first to prevent races
10211 * between the callback and close_stream
10212 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010213 audio_extn_snd_mon_unregister_listener(stream);
10214
kunleiz70e57612018-12-28 17:50:23 +080010215 /* Disable echo reference if there are no active input, hfp call
10216 * and sound trigger while closing input stream
10217 */
Eric Laurent637e2d42018-11-15 12:24:31 -080010218 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +080010219 !audio_extn_hfp_is_active(adev) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010220 !audio_extn_sound_trigger_check_ec_ref_enable()) {
10221 struct listnode out_devices;
10222 list_init(&out_devices);
10223 platform_set_echo_reference(adev, false, &out_devices);
10224 } else
kunleiz70e57612018-12-28 17:50:23 +080010225 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +053010226
Dechen Chai22768452021-07-30 09:29:16 +053010227#ifndef LINUX_ENABLED
Weiyin Jiang2995f662019-04-17 14:25:12 +080010228 error_log_destroy(in->error_log);
10229 in->error_log = NULL;
Dechen Chai22768452021-07-30 09:29:16 +053010230#endif
Pallavid7c7a272018-01-16 11:22:55 +053010231
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080010232 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +053010233 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080010234 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +053010235 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080010236 if (ret != 0)
10237 ALOGE("%s: Compress voip input cannot be closed, error:%d",
10238 __func__, ret);
10239 } else
10240 in_standby(&stream->common);
10241
Weiyin Jiang280ea742020-09-08 20:28:22 +080010242 pthread_mutex_destroy(&in->lock);
10243 pthread_mutex_destroy(&in->pre_lock);
10244
Revathi Uddarajud2634032017-12-07 14:42:34 +053010245 pthread_mutex_lock(&adev->lock);
Krishna Kishor Jha0f4d8482022-02-18 10:56:05 +053010246 if (audio_extn_is_concurrent_pcm_record_enabled() && is_pcm_record_usecase(in->usecase)) {
10247 free_record_usecase(adev, in->usecase);
10248 } else if (in->usecase == USECASE_AUDIO_RECORD) {
Samyak Jain15fda662018-12-18 16:40:52 +053010249 adev->pcm_record_uc_state = 0;
10250 }
10251
Kunlei Zhang5d5d8d92020-02-26 15:00:59 +080010252 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
10253 adev->enable_voicerx = false;
10254 }
10255
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -070010256 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -070010257 audio_extn_ssr_deinit();
10258 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010259
Garmond Leunge2433c32017-09-28 21:51:22 -070010260 if (audio_extn_ffv_get_stream() == in) {
10261 audio_extn_ffv_stream_deinit();
10262 }
10263
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010264 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -070010265 audio_extn_compr_cap_format_supported(in->config.format))
10266 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +053010267
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +053010268 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +053010269 audio_extn_cin_free_input_stream_resources(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010270
Mingming Yinfd7607b2016-01-22 12:48:44 -080010271 if (in->is_st_session) {
10272 ALOGV("%s: sound trigger pcm stop lab", __func__);
10273 audio_extn_sound_trigger_stop_lab(in);
10274 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010275 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +053010276 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010277 return;
10278}
10279
Aalique Grahame22e49102018-12-18 14:23:57 -080010280/* verifies input and output devices and their capabilities.
10281 *
10282 * This verification is required when enabling extended bit-depth or
10283 * sampling rates, as not all qcom products support it.
10284 *
10285 * Suitable for calling only on initialization such as adev_open().
10286 * It fills the audio_device use_case_table[] array.
10287 *
10288 * Has a side-effect that it needs to configure audio routing / devices
10289 * in order to power up the devices and read the device parameters.
10290 * It does not acquire any hw device lock. Should restore the devices
10291 * back to "normal state" upon completion.
10292 */
10293static int adev_verify_devices(struct audio_device *adev)
10294{
10295 /* enumeration is a bit difficult because one really wants to pull
10296 * the use_case, device id, etc from the hidden pcm_device_table[].
10297 * In this case there are the following use cases and device ids.
10298 *
10299 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
10300 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
10301 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
10302 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
10303 * [USECASE_AUDIO_RECORD] = {0, 0},
10304 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
10305 * [USECASE_VOICE_CALL] = {2, 2},
10306 *
10307 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
10308 * USECASE_VOICE_CALL omitted, but possible for either input or output.
10309 */
10310
10311 /* should be the usecases enabled in adev_open_input_stream() */
10312 static const int test_in_usecases[] = {
10313 USECASE_AUDIO_RECORD,
10314 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
10315 };
10316 /* should be the usecases enabled in adev_open_output_stream()*/
10317 static const int test_out_usecases[] = {
10318 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
10319 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
10320 };
10321 static const usecase_type_t usecase_type_by_dir[] = {
10322 PCM_PLAYBACK,
10323 PCM_CAPTURE,
10324 };
10325 static const unsigned flags_by_dir[] = {
10326 PCM_OUT,
10327 PCM_IN,
10328 };
10329
10330 size_t i;
10331 unsigned dir;
10332 const unsigned card_id = adev->snd_card;
10333
10334 for (dir = 0; dir < 2; ++dir) {
10335 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
10336 const unsigned flags_dir = flags_by_dir[dir];
10337 const size_t testsize =
10338 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
10339 const int *testcases =
10340 dir ? test_in_usecases : test_out_usecases;
10341 const audio_devices_t audio_device =
10342 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
10343
10344 for (i = 0; i < testsize; ++i) {
10345 const audio_usecase_t audio_usecase = testcases[i];
10346 int device_id;
10347 struct pcm_params **pparams;
10348 struct stream_out out;
10349 struct stream_in in;
10350 struct audio_usecase uc_info;
10351 int retval;
10352
10353 pparams = &adev->use_case_table[audio_usecase];
10354 pcm_params_free(*pparams); /* can accept null input */
10355 *pparams = NULL;
10356
10357 /* find the device ID for the use case (signed, for error) */
10358 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
10359 if (device_id < 0)
10360 continue;
10361
10362 /* prepare structures for device probing */
10363 memset(&uc_info, 0, sizeof(uc_info));
10364 uc_info.id = audio_usecase;
10365 uc_info.type = usecase_type;
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010366 list_init(&uc_info.device_list);
Aalique Grahame22e49102018-12-18 14:23:57 -080010367 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -080010368 memset(&in, 0, sizeof(in));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010369 list_init(&in.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010370 update_device_list(&in.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -080010371 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
10372 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -080010373 }
10374 memset(&out, 0, sizeof(out));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010375 list_init(&out.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010376 update_device_list(&out.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -080010377 uc_info.stream.out = &out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010378 update_device_list(&uc_info.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -080010379 uc_info.in_snd_device = SND_DEVICE_NONE;
10380 uc_info.out_snd_device = SND_DEVICE_NONE;
10381 list_add_tail(&adev->usecase_list, &uc_info.list);
10382
10383 /* select device - similar to start_(in/out)put_stream() */
10384 retval = select_devices(adev, audio_usecase);
10385 if (retval >= 0) {
10386 *pparams = pcm_params_get(card_id, device_id, flags_dir);
10387#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -070010388 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -080010389 if (*pparams) {
10390 ALOGV("%s: (%s) card %d device %d", __func__,
10391 dir ? "input" : "output", card_id, device_id);
10392 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
10393 } else {
10394 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
10395 }
10396#endif
10397 }
10398
10399 /* deselect device - similar to stop_(in/out)put_stream() */
10400 /* 1. Get and set stream specific mixer controls */
10401 retval = disable_audio_route(adev, &uc_info);
10402 /* 2. Disable the rx device */
10403 retval = disable_snd_device(adev,
10404 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
10405 list_remove(&uc_info.list);
10406 }
10407 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010408 return 0;
10409}
10410
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010411int update_patch(unsigned int num_sources,
10412 const struct audio_port_config *sources,
10413 unsigned int num_sinks,
10414 const struct audio_port_config *sinks,
10415 audio_patch_handle_t handle,
10416 struct audio_patch_info *p_info,
10417 patch_type_t patch_type, bool new_patch)
10418{
Aniket Kumar Latad13758f2020-08-06 15:11:36 -070010419 ALOGV("%s: enter", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010420
10421 if (p_info == NULL) {
10422 ALOGE("%s: Invalid patch pointer", __func__);
10423 return -EINVAL;
10424 }
10425
10426 if (new_patch) {
10427 p_info->patch = (struct audio_patch *) calloc(1, sizeof(struct audio_patch));
10428 if (p_info->patch == NULL) {
10429 ALOGE("%s: Could not allocate patch", __func__);
10430 return -ENOMEM;
10431 }
10432 }
10433
10434 p_info->patch->id = handle;
10435 p_info->patch->num_sources = num_sources;
10436 p_info->patch->num_sinks = num_sinks;
10437
10438 for (int i = 0; i < num_sources; i++)
10439 p_info->patch->sources[i] = sources[i];
10440 for (int i = 0; i < num_sinks; i++)
10441 p_info->patch->sinks[i] = sinks[i];
10442
10443 p_info->patch_type = patch_type;
10444 return 0;
10445}
10446
10447audio_patch_handle_t generate_patch_handle()
10448{
10449 static audio_patch_handle_t patch_handle = AUDIO_PATCH_HANDLE_NONE;
10450 if (++patch_handle < 0)
10451 patch_handle = AUDIO_PATCH_HANDLE_NONE + 1;
10452 return patch_handle;
10453}
10454
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010455int adev_create_audio_patch(struct audio_hw_device *dev,
10456 unsigned int num_sources,
10457 const struct audio_port_config *sources,
10458 unsigned int num_sinks,
10459 const struct audio_port_config *sinks,
10460 audio_patch_handle_t *handle)
10461{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010462 int ret = 0;
10463 struct audio_device *adev = (struct audio_device *)dev;
10464 struct audio_patch_info *p_info = NULL;
10465 patch_type_t patch_type = PATCH_NONE;
10466 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10467 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
10468 struct audio_stream_info *s_info = NULL;
10469 struct audio_stream *stream = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010470 struct listnode devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010471 audio_devices_t device_type = AUDIO_DEVICE_NONE;
10472 bool new_patch = false;
10473 char addr[AUDIO_DEVICE_MAX_ADDRESS_LEN];
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010474
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010475 ALOGD("%s: enter: num sources %d, num_sinks %d, handle %d", __func__,
10476 num_sources, num_sinks, *handle);
10477
10478 if (num_sources == 0 || num_sources > AUDIO_PATCH_PORTS_MAX ||
10479 num_sinks == 0 || num_sinks > AUDIO_PATCH_PORTS_MAX) {
10480 ALOGE("%s: Invalid patch arguments", __func__);
10481 ret = -EINVAL;
10482 goto done;
10483 }
10484
10485 if (num_sources > 1) {
10486 ALOGE("%s: Multiple sources are not supported", __func__);
10487 ret = -EINVAL;
10488 goto done;
10489 }
10490
10491 if (sources == NULL || sinks == NULL) {
10492 ALOGE("%s: Invalid sources or sinks port config", __func__);
10493 ret = -EINVAL;
10494 goto done;
10495 }
10496
10497 ALOGV("%s: source role %d, source type %d", __func__,
10498 sources[0].type, sources[0].role);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010499 list_init(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010500
10501 // Populate source/sink information and fetch stream info
10502 switch (sources[0].type) {
10503 case AUDIO_PORT_TYPE_DEVICE: // Patch for audio capture or loopback
10504 device_type = sources[0].ext.device.type;
10505 strlcpy(&addr[0], &sources[0].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010506 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010507 if (sinks[0].type == AUDIO_PORT_TYPE_MIX) {
10508 patch_type = PATCH_CAPTURE;
10509 io_handle = sinks[0].ext.mix.handle;
10510 input_source = sinks[0].ext.mix.usecase.source;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010511 ALOGD("%s: Capture patch from device %x to mix %d",
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010512 __func__, device_type, io_handle);
10513 } else {
10514 // Device to device patch is not implemented.
10515 // This space will need changes if audio HAL
10516 // handles device to device patches in the future.
10517 patch_type = PATCH_DEVICE_LOOPBACK;
10518 }
10519 break;
10520 case AUDIO_PORT_TYPE_MIX: // Patch for audio playback
10521 io_handle = sources[0].ext.mix.handle;
10522 for (int i = 0; i < num_sinks; i++) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010523 device_type = sinks[i].ext.device.type;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010524 strlcpy(&addr[0], &sinks[i].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010525 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010526 }
10527 patch_type = PATCH_PLAYBACK;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010528 ALOGD("%s: Playback patch from mix handle %d to device %x",
10529 __func__, io_handle, get_device_types(&devices));
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010530 break;
10531 case AUDIO_PORT_TYPE_SESSION:
10532 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010533 ALOGE("%s: Unsupported source type %d", __func__, sources[0].type);
10534 ret = -EINVAL;
10535 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010536 }
10537
10538 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010539
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010540 // Generate patch info and update patch
10541 if (*handle == AUDIO_PATCH_HANDLE_NONE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010542 *handle = generate_patch_handle();
10543 p_info = (struct audio_patch_info *)
10544 calloc(1, sizeof(struct audio_patch_info));
10545 if (p_info == NULL) {
10546 ALOGE("%s: Failed to allocate memory", __func__);
10547 pthread_mutex_unlock(&adev->lock);
10548 ret = -ENOMEM;
10549 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010550 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010551 new_patch = true;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010552 } else {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010553 p_info = fetch_patch_info_l(adev, *handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010554 if (p_info == NULL) {
10555 ALOGE("%s: Unable to fetch patch for received patch handle %d",
10556 __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010557 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010558 ret = -EINVAL;
10559 goto done;
10560 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010561 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010562 update_patch(num_sources, sources, num_sinks, sinks,
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010563 *handle, p_info, patch_type, new_patch);
10564
10565 // Fetch stream info of associated mix for playback or capture patches
10566 if (p_info->patch_type == PATCH_PLAYBACK ||
10567 p_info->patch_type == PATCH_CAPTURE) {
10568 s_info = hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10569 if (s_info == NULL) {
10570 ALOGE("%s: Failed to obtain stream info", __func__);
10571 if (new_patch)
10572 free(p_info);
10573 pthread_mutex_unlock(&adev->lock);
10574 ret = -EINVAL;
10575 goto done;
10576 }
10577 ALOGV("%s: Fetched stream info with io_handle %d", __func__, io_handle);
10578 s_info->patch_handle = *handle;
10579 stream = s_info->stream;
10580 }
10581 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010582
10583 // Update routing for stream
10584 if (stream != NULL) {
Revathi Uddaraju4255a632021-12-02 05:11:13 -080010585 if (p_info->patch_type == PATCH_PLAYBACK) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010586 ret = route_output_stream((struct stream_out *) stream, &devices);
Revathi Uddaraju4255a632021-12-02 05:11:13 -080010587 clear_devices(&devices);
10588 } else if (p_info->patch_type == PATCH_CAPTURE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010589 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Revathi Uddaraju4255a632021-12-02 05:11:13 -080010590 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010591 if (ret < 0) {
10592 pthread_mutex_lock(&adev->lock);
10593 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10594 if (new_patch)
10595 free(p_info);
10596 pthread_mutex_unlock(&adev->lock);
10597 ALOGE("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10598 goto done;
10599 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010600 }
10601
10602 // Add new patch to patch map
10603 if (!ret && new_patch) {
10604 pthread_mutex_lock(&adev->lock);
10605 hashmapPut(adev->patch_map, (void *) (intptr_t) *handle, (void *) p_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010606 ALOGD("%s: Added a new patch with handle %d", __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010607 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010608 }
10609
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010610done:
10611 audio_extn_hw_loopback_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010612 num_sources,
10613 sources,
10614 num_sinks,
10615 sinks,
10616 handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010617 audio_extn_auto_hal_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010618 num_sources,
10619 sources,
10620 num_sinks,
10621 sinks,
10622 handle);
10623 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010624}
10625
10626int adev_release_audio_patch(struct audio_hw_device *dev,
10627 audio_patch_handle_t handle)
10628{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010629 struct audio_device *adev = (struct audio_device *) dev;
10630 int ret = 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010631 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010632 struct audio_stream *stream = NULL;
Derek Chenf939fb72018-11-13 13:34:41 -080010633
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010634 if (handle == AUDIO_PATCH_HANDLE_NONE) {
10635 ALOGE("%s: Invalid patch handle %d", __func__, handle);
10636 ret = -EINVAL;
10637 goto done;
10638 }
10639
10640 ALOGD("%s: Remove patch with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010641 pthread_mutex_lock(&adev->lock);
10642 struct audio_patch_info *p_info = fetch_patch_info_l(adev, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010643 if (p_info == NULL) {
10644 ALOGE("%s: Patch info not found with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010645 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010646 ret = -EINVAL;
10647 goto done;
10648 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010649 struct audio_patch *patch = p_info->patch;
10650 if (patch == NULL) {
10651 ALOGE("%s: Patch not found for handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010652 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010653 ret = -EINVAL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010654 goto done;
10655 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010656 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10657 switch (patch->sources[0].type) {
10658 case AUDIO_PORT_TYPE_MIX:
10659 io_handle = patch->sources[0].ext.mix.handle;
10660 break;
10661 case AUDIO_PORT_TYPE_DEVICE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010662 if (p_info->patch_type == PATCH_CAPTURE)
10663 io_handle = patch->sinks[0].ext.mix.handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010664 break;
10665 case AUDIO_PORT_TYPE_SESSION:
10666 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010667 pthread_mutex_unlock(&adev->lock);
10668 ret = -EINVAL;
10669 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010670 }
10671
10672 // Remove patch and reset patch handle in stream info
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010673 patch_type_t patch_type = p_info->patch_type;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010674 patch_map_remove_l(adev, handle);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010675 if (patch_type == PATCH_PLAYBACK ||
10676 patch_type == PATCH_CAPTURE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010677 struct audio_stream_info *s_info =
10678 hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10679 if (s_info == NULL) {
10680 ALOGE("%s: stream for io_handle %d is not available", __func__, io_handle);
10681 pthread_mutex_unlock(&adev->lock);
10682 goto done;
10683 }
10684 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10685 stream = s_info->stream;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010686 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010687 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010688
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010689 if (stream != NULL) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010690 struct listnode devices;
10691 list_init(&devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010692 if (patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010693 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010694 else if (patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010695 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010696 }
10697
10698 if (ret < 0)
10699 ALOGW("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10700
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010701done:
10702 audio_extn_hw_loopback_release_audio_patch(dev, handle);
10703 audio_extn_auto_hal_release_audio_patch(dev, handle);
10704
10705 ALOGV("%s: Successfully released patch %d", __func__, handle);
Derek Chenf939fb72018-11-13 13:34:41 -080010706 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010707}
10708
10709int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
10710{
Derek Chenf13dd492018-11-13 14:53:51 -080010711 int ret = 0;
10712
10713 ret = audio_extn_hw_loopback_get_audio_port(dev, config);
10714 ret |= audio_extn_auto_hal_get_audio_port(dev, config);
10715 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010716}
10717
10718int adev_set_audio_port_config(struct audio_hw_device *dev,
10719 const struct audio_port_config *config)
10720{
Derek Chenf13dd492018-11-13 14:53:51 -080010721 int ret = 0;
10722
10723 ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
10724 ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
10725 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010726}
10727
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -070010728static int adev_dump(const audio_hw_device_t *device __unused,
10729 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010730{
10731 return 0;
10732}
10733
10734static int adev_close(hw_device_t *device)
10735{
Aalique Grahame22e49102018-12-18 14:23:57 -080010736 size_t i;
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010737 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -070010738
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010739 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -070010740 return 0;
10741
10742 pthread_mutex_lock(&adev_init_lock);
10743
10744 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +053010745 if (audio_extn_spkr_prot_is_enabled())
10746 audio_extn_spkr_prot_deinit();
Jaideep Sharmaa2b49672019-09-10 20:37:03 +053010747 audio_extn_battery_properties_listener_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010748 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010749 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -080010750 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010751 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -080010752 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010753 audio_extn_utils_release_streams_cfg_lists(
10754 &adev->streams_output_cfg_list,
10755 &adev->streams_input_cfg_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010756 if (audio_extn_qap_is_enabled())
10757 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010758 if (audio_extn_qaf_is_enabled())
10759 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -070010760 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +080010761 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -070010762 free(adev->snd_dev_ref_cnt);
10763 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010764 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
10765 pcm_params_free(adev->use_case_table[i]);
10766 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010767 if (adev->adm_deinit)
10768 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010769 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010770 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010771 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010772 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010773 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010774 if (adev->device_cfg_params) {
10775 free(adev->device_cfg_params);
10776 adev->device_cfg_params = NULL;
10777 }
Derek Chend2530072014-11-24 12:39:14 -080010778 if(adev->ext_hw_plugin)
10779 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -080010780 audio_extn_auto_hal_deinit();
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010781 free_map(adev->patch_map);
10782 free_map(adev->io_streams_map);
Kiran Kandi910e1862013-10-29 13:29:42 -070010783 free(device);
10784 adev = NULL;
10785 }
10786 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +053010787 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010788 return 0;
10789}
10790
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010791/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
10792 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
10793 * just that it _might_ work.
10794 */
10795static int period_size_is_plausible_for_low_latency(int period_size)
10796{
10797 switch (period_size) {
10798 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -070010799 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010800 case 240:
10801 case 320:
10802 case 480:
10803 return 1;
10804 default:
10805 return 0;
10806 }
10807}
10808
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010809static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
10810{
10811 bool is_snd_card_status = false;
10812 bool is_ext_device_status = false;
10813 char value[32];
10814 int card = -1;
10815 card_status_t status;
10816
10817 if (cookie != adev || !parms)
10818 return;
10819
10820 if (!parse_snd_card_status(parms, &card, &status)) {
10821 is_snd_card_status = true;
10822 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
10823 is_ext_device_status = true;
10824 } else {
10825 // not a valid event
10826 return;
10827 }
10828
10829 pthread_mutex_lock(&adev->lock);
10830 if (card == adev->snd_card || is_ext_device_status) {
10831 if (is_snd_card_status && adev->card_status != status) {
Jaideep Sharmacb402512020-09-24 17:51:07 +053010832 ALOGD("%s card_status %d", __func__, status);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010833 adev->card_status = status;
10834 platform_snd_card_update(adev->platform, status);
10835 audio_extn_fm_set_parameters(adev, parms);
Derek Chend6f371d2019-03-01 13:45:58 -080010836 audio_extn_auto_hal_set_parameters(adev, parms);
Zhou Song4f43e352019-07-02 00:32:23 +080010837 if (status == CARD_STATUS_OFFLINE)
10838 audio_extn_sco_reset_configuration();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010839 } else if (is_ext_device_status) {
10840 platform_set_parameters(adev->platform, parms);
10841 }
10842 }
10843 pthread_mutex_unlock(&adev->lock);
10844 return;
10845}
10846
Weiyin Jiang280ea742020-09-08 20:28:22 +080010847/* adev lock held */
10848int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010849{
10850 struct audio_usecase *uc_info;
Zhou Song407e5aa2020-12-27 19:13:04 +080010851 struct audio_usecase *usecase;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010852 struct listnode devices;
Zhou Song407e5aa2020-12-27 19:13:04 +080010853 struct listnode *node;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010854
10855 uc_info = get_usecase_from_list(adev, out->usecase);
10856 if (uc_info == NULL) {
10857 ALOGE("%s: Could not find the usecase (%d) in the list",
10858 __func__, out->usecase);
10859 return -EINVAL;
10860 }
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010861 list_init(&devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010862
Zhou Songbaddf9f2020-11-20 13:57:39 +080010863 ALOGD("%s: enter: usecase(%d: %s), a2dp muted %d", __func__,
10864 out->usecase, use_case_table[out->usecase], out->a2dp_muted);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010865
10866 if (restore) {
Weiyin Jiang280ea742020-09-08 20:28:22 +080010867 pthread_mutex_lock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010868 // restore A2DP device for active usecases and unmute if required
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010869 if (is_a2dp_out_device_type(&out->device_list)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010870 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
Zhou Songe5225132019-09-26 15:33:36 +080010871 if (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)
10872 select_devices(adev, uc_info->id);
Zhou Songbaddf9f2020-11-20 13:57:39 +080010873
10874 if (is_offload_usecase(out->usecase)) {
10875 if (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)
Weiyin Jiang280ea742020-09-08 20:28:22 +080010876 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
Zhou Songbaddf9f2020-11-20 13:57:39 +080010877 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
10878 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
10879 } else {
10880 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010881 }
Zhou Songbaddf9f2020-11-20 13:57:39 +080010882 out->a2dp_muted = false;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010883 }
Weiyin Jiang280ea742020-09-08 20:28:22 +080010884 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010885 } else {
Weiyin Jiang280ea742020-09-08 20:28:22 +080010886 pthread_mutex_lock(&out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +080010887 // mute stream and switch to speaker if suspended
10888 if (!out->a2dp_muted && !out->standby) {
Zhou Songbaddf9f2020-11-20 13:57:39 +080010889 assign_devices(&devices, &out->device_list);
10890 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Zhou Song407e5aa2020-12-27 19:13:04 +080010891 list_for_each(node, &adev->usecase_list) {
10892 usecase = node_to_item(node, struct audio_usecase, list);
Zhou Songe63b6fe2021-04-15 13:54:46 +080010893 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
10894 !is_a2dp_out_device_type(&usecase->stream.out->device_list) &&
Zhou Songcf77af02021-05-14 18:21:14 +080010895 !is_sco_out_device_type(&usecase->stream.out->device_list) &&
Zhou Songe63b6fe2021-04-15 13:54:46 +080010896 platform_check_backends_match(SND_DEVICE_OUT_SPEAKER,
10897 usecase->out_snd_device)) {
Zhou Song407e5aa2020-12-27 19:13:04 +080010898 assign_devices(&out->device_list, &usecase->stream.out->device_list);
10899 break;
10900 }
10901 }
Zhou Songcf77af02021-05-14 18:21:14 +080010902 if ((is_a2dp_out_device_type(&devices) && list_length(&devices) == 1) ||
10903 (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)) {
Zhou Song8edbbdb2021-01-14 16:48:03 +080010904 out->a2dp_muted = true;
10905 if (is_offload_usecase(out->usecase)) {
10906 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10907 compress_pause(out->compr);
10908 out_set_compr_volume(&out->stream, (float)0, (float)0);
Zhou Song8edbbdb2021-01-14 16:48:03 +080010909 } else {
Weiyin Jiang906db3c2021-03-02 13:17:04 +080010910 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
10911 out_set_voip_volume(&out->stream, (float)0, (float)0);
10912 else
10913 out_set_pcm_volume(&out->stream, (float)0, (float)0);
10914
Zhou Song8edbbdb2021-01-14 16:48:03 +080010915 /* wait for stale pcm drained before switching to speaker */
10916 uint32_t latency =
10917 (out->config.period_count * out->config.period_size * 1000) /
10918 (out->config.rate);
10919 usleep(latency * 1000);
10920 }
Zhou Songbaddf9f2020-11-20 13:57:39 +080010921 }
10922 select_devices(adev, out->usecase);
Zhou Song8edbbdb2021-01-14 16:48:03 +080010923 ALOGD("%s: switched to device:%s and stream muted:%d", __func__,
10924 platform_get_snd_device_name(uc_info->out_snd_device), out->a2dp_muted);
Zhou Songbaddf9f2020-11-20 13:57:39 +080010925 if (is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010926 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10927 compress_resume(out->compr);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010928 }
Zhou Songbaddf9f2020-11-20 13:57:39 +080010929 assign_devices(&out->device_list, &devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010930 }
Weiyin Jiang280ea742020-09-08 20:28:22 +080010931 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010932 }
10933 ALOGV("%s: exit", __func__);
10934 return 0;
10935}
10936
Haynes Mathew George01156f92018-04-13 15:29:54 -070010937void adev_on_battery_status_changed(bool charging)
10938{
10939 pthread_mutex_lock(&adev->lock);
10940 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
10941 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +080010942 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -070010943 pthread_mutex_unlock(&adev->lock);
10944}
10945
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010946static int adev_open(const hw_module_t *module, const char *name,
10947 hw_device_t **device)
10948{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010949 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -080010950 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010951 char mixer_ctl_name[128] = {0};
10952 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010953
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080010954 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010955 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
10956
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010957 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -070010958 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010959 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -070010960 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010961 ALOGD("%s: returning existing instance of adev", __func__);
10962 ALOGD("%s: exit", __func__);
10963 pthread_mutex_unlock(&adev_init_lock);
10964 return 0;
10965 }
10966
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010967 adev = calloc(1, sizeof(struct audio_device));
10968
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -070010969 if (!adev) {
10970 pthread_mutex_unlock(&adev_init_lock);
10971 return -ENOMEM;
10972 }
10973
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -070010974 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
10975
Weiyin Jiange6ce6312019-01-28 18:28:22 +080010976 // register audio ext hidl at the earliest
10977 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053010978#ifdef DYNAMIC_LOG_ENABLED
10979 register_for_dynamic_logging("hal");
10980#endif
10981
Derek Chenf939fb72018-11-13 13:34:41 -080010982 /* default audio HAL major version */
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010983 uint32_t maj_version = 3;
Derek Chenf939fb72018-11-13 13:34:41 -080010984 if(property_get("vendor.audio.hal.maj.version", value, NULL))
10985 maj_version = atoi(value);
10986
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010987 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -080010988 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010989 adev->device.common.module = (struct hw_module_t *)module;
10990 adev->device.common.close = adev_close;
10991
10992 adev->device.init_check = adev_init_check;
10993 adev->device.set_voice_volume = adev_set_voice_volume;
10994 adev->device.set_master_volume = adev_set_master_volume;
10995 adev->device.get_master_volume = adev_get_master_volume;
10996 adev->device.set_master_mute = adev_set_master_mute;
10997 adev->device.get_master_mute = adev_get_master_mute;
10998 adev->device.set_mode = adev_set_mode;
10999 adev->device.set_mic_mute = adev_set_mic_mute;
11000 adev->device.get_mic_mute = adev_get_mic_mute;
11001 adev->device.set_parameters = adev_set_parameters;
11002 adev->device.get_parameters = adev_get_parameters;
11003 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
11004 adev->device.open_output_stream = adev_open_output_stream;
11005 adev->device.close_output_stream = adev_close_output_stream;
11006 adev->device.open_input_stream = adev_open_input_stream;
11007 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053011008 adev->device.create_audio_patch = adev_create_audio_patch;
11009 adev->device.release_audio_patch = adev_release_audio_patch;
11010 adev->device.get_audio_port = adev_get_audio_port;
11011 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011012 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +053011013 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011014
11015 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011016 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -080011017 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011018 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011019 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -080011020 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -070011021 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +053011022 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -070011023 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -070011024 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -070011025 /* Init audio and voice feature */
11026 audio_extn_feature_init();
11027 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070011028 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -080011029 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -080011030 list_init(&adev->active_inputs_list);
11031 list_init(&adev->active_outputs_list);
Rahul Sharma99770982019-03-06 17:05:26 +053011032 list_init(&adev->audio_patch_record_list);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011033 adev->io_streams_map = hashmapCreate(AUDIO_IO_PORTS_MAX, audio_extn_utils_hash_fn,
11034 audio_extn_utils_hash_eq);
11035 if (!adev->io_streams_map) {
11036 ALOGE("%s: Could not create io streams map", __func__);
11037 ret = -ENOMEM;
11038 goto adev_open_err;
11039 }
11040 adev->patch_map = hashmapCreate(AUDIO_PATCH_PORTS_MAX, audio_extn_utils_hash_fn,
11041 audio_extn_utils_hash_eq);
11042 if (!adev->patch_map) {
11043 ALOGE("%s: Could not create audio patch map", __func__);
11044 ret = -ENOMEM;
11045 goto adev_open_err;
11046 }
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -080011047 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -070011048 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +053011049 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +053011050 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +053011051 adev->perf_lock_opts[0] = 0x101;
11052 adev->perf_lock_opts[1] = 0x20E;
11053 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +080011054 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -070011055 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053011056 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070011057 adev->adm_routing_changed = false;
Revathi Uddarajub26e3932020-06-10 14:51:02 +053011058 adev->a2dp_started = false;
Zhou Song503196b2021-07-23 17:31:05 +080011059 adev->ha_proxy_enable = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +053011060
Zhou Song68ebc352019-12-05 17:11:15 +080011061 audio_extn_perf_lock_init();
11062
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011063 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -070011064 adev->platform = platform_init(adev);
11065 if (!adev->platform) {
Eric Laurentb23d5282013-05-14 15:27:20 -070011066 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011067 ret = -EINVAL;
11068 goto adev_open_err;
Eric Laurentb23d5282013-05-14 15:27:20 -070011069 }
Eric Laurentc4aef752013-09-12 17:45:53 -070011070
Aalique Grahame22e49102018-12-18 14:23:57 -080011071 adev->extspk = audio_extn_extspk_init(adev);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053011072 if (audio_extn_qap_is_enabled()) {
11073 ret = audio_extn_qap_init(adev);
11074 if (ret < 0) {
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053011075 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011076 goto adev_open_err;
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053011077 }
11078 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
11079 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
11080 }
Aalique Grahame22e49102018-12-18 14:23:57 -080011081
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053011082 if (audio_extn_qaf_is_enabled()) {
11083 ret = audio_extn_qaf_init(adev);
11084 if (ret < 0) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053011085 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011086 goto adev_open_err;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053011087 }
11088
11089 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
11090 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
11091 }
11092
Derek Chenae7b0342019-02-08 15:17:04 -080011093 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -080011094 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
11095
Eric Laurentc4aef752013-09-12 17:45:53 -070011096 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
11097 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
11098 if (adev->visualizer_lib == NULL) {
11099 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
11100 } else {
11101 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
11102 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080011103 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070011104 "visualizer_hal_start_output");
11105 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080011106 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070011107 "visualizer_hal_stop_output");
11108 }
11109 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +053011110 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080011111 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -080011112 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +080011113 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +053011114 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070011115 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -070011116
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080011117 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
11118 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
11119 if (adev->offload_effects_lib == NULL) {
11120 ALOGE("%s: DLOPEN failed for %s", __func__,
11121 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
11122 } else {
11123 ALOGV("%s: DLOPEN successful for %s", __func__,
11124 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
11125 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +053011126 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080011127 "offload_effects_bundle_hal_start_output");
11128 adev->offload_effects_stop_output =
11129 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
11130 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080011131 adev->offload_effects_set_hpx_state =
11132 (int (*)(bool))dlsym(adev->offload_effects_lib,
11133 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +053011134 adev->offload_effects_get_parameters =
11135 (void (*)(struct str_parms *, struct str_parms *))
11136 dlsym(adev->offload_effects_lib,
11137 "offload_effects_bundle_get_parameters");
11138 adev->offload_effects_set_parameters =
11139 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
11140 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080011141 }
11142 }
11143
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070011144 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
11145 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
11146 if (adev->adm_lib == NULL) {
11147 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
11148 } else {
11149 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
11150 adev->adm_init = (adm_init_t)
11151 dlsym(adev->adm_lib, "adm_init");
11152 adev->adm_deinit = (adm_deinit_t)
11153 dlsym(adev->adm_lib, "adm_deinit");
11154 adev->adm_register_input_stream = (adm_register_input_stream_t)
11155 dlsym(adev->adm_lib, "adm_register_input_stream");
11156 adev->adm_register_output_stream = (adm_register_output_stream_t)
11157 dlsym(adev->adm_lib, "adm_register_output_stream");
11158 adev->adm_deregister_stream = (adm_deregister_stream_t)
11159 dlsym(adev->adm_lib, "adm_deregister_stream");
11160 adev->adm_request_focus = (adm_request_focus_t)
11161 dlsym(adev->adm_lib, "adm_request_focus");
11162 adev->adm_abandon_focus = (adm_abandon_focus_t)
11163 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -070011164 adev->adm_set_config = (adm_set_config_t)
11165 dlsym(adev->adm_lib, "adm_set_config");
11166 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
11167 dlsym(adev->adm_lib, "adm_request_focus_v2");
11168 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
11169 dlsym(adev->adm_lib, "adm_is_noirq_avail");
11170 adev->adm_on_routing_change = (adm_on_routing_change_t)
11171 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070011172 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
11173 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070011174 }
11175 }
11176
Aalique Grahame22e49102018-12-18 14:23:57 -080011177 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070011178 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +080011179 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Kunlei Zhanga3c4cb02021-03-05 16:03:54 +080011180 adev->fluence_nn_usecase_id = USECASE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -080011181 //initialize this to false for now,
11182 //this will be set to true through set param
11183 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070011184
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -070011185 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011186 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -080011187
11188 if (k_enable_extended_precision)
11189 adev_verify_devices(adev);
11190
Xiaojun Sang785b5da2017-08-03 15:52:29 +080011191 adev->dsp_bit_width_enforce_mode =
11192 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011193
Dhananjay Kumard6d32152016-10-13 16:11:03 +053011194 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
11195 &adev->streams_output_cfg_list,
11196 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070011197
Kiran Kandi910e1862013-10-29 13:29:42 -070011198 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070011199
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070011200 int trial;
Manisha Agarwalc75a0202019-12-06 18:48:25 +053011201 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070011202 trial = atoi(value);
11203 if (period_size_is_plausible_for_low_latency(trial)) {
11204 pcm_config_low_latency.period_size = trial;
11205 pcm_config_low_latency.start_threshold = trial / 4;
11206 pcm_config_low_latency.avail_min = trial / 4;
11207 configured_low_latency_capture_period_size = trial;
11208 }
11209 }
ronghuiz93177262021-04-21 19:58:13 +080011210 if (property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070011211 trial = atoi(value);
11212 if (period_size_is_plausible_for_low_latency(trial)) {
11213 configured_low_latency_capture_period_size = trial;
11214 }
11215 }
11216
Vignesh Kulothungan7d374312018-02-21 17:12:00 -080011217 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
11218
Eric Laurent4b084132018-10-19 17:33:43 -070011219 adev->camera_orientation = CAMERA_DEFAULT;
11220
Manisha Agarwalc75a0202019-12-06 18:48:25 +053011221 if (property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -070011222 af_period_multiplier = atoi(value);
11223 if (af_period_multiplier < 0)
11224 af_period_multiplier = 2;
11225 else if (af_period_multiplier > 4)
11226 af_period_multiplier = 4;
11227
11228 ALOGV("new period_multiplier = %d", af_period_multiplier);
11229 }
11230
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080011231 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080011232
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -070011233 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070011234 pthread_mutex_unlock(&adev_init_lock);
11235
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070011236 if (adev->adm_init)
11237 adev->adm_data = adev->adm_init();
11238
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053011239 qahwi_init(*device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080011240 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053011241
11242 audio_extn_snd_mon_init();
11243 pthread_mutex_lock(&adev->lock);
11244 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
11245 adev->card_status = CARD_STATUS_ONLINE;
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -050011246 adev->out_power_policy = POWER_POLICY_STATUS_ONLINE;
11247 adev->in_power_policy = POWER_POLICY_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -070011248 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
11249 /*
11250 * if the battery state callback happens before charging can be queried,
11251 * it will be guarded with the adev->lock held in the cb function and so
11252 * the callback value will reflect the latest state
11253 */
11254 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053011255 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +080011256 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -070011257 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +080011258 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053011259 /* Allocate memory for Device config params */
11260 adev->device_cfg_params = (struct audio_device_config_param*)
11261 calloc(platform_get_max_codec_backend(),
11262 sizeof(struct audio_device_config_param));
11263 if (adev->device_cfg_params == NULL)
11264 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053011265
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053011266 /*
11267 * Check if new PSPD matrix mixer control is supported. If not
11268 * supported, then set flag so that old mixer ctrl is sent while
11269 * sending pspd coefficients on older kernel version. Query mixer
11270 * control for default pcm id and channel value one.
11271 */
11272 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
11273 "AudStr %d ChMixer Weight Ch %d", 0, 1);
11274
11275 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
11276 if (!ctl) {
11277 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
11278 __func__, mixer_ctl_name);
11279 adev->use_old_pspd_mix_ctrl = true;
11280 }
11281
Jaideep Sharma0fa53812020-09-17 09:00:11 +053011282 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011283 return 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011284
11285adev_open_err:
11286 free_map(adev->patch_map);
11287 free_map(adev->io_streams_map);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080011288 free(adev->snd_dev_ref_cnt);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011289 pthread_mutex_destroy(&adev->lock);
11290 free(adev);
11291 adev = NULL;
11292 *device = NULL;
11293 pthread_mutex_unlock(&adev_init_lock);
11294 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011295}
11296
11297static struct hw_module_methods_t hal_module_methods = {
11298 .open = adev_open,
11299};
11300
11301struct audio_module HAL_MODULE_INFO_SYM = {
11302 .common = {
11303 .tag = HARDWARE_MODULE_TAG,
11304 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
11305 .hal_api_version = HARDWARE_HAL_API_VERSION,
11306 .id = AUDIO_HARDWARE_MODULE_ID,
11307 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -080011308 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011309 .methods = &hal_module_methods,
11310 },
11311};