blob: 8546c9744ea731a34c91da0c57ce25bfe975aa7c [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
715 if (out->realtime)
716 adev->adm_set_config(adev->adm_data,
717 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||
3448 CARD_STATUS_OFFLINE == adev->card_status) {
3449 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303450 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303451 goto error_config;
3452 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303453
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003454 if (is_sco_in_device_type(&in->device_list)) {
Lakshman Chaluvaraju87f53aa2021-02-02 15:50:11 +05303455 if (!adev->bt_sco_on || audio_extn_a2dp_source_is_ready()) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303456 ALOGE("%s: SCO profile is not ready, return error", __func__);
3457 ret = -EIO;
3458 goto error_config;
3459 }
3460 }
3461
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003462 /* Check if source matches incall recording usecase criteria */
3463 ret = voice_check_and_set_incall_rec_usecase(adev, in);
3464 if (ret)
3465 goto error_config;
3466 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07003467 ALOGV("%s: usecase(%d)", __func__, in->usecase);
3468
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303469 if (audio_extn_cin_attached_usecase(in))
3470 audio_extn_cin_acquire_usecase(in);
3471
Mingming Yin2664a5b2015-09-03 10:53:11 -07003472 if (get_usecase_from_list(adev, in->usecase) != NULL) {
3473 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
3474 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Weiyin Jiang38c0e612020-09-10 16:10:51 +08003475 ret = -EINVAL;
3476 goto error_config;
Mingming Yin2664a5b2015-09-03 10:53:11 -07003477 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003478
Eric Laurentb23d5282013-05-14 15:27:20 -07003479 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003480 if (in->pcm_device_id < 0) {
3481 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
3482 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08003483 ret = -EINVAL;
3484 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003485 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003486
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003487 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003488
3489 if (!uc_info) {
3490 ret = -ENOMEM;
3491 goto error_config;
3492 }
3493
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003494 uc_info->id = in->usecase;
3495 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003496 uc_info->stream.in = in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003497 list_init(&uc_info->device_list);
3498 assign_devices(&uc_info->device_list, &in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003499 uc_info->in_snd_device = SND_DEVICE_NONE;
3500 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003501
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003502 list_add_tail(&adev->usecase_list, &uc_info->list);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003503 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303504 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3505 adev->perf_lock_opts,
3506 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003507 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003508
Derek Chenea197282019-01-07 17:35:01 -08003509 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3510 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003511
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05303512 android_atomic_acquire_cas(true, false, &(in->capture_stopped));
3513
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303514 if (audio_extn_cin_attached_usecase(in)) {
Manish Dewangan46e07982018-12-13 18:18:59 +05303515 ret = audio_extn_cin_open_input_stream(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303516 if (ret)
3517 goto error_open;
3518 else
3519 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003520 }
3521
Haynes Mathew George16081042017-05-31 17:16:49 -07003522 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003523 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003524 ALOGE("%s: pcm stream not ready", __func__);
3525 goto error_open;
3526 }
3527 ret = pcm_start(in->pcm);
3528 if (ret < 0) {
3529 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3530 goto error_open;
3531 }
3532 } else {
3533 unsigned int flags = PCM_IN | PCM_MONOTONIC;
3534 unsigned int pcm_open_retry_count = 0;
3535
Zhou Song62ea0282020-03-22 19:53:01 +08003536 if ((in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) ||
3537 (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003538 flags |= PCM_MMAP | PCM_NOIRQ;
3539 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
3540 } else if (in->realtime) {
3541 flags |= PCM_MMAP | PCM_NOIRQ;
3542 }
3543
Garmond Leunge2433c32017-09-28 21:51:22 -07003544 if (audio_extn_ffv_get_stream() == in) {
3545 ALOGD("%s: ffv stream, update pcm config", __func__);
3546 audio_extn_ffv_update_pcm_config(&config);
3547 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003548 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3549 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3550
3551 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003552 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07003553 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07003554 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003555 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303556 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303557 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3558 adev->card_status = CARD_STATUS_OFFLINE;
3559 in->card_status = CARD_STATUS_OFFLINE;
3560 ret = -EIO;
3561 goto error_open;
3562 }
3563
Haynes Mathew George16081042017-05-31 17:16:49 -07003564 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3565 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3566 if (in->pcm != NULL) {
3567 pcm_close(in->pcm);
3568 in->pcm = NULL;
3569 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003570 if (pcm_open_retry_count == 0) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003571 ret = -EIO;
3572 goto error_open;
3573 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003574 pcm_open_retry_count--;
Haynes Mathew George16081042017-05-31 17:16:49 -07003575 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3576 continue;
3577 }
3578 break;
3579 }
3580
3581 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003582 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07003583 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003584 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003585 if (ret < 0) {
3586 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3587 pcm_close(in->pcm);
3588 in->pcm = NULL;
3589 goto error_open;
3590 }
3591 register_in_stream(in);
3592 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003593 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07003594 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003595 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003596 if (ret < 0) {
3597 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003598 pcm_close(in->pcm);
3599 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003600 goto error_open;
3601 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003602 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003603 }
3604
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003605 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07003606 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
3607 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003608
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003609 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303610 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
3611
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303612done_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003613 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303614 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Manisha Agarwal4c2402e2020-10-21 12:02:57 +05303615 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303616 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003617 return ret;
3618
3619error_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003620 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303621 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003622 stop_input_stream(in);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003623
Eric Laurentc8400632013-02-14 19:04:54 -08003624error_config:
Weiyin Jiang38c0e612020-09-10 16:10:51 +08003625 if (audio_extn_cin_attached_usecase(in))
3626 audio_extn_cin_close_input_stream(in);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303627 /*
3628 * sleep 50ms to allow sufficient time for kernel
3629 * drivers to recover incases like SSR.
3630 */
3631 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003632 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303633 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003634 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003635}
3636
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003637void lock_input_stream(struct stream_in *in)
3638{
3639 pthread_mutex_lock(&in->pre_lock);
3640 pthread_mutex_lock(&in->lock);
3641 pthread_mutex_unlock(&in->pre_lock);
3642}
3643
3644void lock_output_stream(struct stream_out *out)
3645{
3646 pthread_mutex_lock(&out->pre_lock);
3647 pthread_mutex_lock(&out->lock);
3648 pthread_mutex_unlock(&out->pre_lock);
3649}
3650
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003651/* must be called with out->lock locked */
3652static int send_offload_cmd_l(struct stream_out* out, int command)
3653{
3654 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
3655
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003656 if (!cmd) {
3657 ALOGE("failed to allocate mem for command 0x%x", command);
3658 return -ENOMEM;
3659 }
3660
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003661 ALOGVV("%s %d", __func__, command);
3662
3663 cmd->cmd = command;
3664 list_add_tail(&out->offload_cmd_list, &cmd->node);
3665 pthread_cond_signal(&out->offload_cond);
3666 return 0;
3667}
3668
Gautam Manam14c198b2020-12-24 14:08:04 +05303669/* must be called with out->lock */
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003670static void stop_compressed_output_l(struct stream_out *out)
3671{
Gautam Manam14c198b2020-12-24 14:08:04 +05303672 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003673 out->offload_state = OFFLOAD_STATE_IDLE;
Gautam Manam14c198b2020-12-24 14:08:04 +05303674 pthread_mutex_unlock(&out->latch_lock);
Weiyin Jiang906db3c2021-03-02 13:17:04 +08003675
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003676 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003677 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003678 if (out->compr != NULL) {
3679 compress_stop(out->compr);
3680 while (out->offload_thread_blocked) {
3681 pthread_cond_wait(&out->cond, &out->lock);
3682 }
3683 }
3684}
3685
Varun Balaraje49253e2017-07-06 19:48:56 +05303686bool is_interactive_usecase(audio_usecase_t uc_id)
3687{
3688 unsigned int i;
3689 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
3690 if (uc_id == interactive_usecases[i])
3691 return true;
3692 }
3693 return false;
3694}
3695
3696static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
3697{
3698 audio_usecase_t ret_uc = USECASE_INVALID;
3699 unsigned int intract_uc_index;
3700 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3701
3702 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
3703 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
3704 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
3705 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
3706 ret_uc = interactive_usecases[intract_uc_index];
3707 break;
3708 }
3709 }
3710
3711 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
3712 return ret_uc;
3713}
3714
3715static void free_interactive_usecase(struct audio_device *adev,
3716 audio_usecase_t uc_id)
3717{
3718 unsigned int interact_uc_index;
3719 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3720
3721 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
3722 if (interactive_usecases[interact_uc_index] == uc_id) {
3723 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
3724 break;
3725 }
3726 }
3727 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
3728}
3729
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003730bool is_offload_usecase(audio_usecase_t uc_id)
3731{
3732 unsigned int i;
3733 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
3734 if (uc_id == offload_usecases[i])
3735 return true;
3736 }
3737 return false;
3738}
3739
Dhananjay Kumarac341582017-02-23 23:42:25 +05303740static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003741{
vivek mehta446c3962015-09-14 10:57:35 -07003742 audio_usecase_t ret_uc = USECASE_INVALID;
3743 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003744 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003745 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05303746 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07003747 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
3748 else
3749 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003750
vivek mehta446c3962015-09-14 10:57:35 -07003751 pthread_mutex_lock(&adev->lock);
3752 if (get_usecase_from_list(adev, ret_uc) != NULL)
3753 ret_uc = USECASE_INVALID;
3754 pthread_mutex_unlock(&adev->lock);
3755
3756 return ret_uc;
3757 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003758
3759 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003760 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3761 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3762 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3763 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003764 break;
3765 }
3766 }
vivek mehta446c3962015-09-14 10:57:35 -07003767
3768 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3769 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003770}
3771
3772static void free_offload_usecase(struct audio_device *adev,
3773 audio_usecase_t uc_id)
3774{
vivek mehta446c3962015-09-14 10:57:35 -07003775 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003776 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003777
3778 if (!adev->multi_offload_enable)
3779 return;
3780
3781 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3782 if (offload_usecases[offload_uc_index] == uc_id) {
3783 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003784 break;
3785 }
3786 }
3787 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3788}
3789
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003790static void *offload_thread_loop(void *context)
3791{
3792 struct stream_out *out = (struct stream_out *) context;
3793 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003794 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003795
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003796 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08003797 set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003798 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3799
3800 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003801 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003802 out->offload_state = OFFLOAD_STATE_IDLE;
3803 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003804 for (;;) {
3805 struct offload_cmd *cmd = NULL;
3806 stream_callback_event_t event;
3807 bool send_callback = false;
3808
3809 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3810 __func__, list_empty(&out->offload_cmd_list),
3811 out->offload_state);
3812 if (list_empty(&out->offload_cmd_list)) {
3813 ALOGV("%s SLEEPING", __func__);
3814 pthread_cond_wait(&out->offload_cond, &out->lock);
3815 ALOGV("%s RUNNING", __func__);
3816 continue;
3817 }
3818
3819 item = list_head(&out->offload_cmd_list);
3820 cmd = node_to_item(item, struct offload_cmd, node);
3821 list_remove(item);
3822
3823 ALOGVV("%s STATE %d CMD %d out->compr %p",
3824 __func__, out->offload_state, cmd->cmd, out->compr);
3825
3826 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3827 free(cmd);
3828 break;
3829 }
3830
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003831 // allow OFFLOAD_CMD_ERROR reporting during standby
3832 // this is needed to handle failures during compress_open
3833 // Note however that on a pause timeout, the stream is closed
3834 // and no offload usecase will be active. Therefore this
3835 // special case is needed for compress_open failures alone
3836 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3837 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003838 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003839 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003840 pthread_cond_signal(&out->cond);
3841 continue;
3842 }
3843 out->offload_thread_blocked = true;
3844 pthread_mutex_unlock(&out->lock);
3845 send_callback = false;
3846 switch(cmd->cmd) {
3847 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003848 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003849 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003850 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003851 send_callback = true;
3852 event = STREAM_CBK_EVENT_WRITE_READY;
3853 break;
3854 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003855 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303856 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003857 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303858 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003859 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303860 if (ret < 0)
3861 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303862 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303863 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003864 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003865 else
3866 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003867 if (-ENETRESET != ret && !(-EINTR == ret &&
3868 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303869 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303870 pthread_mutex_lock(&out->lock);
3871 out->send_new_metadata = 1;
3872 out->send_next_track_params = true;
3873 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303874 event = STREAM_CBK_EVENT_DRAIN_READY;
3875 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3876 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303877 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003878 break;
3879 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003880 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003881 ret = compress_drain(out->compr);
3882 ALOGD("copl(%p):out of compress_drain", out);
3883 // EINTR check avoids drain interruption due to SSR
3884 if (-ENETRESET != ret && !(-EINTR == ret &&
3885 CARD_STATUS_OFFLINE == out->card_status)) {
3886 send_callback = true;
3887 event = STREAM_CBK_EVENT_DRAIN_READY;
3888 } else
3889 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003890 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303891 case OFFLOAD_CMD_ERROR:
3892 ALOGD("copl(%p): sending error callback to AF", out);
3893 send_callback = true;
3894 event = STREAM_CBK_EVENT_ERROR;
3895 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003896 default:
3897 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3898 break;
3899 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003900 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003901 out->offload_thread_blocked = false;
3902 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003903 if (send_callback && out->client_callback) {
3904 ALOGVV("%s: sending client_callback event %d", __func__, event);
3905 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003906 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003907 free(cmd);
3908 }
3909
3910 pthread_cond_signal(&out->cond);
3911 while (!list_empty(&out->offload_cmd_list)) {
3912 item = list_head(&out->offload_cmd_list);
3913 list_remove(item);
3914 free(node_to_item(item, struct offload_cmd, node));
3915 }
3916 pthread_mutex_unlock(&out->lock);
3917
3918 return NULL;
3919}
3920
3921static int create_offload_callback_thread(struct stream_out *out)
3922{
3923 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3924 list_init(&out->offload_cmd_list);
3925 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3926 offload_thread_loop, out);
3927 return 0;
3928}
3929
3930static int destroy_offload_callback_thread(struct stream_out *out)
3931{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003932 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003933 stop_compressed_output_l(out);
3934 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3935
3936 pthread_mutex_unlock(&out->lock);
3937 pthread_join(out->offload_thread, (void **) NULL);
3938 pthread_cond_destroy(&out->offload_cond);
3939
3940 return 0;
3941}
3942
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003943static int stop_output_stream(struct stream_out *out)
3944{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303945 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003946 struct audio_usecase *uc_info;
3947 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003948 bool has_voip_usecase =
3949 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003950
Eric Laurent994a6932013-07-17 11:51:42 -07003951 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003952 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003953 uc_info = get_usecase_from_list(adev, out->usecase);
3954 if (uc_info == NULL) {
3955 ALOGE("%s: Could not find the usecase (%d) in the list",
3956 __func__, out->usecase);
3957 return -EINVAL;
3958 }
3959
Zhou Songbaddf9f2020-11-20 13:57:39 +08003960 out->a2dp_muted = false;
3961
Derek Chenea197282019-01-07 17:35:01 -08003962 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3963 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003964
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003965 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303966 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003967 if (adev->visualizer_stop_output != NULL)
3968 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003969
3970 audio_extn_dts_remove_state_notifier_node(out->usecase);
3971
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003972 if (adev->offload_effects_stop_output != NULL)
3973 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07003974 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3975 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3976 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003977 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003978
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003979 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3980 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003981 voice_set_device_mute_flag(adev, false);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003982 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003983
Eric Laurent150dbfe2013-02-27 14:31:02 -08003984 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003985 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003986
3987 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003988 disable_snd_device(adev, uc_info->out_snd_device);
Zhou Songd9bd9302020-08-04 16:34:45 +08003989 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
3990 disable_snd_device(adev, SND_DEVICE_OUT_HAPTICS);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003991
Aalique Grahame22e49102018-12-18 14:23:57 -08003992 audio_extn_extspk_update(adev->extspk);
3993
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003994 if (is_offload_usecase(out->usecase)) {
3995 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3996 adev->dsp_bit_width_enforce_mode,
3997 false);
3998 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003999 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07004000 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
4001 false);
4002
4003 if (ret != 0)
4004 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
4005 /* default service interval was successfully updated,
4006 reopen USB backend with new service interval */
4007 ret = 0;
4008 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08004009
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004010 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304011 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004012 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304013 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004014 ALOGV("Disable passthrough , reset mixer to pcm");
4015 /* NO_PASSTHROUGH */
Meng Wang4c32fb42020-01-16 17:57:11 +08004016#ifdef AUDIO_GKI_ENABLED
4017 /* out->compr_config.codec->reserved[0] is for compr_passthr */
4018 out->compr_config.codec->reserved[0] = 0;
4019#else
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004020 out->compr_config.codec->compr_passthr = 0;
Meng Wang4c32fb42020-01-16 17:57:11 +08004021#endif
Mingming Yin21854652016-04-13 11:54:02 -07004022 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004023 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
4024 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07004025
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304026 /* Must be called after removing the usecase from list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004027 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL))
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05304028 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304029
Manish Dewangan21a850a2017-08-14 12:03:55 +05304030 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07004031 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
4032 if (ret < 0)
4033 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
4034 }
4035
Zhou Song642ec432020-12-23 16:11:10 +08004036 /* trigger voip input to reroute when voip output changes to hearing aid */
Aalique Grahame22e49102018-12-18 14:23:57 -08004037 if (has_voip_usecase ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004038 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08004039 struct listnode *node;
4040 struct audio_usecase *usecase;
4041 list_for_each(node, &adev->usecase_list) {
4042 usecase = node_to_item(node, struct audio_usecase, list);
Zhou Song642ec432020-12-23 16:11:10 +08004043 if (usecase->type == PCM_PLAYBACK || usecase == uc_info ||
4044 (usecase->type == PCM_CAPTURE &&
Revathi Uddarajud9f23d92020-07-27 10:55:06 +05304045 usecase->id != USECASE_AUDIO_RECORD_VOIP &&
Zhou Song642ec432020-12-23 16:11:10 +08004046 usecase->id != USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY))
Aalique Grahame22e49102018-12-18 14:23:57 -08004047 continue;
4048
4049 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
4050 __func__, usecase->id, use_case_table[usecase->id],
4051 out->usecase, use_case_table[out->usecase]);
4052 select_devices(adev, usecase->id);
4053 }
4054 }
4055
Garmond Leung5fd0b552018-04-17 11:56:12 -07004056 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07004057 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004058 return ret;
4059}
4060
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004061struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
4062 unsigned int flags, unsigned int pcm_open_retry_count,
4063 struct pcm_config *config)
4064{
4065 struct pcm* pcm = NULL;
4066
4067 while (1) {
4068 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
4069 if (pcm == NULL || !pcm_is_ready(pcm)) {
4070 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
4071 if (pcm != NULL) {
4072 pcm_close(pcm);
4073 pcm = NULL;
4074 }
Weiyin Jiang72197252019-10-09 11:49:32 +08004075 if (pcm_open_retry_count == 0)
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004076 return NULL;
4077
Weiyin Jiang72197252019-10-09 11:49:32 +08004078 pcm_open_retry_count--;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004079 usleep(PROXY_OPEN_WAIT_TIME * 1000);
4080 continue;
4081 }
4082 break;
4083 }
4084
4085 if (pcm_is_ready(pcm)) {
4086 int ret = pcm_prepare(pcm);
4087 if (ret < 0) {
4088 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
4089 pcm_close(pcm);
4090 pcm = NULL;
4091 }
4092 }
4093
4094 return pcm;
4095}
4096
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004097int start_output_stream(struct stream_out *out)
4098{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004099 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004100 struct audio_usecase *uc_info;
4101 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004102 char mixer_ctl_name[128];
4103 struct mixer_ctl *ctl = NULL;
4104 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304105 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004106 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004107
Haynes Mathew George380745d2017-10-04 15:27:45 -07004108 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004109 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
4110 ret = -EINVAL;
4111 goto error_config;
4112 }
4113
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004114 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304115 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004116 get_device_types(&out->device_list), is_haptic_usecase);
4117
4118 bool is_speaker_active = compare_device_type(&out->device_list,
4119 AUDIO_DEVICE_OUT_SPEAKER);
4120 bool is_speaker_safe_active = compare_device_type(&out->device_list,
4121 AUDIO_DEVICE_OUT_SPEAKER_SAFE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304122
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304123 if (CARD_STATUS_OFFLINE == out->card_status ||
4124 CARD_STATUS_OFFLINE == adev->card_status) {
4125 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05304126 ret = -EIO;
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004127 goto error_fatal;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304128 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05304129
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004130 //Update incall music usecase to reflect correct voice session
4131 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
4132 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
4133 if (ret != 0) {
4134 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
4135 __func__, ret);
4136 goto error_config;
4137 }
4138 }
4139
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004140 if (is_a2dp_out_device_type(&out->device_list)) {
Florian Pfister1a84f312018-07-19 14:38:18 +02004141 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004142 if (is_speaker_active || is_speaker_safe_active) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304143 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304144 } else {
Zhou Songd01e7a22020-09-23 22:49:01 +08004145 if (!is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304146 ALOGE("%s: A2DP profile is not ready, return error", __func__);
4147 ret = -EAGAIN;
4148 goto error_config;
4149 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304150 }
4151 }
4152 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004153 if (is_sco_out_device_type(&out->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304154 if (!adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004155 if (is_speaker_active) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304156 //combo usecase just by pass a2dp
4157 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004158 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304159 } else {
4160 ALOGE("%s: SCO profile is not ready, return error", __func__);
4161 ret = -EAGAIN;
4162 goto error_config;
4163 }
4164 }
4165 }
4166
Eric Laurentb23d5282013-05-14 15:27:20 -07004167 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004168 if (out->pcm_device_id < 0) {
4169 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
4170 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004171 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004172 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004173 }
4174
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004175 if (is_haptic_usecase) {
Meng Wang51d8c2a2020-04-27 15:23:21 +08004176 adev->haptic_pcm_device_id = platform_get_pcm_device_id(
4177 USECASE_AUDIO_PLAYBACK_HAPTICS, PCM_PLAYBACK);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004178 if (adev->haptic_pcm_device_id < 0) {
4179 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
4180 __func__, adev->haptic_pcm_device_id, out->usecase);
4181 ret = -EINVAL;
4182 goto error_config;
4183 }
4184 }
4185
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004186 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004187
4188 if (!uc_info) {
4189 ret = -ENOMEM;
4190 goto error_config;
4191 }
4192
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004193 uc_info->id = out->usecase;
4194 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004195 uc_info->stream.out = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004196 list_init(&uc_info->device_list);
4197 assign_devices(&uc_info->device_list, &out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004198 uc_info->in_snd_device = SND_DEVICE_NONE;
4199 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07004200
4201 /* This must be called before adding this usecase to the list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004202 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07004203 audio_extn_usb_check_and_set_svc_int(uc_info, true);
4204 /* USB backend is not reopened immediately.
4205 This is eventually done as part of select_devices */
4206 }
4207
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004208 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004209
Wei Wangf7ca6c92017-11-21 14:51:20 -08004210 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304211 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4212 adev->perf_lock_opts,
4213 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304214
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004215 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05304216 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304217 if (audio_extn_passthru_is_enabled() &&
4218 audio_extn_passthru_is_passthrough_stream(out)) {
4219 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304220 }
4221 }
4222
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004223 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02004224 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304225 if (!a2dp_combo) {
4226 check_a2dp_restore_l(adev, out, false);
4227 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004228 struct listnode dev;
4229 list_init(&dev);
4230 assign_devices(&dev, &out->device_list);
4231 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4232 reassign_device_list(&out->device_list,
4233 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aalique Grahame22e49102018-12-18 14:23:57 -08004234 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004235 reassign_device_list(&out->device_list,
4236 AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304237 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004238 assign_devices(&out->device_list, &dev);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304239 }
4240 } else {
Revathi Uddarajub26e3932020-06-10 14:51:02 +05304241 select_devices(adev, out->usecase);
4242 if (is_a2dp_out_device_type(&out->device_list) &&
4243 !adev->a2dp_started) {
4244 if (is_speaker_active || is_speaker_safe_active) {
4245 struct listnode dev;
4246 list_init(&dev);
4247 assign_devices(&dev, &out->device_list);
4248 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4249 reassign_device_list(&out->device_list,
4250 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
4251 else
4252 reassign_device_list(&out->device_list,
4253 AUDIO_DEVICE_OUT_SPEAKER, "");
4254 select_devices(adev, out->usecase);
4255 assign_devices(&out->device_list, &dev);
4256 } else {
4257 ret = -EINVAL;
4258 goto error_open;
4259 }
4260 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304261 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004262
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004263 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
4264 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07004265 voice_set_device_mute_flag(adev, true);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004266 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07004267
Derek Chenea197282019-01-07 17:35:01 -08004268 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
4269 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08004270
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004271 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
4272 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07004273
4274 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07004275 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07004276 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4277 ALOGE("%s: pcm stream not ready", __func__);
4278 goto error_open;
4279 }
4280 ret = pcm_start(out->pcm);
4281 if (ret < 0) {
4282 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
4283 goto error_open;
4284 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07004285 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07004286 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004287 unsigned int flags = PCM_OUT;
4288 unsigned int pcm_open_retry_count = 0;
4289 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
4290 flags |= PCM_MMAP | PCM_NOIRQ;
4291 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004292 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08004293 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004294 } else
4295 flags |= PCM_MONOTONIC;
4296
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004297 if ((adev->vr_audio_mode_enabled) &&
4298 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
4299 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4300 "PCM_Dev %d Topology", out->pcm_device_id);
4301 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4302 if (!ctl) {
4303 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
4304 __func__, mixer_ctl_name);
4305 } else {
4306 //if success use ULLPP
4307 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
4308 __func__, mixer_ctl_name, out->pcm_device_id);
4309 //There is a still a possibility that some sessions
4310 // that request for FAST|RAW when 3D audio is active
4311 //can go through ULLPP. Ideally we expects apps to
4312 //listen to audio focus and stop concurrent playback
4313 //Also, we will look for mode flag (voice_in_communication)
4314 //before enabling the realtime flag.
4315 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
4316 }
4317 }
4318
Vatsal Bucha3f39f222021-06-29 16:16:55 +05304319 platform_set_stream_channel_map(adev->platform, out->channel_mask,
4320 out->pcm_device_id, -1, &out->channel_map_param.channel_map[0]);
Surendar Karka91fa3682018-07-02 18:12:12 +05304321
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004322 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
4323 flags, pcm_open_retry_count,
4324 &(out->config));
4325 if (out->pcm == NULL) {
4326 ret = -EIO;
4327 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004328 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004329
4330 if (is_haptic_usecase) {
4331 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
4332 adev->haptic_pcm_device_id,
4333 flags, pcm_open_retry_count,
4334 &(adev->haptics_config));
4335 // failure to open haptics pcm shouldnt stop audio,
4336 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07004337
4338 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
4339 ALOGD("%s: enable haptic audio synchronization", __func__);
4340 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
4341 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004342 }
4343
Zhou Song2b8f28f2017-09-11 10:51:38 +08004344 // apply volume for voip playback after path is set up
4345 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
4346 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05304347 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
4348 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304349 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
4350 out->apply_volume = false;
Derek Chenf13dd492018-11-13 14:53:51 -08004351 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
4352 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Krishna Kishor Jha10ad39f2022-02-21 17:02:47 +05304353#ifdef SOFT_VOLUME
4354 out_set_soft_volume_params(&out->stream);
4355#endif
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304356 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004357 } else {
Zhou Song79929fe2020-01-20 17:57:43 +08004358 /*
4359 * set custom channel map if:
4360 * 1. neither mono nor stereo clips i.e. channels > 2 OR
4361 * 2. custom channel map has been set by client
4362 * else default channel map of FC/FR/FL can always be set to DSP
4363 */
4364 if (popcount(out->channel_mask) > 2 || out->channel_map_param.channel_map[0])
4365 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Weiyin Jiang810a80d2021-01-18 16:04:31 +08004366 out->pcm_device_id, -1, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08004367 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
4368 adev->dsp_bit_width_enforce_mode,
4369 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004370 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07004371 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004372 out->compr = compress_open(adev->snd_card,
4373 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004374 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004375 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05304376 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05304377 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
4378 adev->card_status = CARD_STATUS_OFFLINE;
4379 out->card_status = CARD_STATUS_OFFLINE;
4380 ret = -EIO;
4381 goto error_open;
4382 }
4383
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004384 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004385 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004386 compress_close(out->compr);
4387 out->compr = NULL;
4388 ret = -EIO;
4389 goto error_open;
4390 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304391 /* compress_open sends params of the track, so reset the flag here */
4392 out->is_compr_metadata_avail = false;
4393
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004394 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004395 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07004396
Fred Oh3f43e742015-03-04 18:42:34 -08004397 /* Since small bufs uses blocking writes, a write will be blocked
4398 for the default max poll time (20s) in the event of an SSR.
4399 Reduce the poll time to observe and deal with SSR faster.
4400 */
Ashish Jain5106d362016-05-11 19:23:33 +05304401 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08004402 compress_set_max_poll_wait(out->compr, 1000);
4403 }
4404
Manish Dewangan69426c82017-01-30 17:35:36 +05304405 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05304406 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05304407
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004408 audio_extn_dts_create_state_notifier_node(out->usecase);
4409 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4410 popcount(out->channel_mask),
4411 out->playback_started);
4412
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004413#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304414 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004415 audio_extn_dolby_send_ddp_endp_params(adev);
4416#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05304417 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
4418 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004419 if (adev->visualizer_start_output != NULL)
4420 adev->visualizer_start_output(out->handle, out->pcm_device_id);
4421 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05304422 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004423 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004424 }
Derek Chenf13dd492018-11-13 14:53:51 -08004425
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004426 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf13dd492018-11-13 14:53:51 -08004427 /* Update cached volume from media to offload/direct stream */
4428 struct listnode *node = NULL;
4429 list_for_each(node, &adev->active_outputs_list) {
4430 streams_output_ctxt_t *out_ctxt = node_to_item(node,
4431 streams_output_ctxt_t,
4432 list);
4433 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
4434 out->volume_l = out_ctxt->output->volume_l;
4435 out->volume_r = out_ctxt->output->volume_r;
4436 }
4437 }
4438 out_set_compr_volume(&out->stream,
4439 out->volume_l, out->volume_r);
4440 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004441 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004442
4443 if (ret == 0) {
4444 register_out_stream(out);
4445 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07004446 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4447 ALOGE("%s: pcm stream not ready", __func__);
4448 goto error_open;
4449 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004450 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004451 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004452 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004453 if (ret < 0)
4454 goto error_open;
4455 }
4456 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004457 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304458 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Jaideep Sharma0fa53812020-09-17 09:00:11 +05304459 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004460
vivek mehtad15d2bf2019-05-17 13:35:10 -07004461 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
4462 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4463 audio_low_latency_hint_start();
4464 }
4465
Manish Dewangan21a850a2017-08-14 12:03:55 +05304466 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07004467 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07004468 if (ret < 0)
4469 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
4470 }
4471
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004472 // consider a scenario where on pause lower layers are tear down.
4473 // so on resume, swap mixer control need to be sent only when
4474 // backend is active, hence rather than sending from enable device
4475 // sending it from start of streamtream
4476
4477 platform_set_swap_channels(adev, true);
4478
Haynes Mathew George380745d2017-10-04 15:27:45 -07004479 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304480 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004481 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004482error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004483 if (adev->haptic_pcm) {
4484 pcm_close(adev->haptic_pcm);
4485 adev->haptic_pcm = NULL;
4486 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004487 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304488 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004489 stop_output_stream(out);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004490error_fatal:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05304491 /*
4492 * sleep 50ms to allow sufficient time for kernel
4493 * drivers to recover incases like SSR.
4494 */
4495 usleep(50000);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004496error_config:
Haynes Mathew George380745d2017-10-04 15:27:45 -07004497 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304498 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004499 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004500}
4501
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004502static int check_input_parameters(uint32_t sample_rate,
4503 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08004504 int channel_count,
4505 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004506{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004507 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004508
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304509 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
4510 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
4511 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07004512 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02004513 !audio_extn_compr_cap_format_supported(format) &&
4514 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004515 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004516
Aalique Grahame22e49102018-12-18 14:23:57 -08004517 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
4518 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
4519 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
4520 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
4521 return -EINVAL;
4522 }
4523
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004524 switch (channel_count) {
4525 case 1:
4526 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304527 case 3:
4528 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004529 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07004530 case 8:
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05304531 case 10:
4532 case 12:
4533 case 14:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004534 break;
4535 default:
4536 ret = -EINVAL;
4537 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004538
4539 switch (sample_rate) {
4540 case 8000:
4541 case 11025:
4542 case 12000:
4543 case 16000:
4544 case 22050:
4545 case 24000:
4546 case 32000:
4547 case 44100:
4548 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004549 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304550 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004551 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304552 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004553 break;
4554 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004555 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004556 }
4557
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004558 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004559}
4560
Naresh Tanniru04f71882018-06-26 17:46:22 +05304561
4562/** Add a value in a list if not already present.
4563 * @return true if value was successfully inserted or already present,
4564 * false if the list is full and does not contain the value.
4565 */
4566static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
4567 for (size_t i = 0; i < list_length; i++) {
4568 if (list[i] == value) return true; // value is already present
4569 if (list[i] == 0) { // no values in this slot
4570 list[i] = value;
4571 return true; // value inserted
4572 }
4573 }
4574 return false; // could not insert value
4575}
4576
4577/** Add channel_mask in supported_channel_masks if not already present.
4578 * @return true if channel_mask was successfully inserted or already present,
4579 * false if supported_channel_masks is full and does not contain channel_mask.
4580 */
4581static void register_channel_mask(audio_channel_mask_t channel_mask,
4582 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
4583 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
4584 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
4585}
4586
4587/** Add format in supported_formats if not already present.
4588 * @return true if format was successfully inserted or already present,
4589 * false if supported_formats is full and does not contain format.
4590 */
4591static void register_format(audio_format_t format,
4592 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
4593 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
4594 "%s: stream can not declare supporting its format %x", __func__, format);
4595}
4596/** Add sample_rate in supported_sample_rates if not already present.
4597 * @return true if sample_rate was successfully inserted or already present,
4598 * false if supported_sample_rates is full and does not contain sample_rate.
4599 */
4600static void register_sample_rate(uint32_t sample_rate,
4601 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
4602 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
4603 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
4604}
4605
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004606static inline uint32_t lcm(uint32_t num1, uint32_t num2)
4607{
4608 uint32_t high = num1, low = num2, temp = 0;
4609
4610 if (!num1 || !num2)
4611 return 0;
4612
4613 if (num1 < num2) {
4614 high = num2;
4615 low = num1;
4616 }
4617
4618 while (low != 0) {
4619 temp = low;
4620 low = high % low;
4621 high = temp;
4622 }
4623 return (num1 * num2)/high;
4624}
4625
4626static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
4627{
4628 uint32_t remainder = 0;
4629
4630 if (!multiplier)
4631 return num;
4632
4633 remainder = num % multiplier;
4634 if (remainder)
4635 num += (multiplier - remainder);
4636
4637 return num;
4638}
4639
Aalique Grahame22e49102018-12-18 14:23:57 -08004640static size_t get_stream_buffer_size(size_t duration_ms,
4641 uint32_t sample_rate,
4642 audio_format_t format,
4643 int channel_count,
4644 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004645{
4646 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004647 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004648
Aalique Grahame22e49102018-12-18 14:23:57 -08004649 size = (sample_rate * duration_ms) / 1000;
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +05304650 if (is_low_latency){
4651 switch(sample_rate) {
4652 case 48000:
4653 size = 240;
4654 break;
4655 case 32000:
4656 size = 160;
4657 break;
4658 case 24000:
4659 size = 120;
4660 break;
4661 case 16000:
4662 size = 80;
4663 break;
4664 case 8000:
4665 size = 40;
4666 break;
4667 default:
4668 size = 240;
4669 }
4670 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304671
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004672 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08004673 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004674
Ralf Herzbd08d632018-09-28 15:50:49 +02004675 /* make sure the size is multiple of 32 bytes and additionally multiple of
4676 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004677 * At 48 kHz mono 16-bit PCM:
4678 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
4679 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004680 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004681 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004682 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07004683
4684 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004685}
4686
Aalique Grahame22e49102018-12-18 14:23:57 -08004687static size_t get_input_buffer_size(uint32_t sample_rate,
4688 audio_format_t format,
4689 int channel_count,
4690 bool is_low_latency)
4691{
4692 /* Don't know if USB HIFI in this context so use true to be conservative */
4693 if (check_input_parameters(sample_rate, format, channel_count,
4694 true /*is_usb_hifi */) != 0)
4695 return 0;
4696
4697 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4698 sample_rate,
4699 format,
4700 channel_count,
4701 is_low_latency);
4702}
4703
Derek Chenf6318be2017-06-12 17:16:24 -04004704size_t get_output_period_size(uint32_t sample_rate,
4705 audio_format_t format,
4706 int channel_count,
4707 int duration /*in millisecs*/)
Ashish Jain058165c2016-09-28 23:18:48 +05304708{
4709 size_t size = 0;
4710 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
4711
4712 if ((duration == 0) || (sample_rate == 0) ||
4713 (bytes_per_sample == 0) || (channel_count == 0)) {
4714 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
4715 bytes_per_sample, channel_count);
4716 return -EINVAL;
4717 }
4718
4719 size = (sample_rate *
4720 duration *
4721 bytes_per_sample *
4722 channel_count) / 1000;
4723 /*
4724 * To have same PCM samples for all channels, the buffer size requires to
4725 * be multiple of (number of channels * bytes per sample)
4726 * For writes to succeed, the buffer must be written at address which is multiple of 32
4727 */
4728 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
4729
4730 return (size/(channel_count * bytes_per_sample));
4731}
4732
Zhou Song48453a02018-01-10 17:50:59 +08004733static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05304734{
4735 uint64_t actual_frames_rendered = 0;
Weiyin Jiang4813da12020-05-28 00:37:28 +08004736 uint64_t written_frames = 0;
4737 uint64_t kernel_frames = 0;
4738 uint64_t dsp_frames = 0;
4739 uint64_t signed_frames = 0;
4740 size_t kernel_buffer_size = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304741
4742 /* This adjustment accounts for buffering after app processor.
4743 * It is based on estimated DSP latency per use case, rather than exact.
4744 */
George Gao9ba8a142020-07-23 14:30:03 -07004745 dsp_frames = platform_render_latency(out) *
Weiyin Jiang4813da12020-05-28 00:37:28 +08004746 out->sample_rate / 1000000LL;
Ashish Jain5106d362016-05-11 19:23:33 +05304747
Zhou Song48453a02018-01-10 17:50:59 +08004748 pthread_mutex_lock(&out->position_query_lock);
Weiyin Jiang4813da12020-05-28 00:37:28 +08004749 written_frames = out->written /
4750 (audio_bytes_per_sample(out->hal_ip_format) * popcount(out->channel_mask));
4751
Ashish Jain5106d362016-05-11 19:23:33 +05304752 /* not querying actual state of buffering in kernel as it would involve an ioctl call
4753 * which then needs protection, this causes delay in TS query for pcm_offload usecase
4754 * hence only estimate.
4755 */
Weiyin Jiang4813da12020-05-28 00:37:28 +08004756 kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
4757 kernel_frames = kernel_buffer_size /
4758 (audio_bytes_per_sample(out->hal_op_format) * popcount(out->channel_mask));
Ashish Jain5106d362016-05-11 19:23:33 +05304759
Weiyin Jiang4813da12020-05-28 00:37:28 +08004760 if (written_frames >= (kernel_frames + dsp_frames))
4761 signed_frames = written_frames - kernel_frames - dsp_frames;
Ashish Jain5106d362016-05-11 19:23:33 +05304762
Zhou Song48453a02018-01-10 17:50:59 +08004763 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05304764 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08004765 if (timestamp != NULL )
4766 *timestamp = out->writeAt;
4767 } else if (timestamp != NULL) {
4768 clock_gettime(CLOCK_MONOTONIC, timestamp);
4769 }
4770 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304771
Weiyin Jiang4813da12020-05-28 00:37:28 +08004772 ALOGVV("%s signed frames %lld written frames %lld kernel frames %lld dsp frames %lld",
4773 __func__, signed_frames, written_frames, kernel_frames, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05304774
4775 return actual_frames_rendered;
4776}
4777
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004778static uint32_t out_get_sample_rate(const struct audio_stream *stream)
4779{
4780 struct stream_out *out = (struct stream_out *)stream;
4781
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004782 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004783}
4784
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004785static int out_set_sample_rate(struct audio_stream *stream __unused,
4786 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004787{
4788 return -ENOSYS;
4789}
4790
4791static size_t out_get_buffer_size(const struct audio_stream *stream)
4792{
4793 struct stream_out *out = (struct stream_out *)stream;
4794
Varun Balaraje49253e2017-07-06 19:48:56 +05304795 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05304796 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05304797 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304798 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4799 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
4800 else
4801 return out->compr_config.fragment_size;
4802 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004803 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304804 else if (is_offload_usecase(out->usecase) &&
4805 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304806 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004807
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004808 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004809 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004810}
4811
4812static uint32_t out_get_channels(const struct audio_stream *stream)
4813{
4814 struct stream_out *out = (struct stream_out *)stream;
4815
4816 return out->channel_mask;
4817}
4818
4819static audio_format_t out_get_format(const struct audio_stream *stream)
4820{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004821 struct stream_out *out = (struct stream_out *)stream;
4822
4823 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004824}
4825
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004826static int out_set_format(struct audio_stream *stream __unused,
4827 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004828{
4829 return -ENOSYS;
4830}
4831
4832static int out_standby(struct audio_stream *stream)
4833{
4834 struct stream_out *out = (struct stream_out *)stream;
4835 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07004836 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004837
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304838 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4839 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004840
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004841 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004842 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004843 if (adev->adm_deregister_stream)
4844 adev->adm_deregister_stream(adev->adm_data, out->handle);
4845
Weiyin Jiang280ea742020-09-08 20:28:22 +08004846 if (is_offload_usecase(out->usecase)) {
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004847 stop_compressed_output_l(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08004848 }
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004849
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004850 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004851 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004852 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4853 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304854 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08004855 pthread_mutex_unlock(&adev->lock);
4856 pthread_mutex_unlock(&out->lock);
4857 ALOGD("VOIP output entered standby");
4858 return 0;
4859 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004860 if (out->pcm) {
4861 pcm_close(out->pcm);
4862 out->pcm = NULL;
4863 }
Meng Wanga09da002020-04-20 12:56:04 +08004864 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4865 if (adev->haptic_pcm) {
4866 pcm_close(adev->haptic_pcm);
4867 adev->haptic_pcm = NULL;
4868 }
4869
4870 if (adev->haptic_buffer != NULL) {
4871 free(adev->haptic_buffer);
4872 adev->haptic_buffer = NULL;
4873 adev->haptic_buffer_size = 0;
4874 }
4875 adev->haptic_pcm_device_id = 0;
4876 }
4877
Haynes Mathew George16081042017-05-31 17:16:49 -07004878 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4879 do_stop = out->playback_started;
4880 out->playback_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07004881
4882 if (out->mmap_shared_memory_fd >= 0) {
4883 ALOGV("%s: closing mmap_shared_memory_fd = %d",
4884 __func__, out->mmap_shared_memory_fd);
4885 close(out->mmap_shared_memory_fd);
4886 out->mmap_shared_memory_fd = -1;
4887 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004888 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004889 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004890 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304891 out->send_next_track_params = false;
4892 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004893 out->gapless_mdata.encoder_delay = 0;
4894 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004895 if (out->compr != NULL) {
4896 compress_close(out->compr);
4897 out->compr = NULL;
4898 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004899 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004900 if (do_stop) {
4901 stop_output_stream(out);
4902 }
Lakshman Chaluvaraju06677b42019-06-24 10:04:52 +05304903 // if fm is active route on selected device in UI
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004904 audio_extn_fm_route_on_selected_device(adev, &out->device_list);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004905 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004906 }
4907 pthread_mutex_unlock(&out->lock);
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07004908 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004909 return 0;
4910}
4911
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304912static int out_on_error(struct audio_stream *stream)
4913{
4914 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004915 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304916
4917 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004918 // always send CMD_ERROR for offload streams, this
4919 // is needed e.g. when SSR happens within compress_open
4920 // since the stream is active, offload_callback_thread is also active.
4921 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
4922 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004923 }
4924 pthread_mutex_unlock(&out->lock);
4925
4926 status = out_standby(&out->stream.common);
4927
4928 lock_output_stream(out);
4929 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004930 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304931 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05304932
4933 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
4934 ALOGD("Setting previous card status if offline");
4935 out->prev_card_status_offline = true;
4936 }
4937
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304938 pthread_mutex_unlock(&out->lock);
4939
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004940 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304941}
4942
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304943/*
Weiyin Jiang280ea742020-09-08 20:28:22 +08004944 * standby implementation without locks, assumes that the callee already
4945 * has taken adev and out lock.
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304946 */
4947int out_standby_l(struct audio_stream *stream)
4948{
4949 struct stream_out *out = (struct stream_out *)stream;
4950 struct audio_device *adev = out->dev;
4951
4952 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4953 stream, out->usecase, use_case_table[out->usecase]);
4954
4955 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07004956 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304957 if (adev->adm_deregister_stream)
4958 adev->adm_deregister_stream(adev->adm_data, out->handle);
4959
Weiyin Jiang280ea742020-09-08 20:28:22 +08004960 if (is_offload_usecase(out->usecase)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304961 stop_compressed_output_l(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08004962 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304963
4964 out->standby = true;
4965 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4966 voice_extn_compress_voip_close_output_stream(stream);
4967 out->started = 0;
4968 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07004969 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304970 return 0;
4971 } else if (!is_offload_usecase(out->usecase)) {
4972 if (out->pcm) {
4973 pcm_close(out->pcm);
4974 out->pcm = NULL;
4975 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004976 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4977 if (adev->haptic_pcm) {
4978 pcm_close(adev->haptic_pcm);
4979 adev->haptic_pcm = NULL;
4980 }
4981
4982 if (adev->haptic_buffer != NULL) {
4983 free(adev->haptic_buffer);
4984 adev->haptic_buffer = NULL;
4985 adev->haptic_buffer_size = 0;
4986 }
4987 adev->haptic_pcm_device_id = 0;
4988 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304989 } else {
4990 ALOGD("copl(%p):standby", out);
4991 out->send_next_track_params = false;
4992 out->is_compr_metadata_avail = false;
4993 out->gapless_mdata.encoder_delay = 0;
4994 out->gapless_mdata.encoder_padding = 0;
4995 if (out->compr != NULL) {
4996 compress_close(out->compr);
4997 out->compr = NULL;
4998 }
4999 }
5000 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005001 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305002 }
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07005003 ALOGV("%s: exit", __func__);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305004 return 0;
5005}
5006
Aalique Grahame22e49102018-12-18 14:23:57 -08005007static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005008{
Aalique Grahame22e49102018-12-18 14:23:57 -08005009 struct stream_out *out = (struct stream_out *)stream;
5010
5011 // We try to get the lock for consistency,
5012 // but it isn't necessary for these variables.
5013 // If we're not in standby, we may be blocked on a write.
5014 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
5015 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
5016 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
Dechen Chai22768452021-07-30 09:29:16 +05305017#ifndef LINUX_ENABLED
Andy Hunga1f48fa2019-07-01 18:14:53 -07005018 char buffer[256]; // for statistics formatting
5019 if (!is_offload_usecase(out->usecase)) {
5020 simple_stats_to_string(&out->fifo_underruns, buffer, sizeof(buffer));
5021 dprintf(fd, " Fifo frame underruns: %s\n", buffer);
5022 }
5023
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005024 if (out->start_latency_ms.n > 0) {
5025 simple_stats_to_string(&out->start_latency_ms, buffer, sizeof(buffer));
5026 dprintf(fd, " Start latency ms: %s\n", buffer);
5027 }
Dechen Chai22768452021-07-30 09:29:16 +05305028#endif
Aalique Grahame22e49102018-12-18 14:23:57 -08005029 if (locked) {
5030 pthread_mutex_unlock(&out->lock);
5031 }
5032
Dechen Chai22768452021-07-30 09:29:16 +05305033#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -08005034 // dump error info
5035 (void)error_log_dump(
5036 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Dechen Chai22768452021-07-30 09:29:16 +05305037#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005038 return 0;
5039}
5040
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005041static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
5042{
5043 int ret = 0;
5044 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08005045
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005046 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08005047 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005048 return -EINVAL;
5049 }
5050
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05305051 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08005052
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005053 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
5054 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05305055 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005056 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005057 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
5058 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05305059 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005060 }
5061
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005062 ALOGV("%s new encoder delay %u and padding %u", __func__,
5063 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
5064
5065 return 0;
5066}
5067
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005068static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
5069{
5070 return out == adev->primary_output || out == adev->voice_tx_output;
5071}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005072
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305073// note: this call is safe only if the stream_cb is
5074// removed first in close_output_stream (as is done now).
5075static void out_snd_mon_cb(void * stream, struct str_parms * parms)
5076{
5077 if (!stream || !parms)
5078 return;
5079
5080 struct stream_out *out = (struct stream_out *)stream;
5081 struct audio_device *adev = out->dev;
5082
5083 card_status_t status;
5084 int card;
5085 if (parse_snd_card_status(parms, &card, &status) < 0)
5086 return;
5087
5088 pthread_mutex_lock(&adev->lock);
5089 bool valid_cb = (card == adev->snd_card);
5090 pthread_mutex_unlock(&adev->lock);
5091
5092 if (!valid_cb)
5093 return;
5094
5095 lock_output_stream(out);
5096 if (out->card_status != status)
5097 out->card_status = status;
5098 pthread_mutex_unlock(&out->lock);
5099
5100 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
5101 use_case_table[out->usecase],
5102 status == CARD_STATUS_OFFLINE ? "offline" : "online");
5103
Aditya Bavanari59ebed42019-02-05 17:44:57 +05305104 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305105 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05305106 if (voice_is_call_state_active(adev) &&
5107 out == adev->primary_output) {
5108 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
5109 pthread_mutex_lock(&adev->lock);
5110 voice_stop_call(adev);
5111 adev->mode = AUDIO_MODE_NORMAL;
5112 pthread_mutex_unlock(&adev->lock);
5113 }
5114 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305115 return;
5116}
5117
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005118int route_output_stream(struct stream_out *out,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005119 struct listnode *devices)
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005120{
5121 struct audio_device *adev = out->dev;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005122 int ret = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005123 struct listnode new_devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005124 bool bypass_a2dp = false;
5125 bool reconfig = false;
5126 unsigned long service_interval = 0;
5127
5128 ALOGD("%s: enter: usecase(%d: %s) devices %x",
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005129 __func__, out->usecase, use_case_table[out->usecase], get_device_types(devices));
5130
5131 list_init(&new_devices);
5132 assign_devices(&new_devices, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005133
5134 lock_output_stream(out);
5135 pthread_mutex_lock(&adev->lock);
5136
5137 /*
5138 * When HDMI cable is unplugged the music playback is paused and
5139 * the policy manager sends routing=0. But the audioflinger continues
5140 * to write data until standby time (3sec). As the HDMI core is
5141 * turned off, the write gets blocked.
5142 * Avoid this by routing audio to speaker until standby.
5143 */
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08005144 if (is_single_device_type_equal(&out->device_list,
5145 AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005146 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005147 !audio_extn_passthru_is_passthrough_stream(out) &&
5148 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005149 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005150 }
5151 /*
5152 * When A2DP is disconnected the
5153 * music playback is paused and the policy manager sends routing=0
5154 * But the audioflinger continues to write data until standby time
5155 * (3sec). As BT is turned off, the write gets blocked.
5156 * Avoid this by routing audio to speaker until standby.
5157 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005158 if (is_a2dp_out_device_type(&out->device_list) &&
5159 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005160 !audio_extn_a2dp_source_is_ready() &&
5161 !adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005162 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005163 }
5164 /*
Weiyin Jiangabedea32020-12-09 12:49:19 +08005165 * When USB headset is disconnected the music playback paused
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005166 * and the policy manager send routing=0. But if the USB is connected
5167 * back before the standby time, AFE is not closed and opened
5168 * when USB is connected back. So routing to speker will guarantee
5169 * AFE reconfiguration and AFE will be opend once USB is connected again
5170 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005171 if (is_usb_out_device_type(&out->device_list) &&
5172 list_empty(&new_devices) &&
5173 !audio_extn_usb_connected(NULL)) {
Sujin Panicker84d953a2020-11-16 17:39:54 +05305174 if (adev->mode == AUDIO_MODE_IN_CALL || adev->mode == AUDIO_MODE_IN_COMMUNICATION)
5175 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_EARPIECE, "");
5176 else
5177 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005178 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005179 /* To avoid a2dp to sco overlapping / BT device improper state
5180 * check with BT lib about a2dp streaming support before routing
5181 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005182 if (is_a2dp_out_device_type(&new_devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005183 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005184 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER) ||
5185 compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005186 //combo usecase just by pass a2dp
5187 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
5188 bypass_a2dp = true;
5189 } else {
5190 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
5191 /* update device to a2dp and don't route as BT returned error
5192 * However it is still possible a2dp routing called because
5193 * of current active device disconnection (like wired headset)
5194 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005195 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005196 pthread_mutex_unlock(&adev->lock);
5197 pthread_mutex_unlock(&out->lock);
5198 goto error;
5199 }
5200 }
5201 }
5202
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005203 // Workaround: If routing to an non existing usb device, fail gracefully
5204 // The routing request will otherwise block during 10 second
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005205 if (is_usb_out_device_type(&new_devices)) {
5206 struct str_parms *parms =
5207 str_parms_create_str(get_usb_device_address(&new_devices));
5208 if (!parms)
5209 goto error;
Weiyin Jiangabedea32020-12-09 12:49:19 +08005210 if (!audio_extn_usb_connected(NULL)) {
5211 ALOGW("%s: ignoring rerouting to non existing USB card", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005212 pthread_mutex_unlock(&adev->lock);
5213 pthread_mutex_unlock(&out->lock);
5214 str_parms_destroy(parms);
5215 ret = -ENOSYS;
5216 goto error;
5217 }
5218 str_parms_destroy(parms);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005219 }
5220
Weiyin Jiang80c8f9a2020-01-10 20:42:08 +08005221 // Workaround: If routing to an non existing hdmi device, fail gracefully
5222 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
5223 (platform_get_edid_info_v2(adev->platform,
5224 out->extconn.cs.controller,
5225 out->extconn.cs.stream) != 0)) {
5226 ALOGW("out_set_parameters() ignoring rerouting to non existing HDMI/DP");
5227 pthread_mutex_unlock(&adev->lock);
5228 pthread_mutex_unlock(&out->lock);
5229 ret = -ENOSYS;
5230 goto error;
5231 }
5232
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005233 /*
5234 * select_devices() call below switches all the usecases on the same
5235 * backend to the new device. Refer to check_usecases_codec_backend() in
5236 * the select_devices(). But how do we undo this?
5237 *
5238 * For example, music playback is active on headset (deep-buffer usecase)
5239 * and if we go to ringtones and select a ringtone, low-latency usecase
5240 * will be started on headset+speaker. As we can't enable headset+speaker
5241 * and headset devices at the same time, select_devices() switches the music
5242 * playback to headset+speaker while starting low-lateny usecase for ringtone.
5243 * So when the ringtone playback is completed, how do we undo the same?
5244 *
5245 * We are relying on the out_set_parameters() call on deep-buffer output,
5246 * once the ringtone playback is ended.
5247 * NOTE: We should not check if the current devices are same as new devices.
5248 * Because select_devices() must be called to switch back the music
5249 * playback to headset.
5250 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005251 if (!list_empty(&new_devices)) {
5252 bool same_dev = compare_devices(&out->device_list, &new_devices);
5253 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005254
5255 if (output_drives_call(adev, out)) {
5256 if (!voice_is_call_state_active(adev)) {
5257 if (adev->mode == AUDIO_MODE_IN_CALL) {
5258 adev->current_call_output = out;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005259 ret = voice_start_call(adev);
5260 }
5261 } else {
Kunlei Zhang253ad102020-10-14 16:21:28 +08005262 platform_is_volume_boost_supported_device(adev->platform, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005263 adev->current_call_output = out;
5264 voice_update_devices_for_all_voice_usecases(adev);
5265 }
5266 }
5267
Mingshu Pang971ff702020-09-09 15:28:22 +08005268 if (is_usb_out_device_type(&out->device_list)) {
5269 service_interval = audio_extn_usb_find_service_interval(false, true /*playback*/);
5270 audio_extn_usb_set_service_interval(true /*playback*/,
5271 service_interval,
5272 &reconfig);
5273 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
5274 }
5275
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005276 if (!out->standby) {
5277 if (!same_dev) {
5278 ALOGV("update routing change");
5279 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
5280 adev->perf_lock_opts,
5281 adev->perf_lock_opts_size);
5282 if (adev->adm_on_routing_change)
5283 adev->adm_on_routing_change(adev->adm_data,
5284 out->handle);
5285 }
5286 if (!bypass_a2dp) {
5287 select_devices(adev, out->usecase);
5288 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005289 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
5290 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005291 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005292 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005293 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005294 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005295 }
5296
5297 if (!same_dev) {
5298 // on device switch force swap, lower functions will make sure
5299 // to check if swap is allowed or not.
5300 platform_set_swap_channels(adev, true);
5301 audio_extn_perf_lock_release(&adev->perf_lock_handle);
5302 }
Zhou Songbaddf9f2020-11-20 13:57:39 +08005303 pthread_mutex_lock(&out->latch_lock);
5304 if (!is_a2dp_out_device_type(&out->device_list) || audio_extn_a2dp_source_is_ready()) {
5305 if (out->a2dp_muted) {
5306 out->a2dp_muted = false;
5307 if (is_offload_usecase(out->usecase))
5308 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5309 else if (out->usecase != USECASE_AUDIO_PLAYBACK_VOIP)
5310 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Weiyin Jiang280ea742020-09-08 20:28:22 +08005311 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005312 }
Zhou Songbaddf9f2020-11-20 13:57:39 +08005313 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP && !out->a2dp_muted)
5314 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
5315 pthread_mutex_unlock(&out->latch_lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005316 }
5317 }
5318
5319 pthread_mutex_unlock(&adev->lock);
5320 pthread_mutex_unlock(&out->lock);
5321
5322 /*handles device and call state changes*/
5323 audio_extn_extspk_update(adev->extspk);
5324
Revathi Uddaraju4255a632021-12-02 05:11:13 -08005325 clear_devices(&new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005326error:
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005327 ALOGV("%s: exit: code(%d)", __func__, ret);
5328 return ret;
5329}
5330
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005331static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
5332{
5333 struct stream_out *out = (struct stream_out *)stream;
5334 struct audio_device *adev = out->dev;
5335 struct str_parms *parms;
5336 char value[32];
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005337 int ret = 0, err;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005338 int ext_controller = -1;
5339 int ext_stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005340
sangwoobc677242013-08-08 16:53:43 +09005341 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005342 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005343 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305344 if (!parms)
5345 goto error;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005346
5347 err = platform_get_controller_stream_from_params(parms, &ext_controller,
5348 &ext_stream);
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08005349 if (err == 0) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005350 out->extconn.cs.controller = ext_controller;
5351 out->extconn.cs.stream = ext_stream;
5352 ALOGD("%s: usecase(%s) new controller/stream (%d/%d)", __func__,
5353 use_case_table[out->usecase], out->extconn.cs.controller,
5354 out->extconn.cs.stream);
5355 }
5356
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005357 if (out == adev->primary_output) {
5358 pthread_mutex_lock(&adev->lock);
5359 audio_extn_set_parameters(adev, parms);
5360 pthread_mutex_unlock(&adev->lock);
5361 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005362 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005363 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005364 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005365
5366 audio_extn_dts_create_state_notifier_node(out->usecase);
5367 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5368 popcount(out->channel_mask),
5369 out->playback_started);
5370
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08005371 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005372 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005373
Surendar Karkaf51b5842018-04-26 11:28:38 +05305374 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
5375 sizeof(value));
5376 if (err >= 0) {
5377 if (!strncmp("true", value, sizeof("true")) || atoi(value))
5378 audio_extn_send_dual_mono_mixing_coefficients(out);
5379 }
5380
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305381 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5382 if (err >= 0) {
5383 strlcpy(out->profile, value, sizeof(out->profile));
5384 ALOGV("updating stream profile with value '%s'", out->profile);
5385 lock_output_stream(out);
5386 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
5387 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005388 &out->device_list, out->flags,
5389 out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305390 out->sample_rate, out->bit_width,
5391 out->channel_mask, out->profile,
5392 &out->app_type_cfg);
5393 pthread_mutex_unlock(&out->lock);
5394 }
5395
Alexy Joseph98988832017-01-13 14:56:59 -08005396 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005397 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
5398 // and vendor.audio.hal.output.suspend.supported is set to true
5399 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08005400 //check suspend parameter only for low latency and if the property
5401 //is enabled
5402 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
5403 ALOGI("%s: got suspend_playback %s", __func__, value);
5404 lock_output_stream(out);
5405 if (!strncmp(value, "false", 5)) {
5406 //suspend_playback=false is supposed to set QOS value back to 75%
5407 //the mixer control sent with value Enable will achieve that
5408 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5409 } else if (!strncmp (value, "true", 4)) {
5410 //suspend_playback=true is supposed to remove QOS value
5411 //resetting the mixer control will set the default value
5412 //for the mixer control which is Disable and this removes the QOS vote
5413 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5414 } else {
5415 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
5416 " got %s", __func__, value);
5417 ret = -1;
5418 }
5419
5420 if (ret != 0) {
5421 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
5422 __func__, out->pm_qos_mixer_path, ret);
5423 }
5424
5425 pthread_mutex_unlock(&out->lock);
5426 }
5427 }
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005428
Alexy Joseph98988832017-01-13 14:56:59 -08005429 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005430 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305431error:
Eric Laurent994a6932013-07-17 11:51:42 -07005432 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005433 return ret;
5434}
5435
Paul McLeana50b7332018-12-17 08:24:21 -07005436static int in_set_microphone_direction(const struct audio_stream_in *stream,
5437 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07005438 struct stream_in *in = (struct stream_in *)stream;
5439
5440 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
5441
5442 in->direction = dir;
5443
5444 if (in->standby)
5445 return 0;
5446
5447 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07005448}
5449
5450static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07005451 struct stream_in *in = (struct stream_in *)stream;
5452
5453 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
5454
5455 if (zoom > 1.0 || zoom < -1.0)
5456 return -EINVAL;
5457
5458 in->zoom = zoom;
5459
5460 if (in->standby)
5461 return 0;
5462
5463 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07005464}
5465
5466
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005467static bool stream_get_parameter_channels(struct str_parms *query,
5468 struct str_parms *reply,
5469 audio_channel_mask_t *supported_channel_masks) {
5470 int ret = -1;
5471 char value[512];
5472 bool first = true;
5473 size_t i, j;
5474
5475 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
5476 ret = 0;
5477 value[0] = '\0';
5478 i = 0;
5479 while (supported_channel_masks[i] != 0) {
5480 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5481 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
5482 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305483 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005484
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305485 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005486 first = false;
5487 break;
5488 }
5489 }
5490 i++;
5491 }
5492 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5493 }
5494 return ret == 0;
5495}
5496
5497static bool stream_get_parameter_formats(struct str_parms *query,
5498 struct str_parms *reply,
5499 audio_format_t *supported_formats) {
5500 int ret = -1;
5501 char value[256];
5502 size_t i, j;
5503 bool first = true;
5504
5505 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
5506 ret = 0;
5507 value[0] = '\0';
5508 i = 0;
5509 while (supported_formats[i] != 0) {
5510 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5511 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
5512 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305513 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005514 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305515 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005516 first = false;
5517 break;
5518 }
5519 }
5520 i++;
5521 }
5522 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
5523 }
5524 return ret == 0;
5525}
5526
5527static bool stream_get_parameter_rates(struct str_parms *query,
5528 struct str_parms *reply,
5529 uint32_t *supported_sample_rates) {
5530
5531 int i;
5532 char value[256];
5533 int ret = -1;
5534 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
5535 ret = 0;
5536 value[0] = '\0';
5537 i=0;
5538 int cursor = 0;
5539 while (supported_sample_rates[i]) {
5540 int avail = sizeof(value) - cursor;
5541 ret = snprintf(value + cursor, avail, "%s%d",
5542 cursor > 0 ? "|" : "",
5543 supported_sample_rates[i]);
5544 if (ret < 0 || ret >= avail) {
5545 // if cursor is at the last element of the array
5546 // overwrite with \0 is duplicate work as
5547 // snprintf already put a \0 in place.
5548 // else
5549 // we had space to write the '|' at value[cursor]
5550 // (which will be overwritten) or no space to fill
5551 // the first element (=> cursor == 0)
5552 value[cursor] = '\0';
5553 break;
5554 }
5555 cursor += ret;
5556 ++i;
5557 }
5558 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
5559 value);
5560 }
5561 return ret >= 0;
5562}
5563
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005564static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
5565{
5566 struct stream_out *out = (struct stream_out *)stream;
5567 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005568 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005569 char value[256];
5570 struct str_parms *reply = str_parms_create();
5571 size_t i, j;
5572 int ret;
5573 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005574
5575 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005576 if (reply) {
5577 str_parms_destroy(reply);
5578 }
5579 if (query) {
5580 str_parms_destroy(query);
5581 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005582 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
5583 return NULL;
5584 }
5585
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005586 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005587 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
5588 if (ret >= 0) {
5589 value[0] = '\0';
5590 i = 0;
5591 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005592 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5593 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005594 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005595 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005596 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005597 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005598 first = false;
5599 break;
5600 }
5601 }
5602 i++;
5603 }
5604 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5605 str = str_parms_to_str(reply);
5606 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005607 voice_extn_out_get_parameters(out, query, reply);
5608 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005609 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005610
Alexy Joseph62142aa2015-11-16 15:10:34 -08005611
5612 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
5613 if (ret >= 0) {
5614 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05305615 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
5616 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08005617 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305618 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005619 } else {
5620 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05305621 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005622 }
5623 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005624 if (str)
5625 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08005626 str = str_parms_to_str(reply);
5627 }
5628
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005629 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
5630 if (ret >= 0) {
5631 value[0] = '\0';
5632 i = 0;
5633 first = true;
5634 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005635 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5636 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005637 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005638 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005639 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005640 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005641 first = false;
5642 break;
5643 }
5644 }
5645 i++;
5646 }
5647 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005648 if (str)
5649 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005650 str = str_parms_to_str(reply);
5651 }
Mingming Yin3a941d42016-02-17 18:08:05 -08005652
5653 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
5654 if (ret >= 0) {
5655 value[0] = '\0';
5656 i = 0;
5657 first = true;
5658 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005659 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
5660 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005661 if (!first) {
5662 strlcat(value, "|", sizeof(value));
5663 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005664 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08005665 first = false;
5666 break;
5667 }
5668 }
5669 i++;
5670 }
5671 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
5672 if (str)
5673 free(str);
5674 str = str_parms_to_str(reply);
5675 }
5676
Alexy Joseph98988832017-01-13 14:56:59 -08005677 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
5678 //only low latency track supports suspend_resume
5679 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005680 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08005681 if (str)
5682 free(str);
5683 str = str_parms_to_str(reply);
5684 }
5685
5686
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005687 str_parms_destroy(query);
5688 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07005689 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005690 return str;
5691}
5692
5693static uint32_t out_get_latency(const struct audio_stream_out *stream)
5694{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005695 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005696 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08005697 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005698
Alexy Josephaa54c872014-12-03 02:46:47 -08005699 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05305700 lock_output_stream(out);
5701 latency = audio_extn_utils_compress_get_dsp_latency(out);
5702 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005703 } else if ((out->realtime) ||
5704 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005705 // since the buffer won't be filled up faster than realtime,
5706 // return a smaller number
5707 if (out->config.rate)
5708 period_ms = (out->af_period_multiplier * out->config.period_size *
5709 1000) / (out->config.rate);
5710 else
5711 period_ms = 0;
George Gao9ba8a142020-07-23 14:30:03 -07005712 latency = period_ms + platform_render_latency(out) / 1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005713 } else {
5714 latency = (out->config.period_count * out->config.period_size * 1000) /
Mingshu Pangf69a88d2021-04-30 16:14:39 +08005715 (out->config.rate);
pavanisra2d95d82022-02-09 18:55:58 +05305716 if (out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5717 out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY)
Mingshu Pangf69a88d2021-04-30 16:14:39 +08005718 latency += platform_render_latency(out)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005719 }
5720
Zhou Songd2537a02020-06-11 22:04:46 +08005721 if (!out->standby && is_a2dp_out_device_type(&out->device_list))
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08005722 latency += audio_extn_a2dp_get_encoder_latency();
5723
Anish Kumar50ebcbf2014-12-09 04:01:39 +05305724 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08005725 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005726}
5727
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305728static float AmpToDb(float amplification)
5729{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305730 float db = DSD_VOLUME_MIN_DB;
5731 if (amplification > 0) {
5732 db = 20 * log10(amplification);
5733 if(db < DSD_VOLUME_MIN_DB)
5734 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305735 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305736 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305737}
5738
Krishna Kishor Jha10ad39f2022-02-21 17:02:47 +05305739#ifdef SOFT_VOLUME
5740static int out_set_soft_volume_params(struct audio_stream_out *stream)
5741{
5742 struct stream_out *out = (struct stream_out *)stream;
5743 int ret = 0;
5744 char mixer_ctl_name[128];
5745 struct audio_device *adev = out->dev;
5746 struct mixer_ctl *ctl = NULL;
5747 struct soft_step_volume_params *volume_params = NULL;
5748
5749 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5750 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Soft Vol Params", pcm_device_id);
5751 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5752 if (!ctl) {
5753 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5754 return -EINVAL;
5755 }
5756
5757 volume_params =(struct soft_step_volume_params * ) malloc(sizeof(struct soft_step_volume_params));
5758 if (volume_params == NULL){
5759 ALOGE("%s : malloc is failed for volume params", __func__);
5760 return -EINVAL;
5761 } else {
5762 ret = platform_get_soft_step_volume_params(volume_params,out->usecase);
5763 if (ret < 0) {
5764 ALOGE("%s : platform_get_soft_step_volume_params is fialed", __func__);
5765 return -EINVAL;
5766 }
5767
5768 }
5769 ret = mixer_ctl_set_array(ctl, volume_params, sizeof(struct soft_step_volume_params)/sizeof(int));
5770 if (ret < 0) {
5771 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
5772 return -EINVAL;
5773 }
5774 return 0;
5775}
5776#endif
5777
Arun Mirpuri5d170872019-03-26 13:21:31 -07005778static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
5779 float right)
5780{
5781 struct stream_out *out = (struct stream_out *)stream;
5782 long volume = 0;
5783 char mixer_ctl_name[128] = "";
5784 struct audio_device *adev = out->dev;
5785 struct mixer_ctl *ctl = NULL;
5786 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5787 PCM_PLAYBACK);
5788
5789 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5790 "Playback %d Volume", pcm_device_id);
5791 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5792 if (!ctl) {
5793 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5794 __func__, mixer_ctl_name);
5795 return -EINVAL;
5796 }
5797 if (left != right)
5798 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
5799 __func__, left, right);
5800 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
5801 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
5802 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
5803 __func__, mixer_ctl_name, volume);
5804 return -EINVAL;
5805 }
5806 return 0;
5807}
5808
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305809static int out_set_compr_volume(struct audio_stream_out *stream, float left,
5810 float right)
5811{
5812 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305813 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305814 char mixer_ctl_name[128];
5815 struct audio_device *adev = out->dev;
5816 struct mixer_ctl *ctl;
5817 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5818 PCM_PLAYBACK);
5819
5820 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5821 "Compress Playback %d Volume", pcm_device_id);
5822 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5823 if (!ctl) {
5824 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5825 __func__, mixer_ctl_name);
5826 return -EINVAL;
5827 }
5828 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
5829 __func__, mixer_ctl_name, left, right);
5830 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
5831 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
5832 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5833
5834 return 0;
5835}
5836
Zhou Song2b8f28f2017-09-11 10:51:38 +08005837static int out_set_voip_volume(struct audio_stream_out *stream, float left,
5838 float right)
5839{
5840 struct stream_out *out = (struct stream_out *)stream;
5841 char mixer_ctl_name[] = "App Type Gain";
5842 struct audio_device *adev = out->dev;
5843 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305844 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08005845
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07005846 if (!is_valid_volume(left, right)) {
5847 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
5848 __func__, left, right);
5849 return -EINVAL;
5850 }
5851
Zhou Song2b8f28f2017-09-11 10:51:38 +08005852 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5853 if (!ctl) {
5854 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5855 __func__, mixer_ctl_name);
5856 return -EINVAL;
5857 }
5858
5859 set_values[0] = 0; //0: Rx Session 1:Tx Session
5860 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305861 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
5862 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005863
5864 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
5865 return 0;
5866}
5867
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305868static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
5869 float right)
5870{
5871 struct stream_out *out = (struct stream_out *)stream;
5872 /* Volume control for pcm playback */
5873 if (left != right) {
5874 return -EINVAL;
5875 } else {
5876 char mixer_ctl_name[128];
5877 struct audio_device *adev = out->dev;
5878 struct mixer_ctl *ctl;
5879 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5880 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
5881 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5882 if (!ctl) {
5883 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5884 return -EINVAL;
5885 }
5886
5887 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
5888 int ret = mixer_ctl_set_value(ctl, 0, volume);
5889 if (ret < 0) {
5890 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
5891 return -EINVAL;
5892 }
5893
5894 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
5895
5896 return 0;
5897 }
5898}
5899
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005900static int out_set_volume(struct audio_stream_out *stream, float left,
5901 float right)
5902{
Eric Laurenta9024de2013-04-04 09:19:12 -07005903 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005904 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305905 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005906
Arun Mirpuri5d170872019-03-26 13:21:31 -07005907 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07005908 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
5909 /* only take left channel into account: the API is for stereo anyway */
5910 out->muted = (left == 0.0f);
5911 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005912 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305913 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005914 /*
5915 * Set mute or umute on HDMI passthrough stream.
5916 * Only take left channel into account.
5917 * Mute is 0 and unmute 1
5918 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305919 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305920 } else if (out->format == AUDIO_FORMAT_DSD){
5921 char mixer_ctl_name[128] = "DSD Volume";
5922 struct audio_device *adev = out->dev;
5923 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5924
5925 if (!ctl) {
5926 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5927 __func__, mixer_ctl_name);
5928 return -EINVAL;
5929 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05305930 volume[0] = (long)(AmpToDb(left));
5931 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305932 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5933 return 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005934 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS) &&
Derek Chendf05eea2019-08-01 13:57:49 -07005935 (out->car_audio_stream == CAR_AUDIO_STREAM_MEDIA)) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005936 ALOGD("%s: Overriding offload set volume for media bus stream", __func__);
5937 struct listnode *node = NULL;
5938 list_for_each(node, &adev->active_outputs_list) {
5939 streams_output_ctxt_t *out_ctxt = node_to_item(node,
5940 streams_output_ctxt_t,
5941 list);
5942 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
5943 out->volume_l = out_ctxt->output->volume_l;
5944 out->volume_r = out_ctxt->output->volume_r;
5945 }
5946 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08005947 pthread_mutex_lock(&out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +08005948 if (!out->a2dp_muted) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005949 ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5950 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08005951 pthread_mutex_unlock(&out->latch_lock);
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005952 return ret;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005953 } else {
Weiyin Jiang280ea742020-09-08 20:28:22 +08005954 pthread_mutex_lock(&out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +08005955 ALOGV("%s: compress mute %d", __func__, out->a2dp_muted);
5956 if (!out->a2dp_muted)
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305957 ret = out_set_compr_volume(stream, left, right);
5958 out->volume_l = left;
5959 out->volume_r = right;
Weiyin Jiang280ea742020-09-08 20:28:22 +08005960 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305961 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005962 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005963 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005964 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
5965 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Songbaddf9f2020-11-20 13:57:39 +08005966 pthread_mutex_lock(&out->latch_lock);
Aalique Grahame22e49102018-12-18 14:23:57 -08005967 if (!out->standby) {
5968 audio_extn_utils_send_app_type_gain(out->dev,
5969 out->app_type_cfg.app_type,
5970 &out->app_type_cfg.gain[0]);
Zhou Songbaddf9f2020-11-20 13:57:39 +08005971 if (!out->a2dp_muted)
5972 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08005973 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08005974 out->volume_l = left;
5975 out->volume_r = right;
Zhou Songbaddf9f2020-11-20 13:57:39 +08005976 pthread_mutex_unlock(&out->latch_lock);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005977 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005978 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5979 ALOGV("%s: MMAP set volume called", __func__);
5980 if (!out->standby)
5981 ret = out_set_mmap_volume(stream, left, right);
5982 out->volume_l = left;
5983 out->volume_r = right;
5984 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305985 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05305986 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5987 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Zhou Songbaddf9f2020-11-20 13:57:39 +08005988 pthread_mutex_lock(&out->latch_lock);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305989 /* Volume control for pcm playback */
Zhou Songbaddf9f2020-11-20 13:57:39 +08005990 if (!out->standby && !out->a2dp_muted)
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305991 ret = out_set_pcm_volume(stream, left, right);
5992 else
5993 out->apply_volume = true;
5994
5995 out->volume_l = left;
5996 out->volume_r = right;
Zhou Songbaddf9f2020-11-20 13:57:39 +08005997 pthread_mutex_unlock(&out->latch_lock);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305998 return ret;
Derek Chenf13dd492018-11-13 14:53:51 -08005999 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
6000 ALOGV("%s: bus device set volume called", __func__);
Zhou Songbaddf9f2020-11-20 13:57:39 +08006001 pthread_mutex_lock(&out->latch_lock);
6002 if (!out->standby && !out->a2dp_muted)
Derek Chenf13dd492018-11-13 14:53:51 -08006003 ret = out_set_pcm_volume(stream, left, right);
6004 out->volume_l = left;
6005 out->volume_r = right;
Zhou Songbaddf9f2020-11-20 13:57:39 +08006006 pthread_mutex_unlock(&out->latch_lock);
Derek Chenf13dd492018-11-13 14:53:51 -08006007 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07006008 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006009
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006010 return -ENOSYS;
6011}
6012
Zhou Songc9672822017-08-16 16:01:39 +08006013static void update_frames_written(struct stream_out *out, size_t bytes)
6014{
6015 size_t bpf = 0;
6016
6017 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
6018 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
6019 bpf = 1;
6020 else if (!is_offload_usecase(out->usecase))
6021 bpf = audio_bytes_per_sample(out->format) *
6022 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08006023
6024 pthread_mutex_lock(&out->position_query_lock);
6025 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08006026 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08006027 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
6028 }
6029 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08006030}
6031
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006032int split_and_write_audio_haptic_data(struct stream_out *out,
6033 const void *buffer, size_t bytes_to_write)
6034{
6035 struct audio_device *adev = out->dev;
6036
6037 int ret = 0;
6038 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
6039 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
6040 size_t frame_size = channel_count * bytes_per_sample;
6041 size_t frame_count = bytes_to_write / frame_size;
6042
6043 bool force_haptic_path =
6044 property_get_bool("vendor.audio.test_haptic", false);
6045
6046 // extract Haptics data from Audio buffer
6047 bool alloc_haptic_buffer = false;
6048 int haptic_channel_count = adev->haptics_config.channels;
6049 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
6050 size_t audio_frame_size = frame_size - haptic_frame_size;
6051 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
6052
6053 if (adev->haptic_buffer == NULL) {
6054 alloc_haptic_buffer = true;
6055 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
6056 free(adev->haptic_buffer);
6057 adev->haptic_buffer_size = 0;
6058 alloc_haptic_buffer = true;
6059 }
6060
6061 if (alloc_haptic_buffer) {
6062 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08006063 if(adev->haptic_buffer == NULL) {
6064 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
6065 return -ENOMEM;
6066 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006067 adev->haptic_buffer_size = total_haptic_buffer_size;
6068 }
6069
6070 size_t src_index = 0, aud_index = 0, hap_index = 0;
6071 uint8_t *audio_buffer = (uint8_t *)buffer;
6072 uint8_t *haptic_buffer = adev->haptic_buffer;
6073
6074 // This is required for testing only. This works for stereo data only.
6075 // One channel is fed to audio stream and other to haptic stream for testing.
6076 if (force_haptic_path)
6077 audio_frame_size = haptic_frame_size = bytes_per_sample;
6078
6079 for (size_t i = 0; i < frame_count; i++) {
6080 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
6081 audio_frame_size);
6082 aud_index += audio_frame_size;
6083 src_index += audio_frame_size;
6084
6085 if (adev->haptic_pcm)
6086 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
6087 haptic_frame_size);
6088 hap_index += haptic_frame_size;
6089 src_index += haptic_frame_size;
6090
6091 // This is required for testing only.
6092 // Discard haptic channel data.
6093 if (force_haptic_path)
6094 src_index += haptic_frame_size;
6095 }
6096
6097 // write to audio pipeline
6098 ret = pcm_write(out->pcm, (void *)audio_buffer,
6099 frame_count * audio_frame_size);
6100
6101 // write to haptics pipeline
6102 if (adev->haptic_pcm)
6103 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
6104 frame_count * haptic_frame_size);
6105
6106 return ret;
6107}
6108
Aalique Grahame22e49102018-12-18 14:23:57 -08006109#ifdef NO_AUDIO_OUT
6110static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
6111 const void *buffer __unused, size_t bytes)
6112{
6113 struct stream_out *out = (struct stream_out *)stream;
6114
6115 /* No Output device supported other than BT for playback.
6116 * Sleep for the amount of buffer duration
6117 */
6118 lock_output_stream(out);
6119 usleep(bytes * 1000000 / audio_stream_out_frame_size(
6120 (const struct audio_stream_out *)&out->stream) /
6121 out_get_sample_rate(&out->stream.common));
6122 pthread_mutex_unlock(&out->lock);
6123 return bytes;
6124}
6125#endif
6126
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006127static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
6128 size_t bytes)
6129{
6130 struct stream_out *out = (struct stream_out *)stream;
6131 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07006132 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05306133 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006134 const size_t frame_size = audio_stream_out_frame_size(stream);
6135 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05306136 struct audio_usecase *usecase = NULL;
Meng Wang4c32fb42020-01-16 17:57:11 +08006137 uint32_t compr_passthr = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006138
Haynes Mathew George380745d2017-10-04 15:27:45 -07006139 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006140 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306141
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306142 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08006143
Dhananjay Kumarac341582017-02-23 23:42:25 +05306144 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306145 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05306146 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
6147 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006148 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05306149 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05306150 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05306151 ALOGD(" %s: sound card is not active/SSR state", __func__);
6152 ret= -EIO;
6153 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306154 }
6155 }
6156
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306157 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05306158 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05306159 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306160 goto exit;
6161 }
6162
Haynes Mathew George16081042017-05-31 17:16:49 -07006163 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
6164 ret = -EINVAL;
6165 goto exit;
6166 }
6167
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006168 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306169 !out->is_iec61937_info_available) {
6170
6171 if (!audio_extn_passthru_is_passthrough_stream(out)) {
6172 out->is_iec61937_info_available = true;
6173 } else if (audio_extn_passthru_is_enabled()) {
6174 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05306175 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05306176
6177 if((out->format == AUDIO_FORMAT_DTS) ||
6178 (out->format == AUDIO_FORMAT_DTS_HD)) {
6179 ret = audio_extn_passthru_update_dts_stream_configuration(out,
6180 buffer, bytes);
6181 if (ret) {
6182 if (ret != -ENOSYS) {
6183 out->is_iec61937_info_available = false;
6184 ALOGD("iec61937 transmission info not yet updated retry");
6185 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306186 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05306187 /* if stream has started and after that there is
6188 * stream config change (iec transmission config)
6189 * then trigger select_device to update backend configuration.
6190 */
6191 out->stream_config_changed = true;
6192 pthread_mutex_lock(&adev->lock);
6193 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306194 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08006195 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306196 ret = -EINVAL;
6197 goto exit;
6198 }
Manish Dewangan671a4202017-08-18 17:30:46 +05306199 pthread_mutex_unlock(&adev->lock);
6200 out->stream_config_changed = false;
6201 out->is_iec61937_info_available = true;
6202 }
6203 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05306204
Meng Wang4c32fb42020-01-16 17:57:11 +08006205#ifdef AUDIO_GKI_ENABLED
6206 /* out->compr_config.codec->reserved[0] is for compr_passthr */
6207 compr_passthr = out->compr_config.codec->reserved[0];
6208#else
6209 compr_passthr = out->compr_config.codec->compr_passthr;
6210#endif
6211
Garmond Leung317cbf12017-09-13 16:20:50 -07006212 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Meng Wang4c32fb42020-01-16 17:57:11 +08006213 (compr_passthr == PASSTHROUGH) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05306214 (out->is_iec61937_info_available == true)) {
6215 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
6216 ret = -EINVAL;
6217 goto exit;
6218 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05306219 }
6220 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306221
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006222 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02006223 (audio_extn_a2dp_source_is_suspended())) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006224 if (!(compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER) ||
6225 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Zhou Songd01e7a22020-09-23 22:49:01 +08006226 if (!is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306227 ret = -EIO;
6228 goto exit;
6229 }
6230 }
6231 }
6232
Weiyin Jiangabedea32020-12-09 12:49:19 +08006233 if (is_usb_out_device_type(&out->device_list) &&
6234 !audio_extn_usb_connected(NULL)) {
6235 ret = -EIO;
6236 goto exit;
6237 }
6238
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006239 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07006240 out->standby = false;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006241 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
6242
Eric Laurent150dbfe2013-02-27 14:31:02 -08006243 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006244 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
6245 ret = voice_extn_compress_voip_start_output_stream(out);
6246 else
6247 ret = start_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006248 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006249 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07006250 out->standby = true;
Weiyin Jiangac2bae82020-07-29 17:23:53 +08006251 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006252 goto exit;
6253 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306254 out->started = 1;
Andy Hunga1f48fa2019-07-01 18:14:53 -07006255 out->last_fifo_valid = false; // we're coming out of standby, last_fifo isn't valid.
Weiyin Jiangac2bae82020-07-29 17:23:53 +08006256
6257 if ((last_known_cal_step != -1) && (adev->platform != NULL)) {
vivek mehtab72d08d2016-04-29 03:16:47 -07006258 ALOGD("%s: retry previous failed cal level set", __func__);
Weiyin Jiangac2bae82020-07-29 17:23:53 +08006259 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05306260 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07006261 }
Weiyin Jiangac2bae82020-07-29 17:23:53 +08006262 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306263
6264 if ((out->is_iec61937_info_available == true) &&
6265 (audio_extn_passthru_is_passthrough_stream(out))&&
6266 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
6267 ret = -EINVAL;
6268 goto exit;
6269 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05306270 if (out->set_dual_mono)
6271 audio_extn_send_dual_mono_mixing_coefficients(out);
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006272
Dechen Chai22768452021-07-30 09:29:16 +05306273#ifndef LINUX_ENABLED
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006274 // log startup time in ms.
6275 simple_stats_log(
6276 &out->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Dechen Chai22768452021-07-30 09:29:16 +05306277#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006278 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006279
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006280 if (adev->is_channel_status_set == false &&
6281 compare_device_type(&out->device_list,
6282 AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Alexy Josephb1379942016-01-29 15:49:38 -08006283 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05306284 adev->is_channel_status_set = true;
6285 }
6286
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05306287 if ((adev->use_old_pspd_mix_ctrl == true) &&
6288 (out->pspd_coeff_sent == false)) {
6289 /*
6290 * Need to resend pspd coefficients after stream started for
6291 * older kernel version as it does not save the coefficients
6292 * and also stream has to be started for coeff to apply.
6293 */
6294 usecase = get_usecase_from_list(adev, out->usecase);
6295 if (usecase != NULL) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05306296 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05306297 out->pspd_coeff_sent = true;
6298 }
6299 }
6300
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006301 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08006302 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006303 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006304 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006305 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
6306 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05306307 if (out->send_next_track_params && out->is_compr_metadata_avail) {
6308 ALOGD("copl(%p):send next track params in gapless", out);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08006309 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05306310 out->send_next_track_params = false;
6311 out->is_compr_metadata_avail = false;
6312 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006313 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05306314 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306315 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006316
Ashish Jain83a6cc22016-06-28 14:34:17 +05306317 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05306318 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05306319 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05306320 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006321 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05306322 return -EINVAL;
6323 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05306324 audio_format_t dst_format = out->hal_op_format;
6325 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306326
Dieter Luecking5d57def2018-09-07 14:23:37 +02006327 /* prevent division-by-zero */
6328 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
6329 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
6330 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
6331 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05306332 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006333 ATRACE_END();
6334 return -EINVAL;
6335 }
6336
Ashish Jainf1eaa582016-05-23 20:54:24 +05306337 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
6338 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
6339
Ashish Jain83a6cc22016-06-28 14:34:17 +05306340 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05306341 dst_format,
6342 buffer,
6343 src_format,
6344 frames);
6345
Ashish Jain83a6cc22016-06-28 14:34:17 +05306346 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05306347 bytes_to_write);
6348
6349 /*Convert written bytes in audio flinger format*/
6350 if (ret > 0)
6351 ret = ((ret * format_to_bitwidth_table[out->format]) /
6352 format_to_bitwidth_table[dst_format]);
6353 }
6354 } else
6355 ret = compress_write(out->compr, buffer, bytes);
6356
Zhou Songc9672822017-08-16 16:01:39 +08006357 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
6358 update_frames_written(out, bytes);
6359
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306360 if (ret < 0)
6361 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08006362 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05306363 /*msg to cb thread only if non blocking write is enabled*/
6364 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05306365 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006366 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05306367 } else if (-ENETRESET == ret) {
6368 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306369 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05306370 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05306371 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006372 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05306373 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006374 }
Ashish Jain5106d362016-05-11 19:23:33 +05306375
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05306376 /* Call compr start only when non-zero bytes of data is there to be rendered */
6377 if (!out->playback_started && ret > 0) {
6378 int status = compress_start(out->compr);
6379 if (status < 0) {
6380 ret = status;
6381 ALOGE("%s: compr start failed with err %d", __func__, errno);
6382 goto exit;
6383 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07006384 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006385 out->playback_started = 1;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006386 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006387 out->offload_state = OFFLOAD_STATE_PLAYING;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006388 pthread_mutex_unlock(&out->latch_lock);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006389
6390 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6391 popcount(out->channel_mask),
6392 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006393 }
6394 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006395 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006396 return ret;
6397 } else {
6398 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006399 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006400 if (out->muted)
6401 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006402 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
6403 __func__, frames, frame_size, bytes_to_write);
6404
Aalique Grahame22e49102018-12-18 14:23:57 -08006405 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07006406 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
6407 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
6408 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006409 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
6410 int16_t *src = (int16_t *)buffer;
6411 int16_t *dst = (int16_t *)buffer;
6412
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006413 LOG_ALWAYS_FATAL_IF(channel_count > 2 ||
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006414 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08006415 "out_write called for %s use case with wrong properties",
6416 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006417
6418 /*
6419 * FIXME: this can be removed once audio flinger mixer supports
6420 * mono output
6421 */
6422
6423 /*
6424 * Code below goes over each frame in the buffer and adds both
6425 * L and R samples and then divides by 2 to convert to mono
6426 */
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006427 if (channel_count == 2) {
6428 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
6429 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
6430 }
6431 bytes_to_write /= 2;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006432 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006433 }
Andy Hunga1f48fa2019-07-01 18:14:53 -07006434
6435 // Note: since out_get_presentation_position() is called alternating with out_write()
6436 // by AudioFlinger, we can check underruns using the prior timestamp read.
6437 // (Alternately we could check if the buffer is empty using pcm_get_htimestamp().
6438 if (out->last_fifo_valid) {
6439 // compute drain to see if there is an underrun.
6440 const int64_t current_ns = systemTime(SYSTEM_TIME_MONOTONIC); // sys call
Dhananjay Kumara4429632020-07-11 02:53:37 +05306441 int64_t time_diff_ns = current_ns - out->last_fifo_time_ns;
6442 int64_t frames_by_time =
6443 ((time_diff_ns > 0) && (time_diff_ns < (INT64_MAX / out->config.rate))) ?
6444 (time_diff_ns * out->config.rate / NANOS_PER_SECOND) : 0;
Andy Hunga1f48fa2019-07-01 18:14:53 -07006445 const int64_t underrun = frames_by_time - out->last_fifo_frames_remaining;
6446
6447 if (underrun > 0) {
Dechen Chai22768452021-07-30 09:29:16 +05306448#ifndef LINUX_ENABLED
Andy Hunga1f48fa2019-07-01 18:14:53 -07006449 simple_stats_log(&out->fifo_underruns, underrun);
Dechen Chai22768452021-07-30 09:29:16 +05306450#endif
Andy Hunga1f48fa2019-07-01 18:14:53 -07006451
6452 ALOGW("%s: underrun(%lld) "
6453 "frames_by_time(%lld) > out->last_fifo_frames_remaining(%lld)",
6454 __func__,
6455 (long long)out->fifo_underruns.n,
6456 (long long)frames_by_time,
6457 (long long)out->last_fifo_frames_remaining);
6458 }
6459 out->last_fifo_valid = false; // we're writing below, mark fifo info as stale.
6460 }
6461
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306462 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006463
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006464 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006465
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006466 if (out->config.rate)
6467 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
6468 out->config.rate;
6469
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006470 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006471 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
6472
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006473 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006474 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006475 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306476 out->convert_buffer != NULL) {
6477
6478 memcpy_by_audio_format(out->convert_buffer,
6479 out->hal_op_format,
6480 buffer,
6481 out->hal_ip_format,
6482 out->config.period_size * out->config.channels);
6483
6484 ret = pcm_write(out->pcm, out->convert_buffer,
6485 (out->config.period_size *
6486 out->config.channels *
6487 format_to_bitwidth_table[out->hal_op_format]));
6488 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05306489 /*
6490 * To avoid underrun in DSP when the application is not pumping
6491 * data at required rate, check for the no. of bytes and ignore
6492 * pcm_write if it is less than actual buffer size.
6493 * It is a work around to a change in compress VOIP driver.
6494 */
6495 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
6496 bytes < (out->config.period_size * out->config.channels *
6497 audio_bytes_per_sample(out->format))) {
6498 size_t voip_buf_size =
6499 out->config.period_size * out->config.channels *
6500 audio_bytes_per_sample(out->format);
6501 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
6502 __func__, bytes, voip_buf_size);
6503 usleep(((uint64_t)voip_buf_size - bytes) *
6504 1000000 / audio_stream_out_frame_size(stream) /
6505 out_get_sample_rate(&out->stream.common));
6506 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006507 } else {
6508 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
6509 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
6510 else
6511 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
6512 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306513 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006514
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006515 release_out_focus(out);
6516
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306517 if (ret < 0)
6518 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08006519 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05306520 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006521 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006522 }
6523
6524exit:
Zhou Songc9672822017-08-16 16:01:39 +08006525 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306526 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306527 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306528 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006529 pthread_mutex_unlock(&out->lock);
6530
6531 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006532 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08006533 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306534 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306535 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306536 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306537 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306538 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306539 out->standby = true;
6540 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306541 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006542 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
6543 /* prevent division-by-zero */
6544 uint32_t stream_size = audio_stream_out_frame_size(stream);
6545 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006546
Dieter Luecking5d57def2018-09-07 14:23:37 +02006547 if ((stream_size == 0) || (srate == 0)) {
6548 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
6549 ATRACE_END();
6550 return -EINVAL;
6551 }
6552 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
6553 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006554 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05306555 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006556 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006557 return ret;
6558 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006559 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07006560 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006561 return bytes;
6562}
6563
6564static int out_get_render_position(const struct audio_stream_out *stream,
6565 uint32_t *dsp_frames)
6566{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006567 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08006568
6569 if (dsp_frames == NULL)
6570 return -EINVAL;
6571
6572 *dsp_frames = 0;
6573 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08006574 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05306575
6576 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
6577 * this operation and adev_close_output_stream(where out gets reset).
6578 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05306579 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006580 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05306581 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006582 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05306583 return 0;
6584 }
6585
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006586 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05306587 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306588 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006589 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306590 if (ret < 0)
6591 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006592 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05306593 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006594 }
Naresh Tanniru80659832014-06-04 18:17:56 +05306595 if (-ENETRESET == ret) {
6596 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306597 out->card_status = CARD_STATUS_OFFLINE;
6598 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306599 } else if(ret < 0) {
6600 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306601 ret = -EINVAL;
6602 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05306603 /*
6604 * Handle corner case where compress session is closed during SSR
6605 * and timestamp is queried
6606 */
6607 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306608 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306609 } else if (out->prev_card_status_offline) {
6610 ALOGE("ERROR: previously sound card was offline,return error");
6611 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306612 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306613 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006614 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05306615 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306616 pthread_mutex_unlock(&out->lock);
6617 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08006618 } else if (audio_is_linear_pcm(out->format)) {
6619 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006620 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08006621 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006622 } else
6623 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006624}
6625
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006626static int out_add_audio_effect(const struct audio_stream *stream __unused,
6627 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006628{
6629 return 0;
6630}
6631
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006632static int out_remove_audio_effect(const struct audio_stream *stream __unused,
6633 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006634{
6635 return 0;
6636}
6637
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006638static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
6639 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006640{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05306641 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006642}
6643
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006644static int out_get_presentation_position(const struct audio_stream_out *stream,
6645 uint64_t *frames, struct timespec *timestamp)
6646{
6647 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05306648 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07006649 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006650
Ashish Jain5106d362016-05-11 19:23:33 +05306651 /* below piece of code is not guarded against any lock because audioFliner serializes
6652 * this operation and adev_close_output_stream( where out gets reset).
6653 */
6654 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05306655 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006656 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05306657 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
6658 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
6659 return 0;
6660 }
6661
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006662 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006663
Ashish Jain5106d362016-05-11 19:23:33 +05306664 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
6665 ret = compress_get_tstamp(out->compr, &dsp_frames,
6666 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08006667 // Adjustment accounts for A2dp encoder latency with offload usecases
6668 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006669 if (is_a2dp_out_device_type(&out->device_list)) {
yidongh0515e042017-07-06 15:00:34 +08006670 unsigned long offset =
6671 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
6672 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
6673 }
Ashish Jain5106d362016-05-11 19:23:33 +05306674 ALOGVV("%s rendered frames %ld sample_rate %d",
6675 __func__, dsp_frames, out->sample_rate);
6676 *frames = dsp_frames;
6677 if (ret < 0)
6678 ret = -errno;
6679 if (-ENETRESET == ret) {
6680 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306681 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05306682 ret = -EINVAL;
6683 } else
6684 ret = 0;
6685 /* this is the best we can do */
6686 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07006687 } else {
6688 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08006689 unsigned int avail;
6690 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
George Gao62ebc722019-07-29 16:29:44 -07006691 uint64_t signed_frames = 0;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006692 uint64_t frames_temp = 0;
George Gao62ebc722019-07-29 16:29:44 -07006693
Andy Hunga1f48fa2019-07-01 18:14:53 -07006694 if (out->kernel_buffer_size > avail) {
6695 frames_temp = out->last_fifo_frames_remaining = out->kernel_buffer_size - avail;
6696 } else {
6697 ALOGW("%s: avail:%u > kernel_buffer_size:%zu clamping!",
6698 __func__, avail, out->kernel_buffer_size);
6699 avail = out->kernel_buffer_size;
6700 frames_temp = out->last_fifo_frames_remaining = 0;
6701 }
6702 out->last_fifo_valid = true;
6703 out->last_fifo_time_ns = audio_utils_ns_from_timespec(timestamp);
6704
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006705 if (out->written >= frames_temp)
6706 signed_frames = out->written - frames_temp;
George Gao62ebc722019-07-29 16:29:44 -07006707
Andy Hunga1f48fa2019-07-01 18:14:53 -07006708 ALOGVV("%s: frames:%lld avail:%u kernel_buffer_size:%zu",
6709 __func__, (long long)signed_frames, avail, out->kernel_buffer_size);
6710
Weiyin Jiangd4633762018-03-16 12:05:03 +08006711 // This adjustment accounts for buffering after app processor.
6712 // It is based on estimated DSP latency per use case, rather than exact.
George Gao9ba8a142020-07-23 14:30:03 -07006713 frames_temp = platform_render_latency(out) *
Robert Lee58215542019-07-15 20:55:12 +08006714 out->sample_rate / 1000000LL;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006715 if (signed_frames >= frames_temp)
6716 signed_frames -= frames_temp;
Aniket Kumar Lataff613152017-07-18 18:19:21 -07006717
Weiyin Jiangd4633762018-03-16 12:05:03 +08006718 // Adjustment accounts for A2dp encoder latency with non offload usecases
6719 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006720 if (is_a2dp_out_device_type(&out->device_list)) {
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006721 frames_temp = audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000;
6722 if (signed_frames >= frames_temp)
6723 signed_frames -= frames_temp;
Weiyin Jiangd4633762018-03-16 12:05:03 +08006724 }
6725
6726 // It would be unusual for this value to be negative, but check just in case ...
George Gao62ebc722019-07-29 16:29:44 -07006727 *frames = signed_frames;
6728 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006729 }
Eric Laurenta7a33042019-07-10 16:20:22 -07006730 } else if (out->card_status == CARD_STATUS_OFFLINE ||
6731 // audioflinger still needs position updates when A2DP is suspended
Jasmine Cha5c2517f2019-09-09 11:07:28 +08006732 (is_a2dp_out_device_type(&out->device_list) && audio_extn_a2dp_source_is_suspended())) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306733 *frames = out->written;
6734 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306735 if (is_offload_usecase(out->usecase))
6736 ret = -EINVAL;
6737 else
6738 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006739 }
6740 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006741 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006742 return ret;
6743}
6744
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006745static int out_set_callback(struct audio_stream_out *stream,
6746 stream_callback_t callback, void *cookie)
6747{
6748 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006749 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006750
6751 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006752 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006753 out->client_callback = callback;
6754 out->client_cookie = cookie;
6755 if (out->adsp_hdlr_stream_handle) {
6756 ret = audio_extn_adsp_hdlr_stream_set_callback(
6757 out->adsp_hdlr_stream_handle,
6758 callback,
6759 cookie);
6760 if (ret)
6761 ALOGW("%s:adsp hdlr callback registration failed %d",
6762 __func__, ret);
6763 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006764 pthread_mutex_unlock(&out->lock);
6765 return 0;
6766}
6767
6768static int out_pause(struct audio_stream_out* stream)
6769{
6770 struct stream_out *out = (struct stream_out *)stream;
6771 int status = -ENOSYS;
6772 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006773 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006774 ALOGD("copl(%p):pause compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306775 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006776 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006777 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006778 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306779 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05306780 status = compress_pause(out->compr);
6781
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006782 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006783
Mingming Yin21854652016-04-13 11:54:02 -07006784 if (audio_extn_passthru_is_active()) {
6785 ALOGV("offload use case, pause passthru");
6786 audio_extn_passthru_on_pause(out);
6787 }
6788
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306789 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006790 audio_extn_dts_notify_playback_state(out->usecase, 0,
6791 out->sample_rate, popcount(out->channel_mask),
6792 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006793 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08006794 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006795 pthread_mutex_unlock(&out->lock);
6796 }
6797 return status;
6798}
6799
6800static int out_resume(struct audio_stream_out* stream)
6801{
6802 struct stream_out *out = (struct stream_out *)stream;
6803 int status = -ENOSYS;
6804 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006805 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006806 ALOGD("copl(%p):resume compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306807 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006808 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006809 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006810 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306811 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306812 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07006813 }
6814 if (!status) {
6815 out->offload_state = OFFLOAD_STATE_PLAYING;
6816 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306817 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006818 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6819 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006820 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08006821 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006822 pthread_mutex_unlock(&out->lock);
6823 }
6824 return status;
6825}
6826
6827static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
6828{
6829 struct stream_out *out = (struct stream_out *)stream;
6830 int status = -ENOSYS;
6831 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006832 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006833 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006834 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
6835 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
6836 else
6837 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
6838 pthread_mutex_unlock(&out->lock);
6839 }
6840 return status;
6841}
6842
6843static int out_flush(struct audio_stream_out* stream)
6844{
6845 struct stream_out *out = (struct stream_out *)stream;
6846 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006847 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006848 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006849 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006850 pthread_mutex_lock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006851 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
Gautam Manam14c198b2020-12-24 14:08:04 +05306852 pthread_mutex_unlock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006853 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006854 } else {
6855 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
Gautam Manam14c198b2020-12-24 14:08:04 +05306856 pthread_mutex_unlock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006857 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08006858 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006859 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006860 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006861 return 0;
6862 }
6863 return -ENOSYS;
6864}
6865
Haynes Mathew George16081042017-05-31 17:16:49 -07006866static int out_stop(const struct audio_stream_out* stream)
6867{
6868 struct stream_out *out = (struct stream_out *)stream;
6869 struct audio_device *adev = out->dev;
6870 int ret = -ENOSYS;
6871
6872 ALOGV("%s", __func__);
6873 pthread_mutex_lock(&adev->lock);
6874 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6875 out->playback_started && out->pcm != NULL) {
6876 pcm_stop(out->pcm);
6877 ret = stop_output_stream(out);
6878 out->playback_started = false;
6879 }
6880 pthread_mutex_unlock(&adev->lock);
6881 return ret;
6882}
6883
6884static int out_start(const struct audio_stream_out* stream)
6885{
6886 struct stream_out *out = (struct stream_out *)stream;
6887 struct audio_device *adev = out->dev;
6888 int ret = -ENOSYS;
6889
6890 ALOGV("%s", __func__);
6891 pthread_mutex_lock(&adev->lock);
6892 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6893 !out->playback_started && out->pcm != NULL) {
6894 ret = start_output_stream(out);
6895 if (ret == 0) {
6896 out->playback_started = true;
6897 }
6898 }
6899 pthread_mutex_unlock(&adev->lock);
6900 return ret;
6901}
6902
6903/*
6904 * Modify config->period_count based on min_size_frames
6905 */
6906static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
6907{
6908 int periodCountRequested = (min_size_frames + config->period_size - 1)
6909 / config->period_size;
6910 int periodCount = MMAP_PERIOD_COUNT_MIN;
6911
6912 ALOGV("%s original config.period_size = %d config.period_count = %d",
6913 __func__, config->period_size, config->period_count);
6914
6915 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
6916 periodCount *= 2;
6917 }
6918 config->period_count = periodCount;
6919
6920 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
6921}
6922
Phil Burkfe17efd2019-03-25 10:23:35 -07006923// Read offset for the positional timestamp from a persistent vendor property.
6924// This is to workaround apparent inaccuracies in the timing information that
6925// is used by the AAudio timing model. The inaccuracies can cause glitches.
6926static int64_t get_mmap_out_time_offset() {
6927 const int32_t kDefaultOffsetMicros = 0;
6928 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006929 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07006930 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
6931 return mmap_time_offset_micros * (int64_t)1000;
6932}
6933
Haynes Mathew George16081042017-05-31 17:16:49 -07006934static int out_create_mmap_buffer(const struct audio_stream_out *stream,
6935 int32_t min_size_frames,
6936 struct audio_mmap_buffer_info *info)
6937{
6938 struct stream_out *out = (struct stream_out *)stream;
6939 struct audio_device *adev = out->dev;
6940 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07006941 unsigned int offset1 = 0;
6942 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006943 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006944 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006945 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07006946
Arun Mirpuri5d170872019-03-26 13:21:31 -07006947 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306948 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07006949 pthread_mutex_lock(&adev->lock);
6950
Sharad Sanglec6f32552018-05-04 16:15:38 +05306951 if (CARD_STATUS_OFFLINE == out->card_status ||
6952 CARD_STATUS_OFFLINE == adev->card_status) {
6953 ALOGW("out->card_status or adev->card_status offline, try again");
6954 ret = -EIO;
6955 goto exit;
6956 }
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306957 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07006958 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
6959 ret = -EINVAL;
6960 goto exit;
6961 }
6962 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
6963 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
6964 ret = -ENOSYS;
6965 goto exit;
6966 }
6967 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
6968 if (out->pcm_device_id < 0) {
6969 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6970 __func__, out->pcm_device_id, out->usecase);
6971 ret = -EINVAL;
6972 goto exit;
6973 }
6974
6975 adjust_mmap_period_count(&out->config, min_size_frames);
6976
Arun Mirpuri5d170872019-03-26 13:21:31 -07006977 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006978 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
6979 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
6980 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306981 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306982 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6983 out->card_status = CARD_STATUS_OFFLINE;
6984 adev->card_status = CARD_STATUS_OFFLINE;
6985 ret = -EIO;
6986 goto exit;
6987 }
6988
Haynes Mathew George16081042017-05-31 17:16:49 -07006989 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
6990 step = "open";
6991 ret = -ENODEV;
6992 goto exit;
6993 }
6994 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
6995 if (ret < 0) {
6996 step = "begin";
6997 goto exit;
6998 }
juyuchen626833d2019-06-04 16:48:02 +08006999
7000 info->flags = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007001 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07007002 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07007003 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07007004 ret = platform_get_mmap_data_fd(adev->platform,
7005 out->pcm_device_id, 0 /*playback*/,
7006 &info->shared_memory_fd,
7007 &mmap_size);
7008 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07007009 // Fall back to non exclusive mode
7010 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
7011 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07007012 out->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
7013 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, out->mmap_shared_memory_fd);
7014
Arun Mirpuri5d170872019-03-26 13:21:31 -07007015 if (mmap_size < buffer_size) {
7016 step = "mmap";
7017 goto exit;
7018 }
juyuchen626833d2019-06-04 16:48:02 +08007019 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07007020 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007021 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07007022 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07007023
7024 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
7025 if (ret < 0) {
7026 step = "commit";
7027 goto exit;
7028 }
7029
Phil Burkfe17efd2019-03-25 10:23:35 -07007030 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
7031
Haynes Mathew George16081042017-05-31 17:16:49 -07007032 out->standby = false;
7033 ret = 0;
7034
Arun Mirpuri5d170872019-03-26 13:21:31 -07007035 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07007036 __func__, info->shared_memory_address, info->buffer_size_frames);
7037
7038exit:
7039 if (ret != 0) {
7040 if (out->pcm == NULL) {
7041 ALOGE("%s: %s - %d", __func__, step, ret);
7042 } else {
7043 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
7044 pcm_close(out->pcm);
7045 out->pcm = NULL;
7046 }
7047 }
7048 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05307049 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07007050 return ret;
7051}
7052
7053static int out_get_mmap_position(const struct audio_stream_out *stream,
7054 struct audio_mmap_position *position)
7055{
7056 struct stream_out *out = (struct stream_out *)stream;
7057 ALOGVV("%s", __func__);
7058 if (position == NULL) {
7059 return -EINVAL;
7060 }
7061 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08007062 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07007063 return -ENOSYS;
7064 }
7065 if (out->pcm == NULL) {
7066 return -ENOSYS;
7067 }
7068
7069 struct timespec ts = { 0, 0 };
7070 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
7071 if (ret < 0) {
7072 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
7073 return ret;
7074 }
Phil Burkfe17efd2019-03-25 10:23:35 -07007075 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7076 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07007077 return 0;
7078}
7079
7080
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007081/** audio_stream_in implementation **/
7082static uint32_t in_get_sample_rate(const struct audio_stream *stream)
7083{
7084 struct stream_in *in = (struct stream_in *)stream;
7085
7086 return in->config.rate;
7087}
7088
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007089static int in_set_sample_rate(struct audio_stream *stream __unused,
7090 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007091{
7092 return -ENOSYS;
7093}
7094
7095static size_t in_get_buffer_size(const struct audio_stream *stream)
7096{
7097 struct stream_in *in = (struct stream_in *)stream;
7098
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007099 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
7100 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07007101 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
7102 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307103 else if(audio_extn_cin_attached_usecase(in))
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307104 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007105
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007106 return in->config.period_size * in->af_period_multiplier *
7107 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007108}
7109
7110static uint32_t in_get_channels(const struct audio_stream *stream)
7111{
7112 struct stream_in *in = (struct stream_in *)stream;
7113
7114 return in->channel_mask;
7115}
7116
7117static audio_format_t in_get_format(const struct audio_stream *stream)
7118{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007119 struct stream_in *in = (struct stream_in *)stream;
7120
7121 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007122}
7123
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007124static int in_set_format(struct audio_stream *stream __unused,
7125 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007126{
7127 return -ENOSYS;
7128}
7129
7130static int in_standby(struct audio_stream *stream)
7131{
7132 struct stream_in *in = (struct stream_in *)stream;
7133 struct audio_device *adev = in->dev;
7134 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307135 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
7136 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07007137 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307138
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007139 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007140 if (!in->standby && in->is_st_session) {
7141 ALOGD("%s: sound trigger pcm stop lab", __func__);
7142 audio_extn_sound_trigger_stop_lab(in);
George Gao3018ede2019-10-23 13:23:00 -07007143 if (adev->num_va_sessions > 0)
7144 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007145 in->standby = 1;
7146 }
7147
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007148 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007149 if (adev->adm_deregister_stream)
7150 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
7151
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08007152 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007153 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08007154 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08007155 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08007156 voice_extn_compress_voip_close_input_stream(stream);
7157 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07007158 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
7159 do_stop = in->capture_started;
7160 in->capture_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07007161 if (in->mmap_shared_memory_fd >= 0) {
7162 ALOGV("%s: closing mmap_shared_memory_fd = %d",
7163 __func__, in->mmap_shared_memory_fd);
7164 close(in->mmap_shared_memory_fd);
7165 in->mmap_shared_memory_fd = -1;
7166 }
Zhou Songa8895042016-07-05 17:54:22 +08007167 } else {
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307168 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05307169 audio_extn_cin_close_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08007170 }
7171
Arun Mirpuri5d170872019-03-26 13:21:31 -07007172 if (in->pcm) {
7173 ATRACE_BEGIN("pcm_in_close");
7174 pcm_close(in->pcm);
7175 ATRACE_END();
7176 in->pcm = NULL;
7177 }
7178
Carter Hsu2e429db2019-05-14 18:50:52 +08007179 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08007180 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08007181
George Gao3018ede2019-10-23 13:23:00 -07007182 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
7183 if (adev->num_va_sessions > 0)
7184 adev->num_va_sessions--;
7185 }
Quinn Malef6050362019-01-30 15:55:40 -08007186
Eric Laurent150dbfe2013-02-27 14:31:02 -08007187 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007188 }
7189 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07007190 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007191 return status;
7192}
7193
Aalique Grahame22e49102018-12-18 14:23:57 -08007194static int in_dump(const struct audio_stream *stream,
7195 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007196{
Aalique Grahame22e49102018-12-18 14:23:57 -08007197 struct stream_in *in = (struct stream_in *)stream;
7198
7199 // We try to get the lock for consistency,
7200 // but it isn't necessary for these variables.
7201 // If we're not in standby, we may be blocked on a read.
7202 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
7203 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
7204 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
7205 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
Dechen Chai22768452021-07-30 09:29:16 +05307206#ifndef LINUX_ENABLED
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007207 char buffer[256]; // for statistics formatting
7208 if (in->start_latency_ms.n > 0) {
7209 simple_stats_to_string(&in->start_latency_ms, buffer, sizeof(buffer));
7210 dprintf(fd, " Start latency ms: %s\n", buffer);
7211 }
Dechen Chai22768452021-07-30 09:29:16 +05307212#endif
Aalique Grahame22e49102018-12-18 14:23:57 -08007213 if (locked) {
7214 pthread_mutex_unlock(&in->lock);
7215 }
Dechen Chai22768452021-07-30 09:29:16 +05307216#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -08007217 // dump error info
7218 (void)error_log_dump(
7219 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Dechen Chai22768452021-07-30 09:29:16 +05307220#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007221 return 0;
7222}
7223
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307224static void in_snd_mon_cb(void * stream, struct str_parms * parms)
7225{
7226 if (!stream || !parms)
7227 return;
7228
7229 struct stream_in *in = (struct stream_in *)stream;
7230 struct audio_device *adev = in->dev;
7231
7232 card_status_t status;
7233 int card;
7234 if (parse_snd_card_status(parms, &card, &status) < 0)
7235 return;
7236
7237 pthread_mutex_lock(&adev->lock);
7238 bool valid_cb = (card == adev->snd_card);
7239 pthread_mutex_unlock(&adev->lock);
7240
7241 if (!valid_cb)
7242 return;
7243
7244 lock_input_stream(in);
7245 if (in->card_status != status)
7246 in->card_status = status;
7247 pthread_mutex_unlock(&in->lock);
7248
7249 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
7250 use_case_table[in->usecase],
7251 status == CARD_STATUS_OFFLINE ? "offline" : "online");
7252
7253 // a better solution would be to report error back to AF and let
7254 // it put the stream to standby
7255 if (status == CARD_STATUS_OFFLINE)
7256 in_standby(&in->stream.common);
7257
7258 return;
7259}
7260
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007261int route_input_stream(struct stream_in *in,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007262 struct listnode *devices,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007263 audio_source_t source)
7264{
7265 struct audio_device *adev = in->dev;
7266 int ret = 0;
7267
7268 lock_input_stream(in);
7269 pthread_mutex_lock(&adev->lock);
7270
7271 /* no audio source uses val == 0 */
7272 if ((in->source != source) && (source != AUDIO_SOURCE_DEFAULT)) {
7273 in->source = source;
7274 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
7275 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
7276 (voice_extn_compress_voip_is_format_supported(in->format)) &&
7277 (in->config.rate == 8000 || in->config.rate == 16000 ||
7278 in->config.rate == 32000 || in->config.rate == 48000 ) &&
7279 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
7280 ret = voice_extn_compress_voip_open_input_stream(in);
7281 if (ret != 0) {
7282 ALOGE("%s: Compress voip input cannot be opened, error:%d",
7283 __func__, ret);
7284 }
7285 }
7286 }
7287
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007288 if (!compare_devices(&in->device_list, devices) && !list_empty(devices) &&
7289 is_audio_in_device_type(devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007290 // Workaround: If routing to an non existing usb device, fail gracefully
7291 // The routing request will otherwise block during 10 second
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007292 struct str_parms *usb_addr =
7293 str_parms_create_str(get_usb_device_address(devices));
7294 if (is_usb_in_device_type(devices) && usb_addr &&
Weiyin Jiangabedea32020-12-09 12:49:19 +08007295 !audio_extn_usb_connected(NULL)) {
7296 ALOGW("%s: ignoring rerouting to non existing USB", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007297 ret = -ENOSYS;
7298 } else {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007299 /* If recording is in progress, change the tx device to new device */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007300 assign_devices(&in->device_list, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007301 if (!in->standby && !in->is_st_session) {
7302 ALOGV("update input routing change");
7303 // inform adm before actual routing to prevent glitches.
7304 if (adev->adm_on_routing_change) {
7305 adev->adm_on_routing_change(adev->adm_data,
7306 in->capture_handle);
7307 ret = select_devices(adev, in->usecase);
7308 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7309 adev->adm_routing_changed = true;
7310 }
7311 }
7312 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007313 if (usb_addr)
7314 str_parms_destroy(usb_addr);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007315 }
7316 pthread_mutex_unlock(&adev->lock);
7317 pthread_mutex_unlock(&in->lock);
7318
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07007319 ALOGV("%s: exit: status(%d)", __func__, ret);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007320 return ret;
7321}
7322
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007323static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
7324{
7325 struct stream_in *in = (struct stream_in *)stream;
7326 struct audio_device *adev = in->dev;
7327 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007328 char value[32];
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307329 int err = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007330
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307331 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007332 parms = str_parms_create_str(kvpairs);
7333
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307334 if (!parms)
7335 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007336 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08007337 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007338
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307339 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
7340 if (err >= 0) {
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307341 strlcpy(in->profile, value, sizeof(in->profile));
7342 ALOGV("updating stream profile with value '%s'", in->profile);
7343 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
7344 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007345 &in->device_list, in->flags, in->format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307346 in->sample_rate, in->bit_width,
7347 in->profile, &in->app_type_cfg);
7348 }
7349
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007350 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08007351 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007352
7353 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307354error:
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307355 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007356}
7357
7358static char* in_get_parameters(const struct audio_stream *stream,
7359 const char *keys)
7360{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007361 struct stream_in *in = (struct stream_in *)stream;
7362 struct str_parms *query = str_parms_create_str(keys);
7363 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007364 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007365
7366 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08007367 if (reply) {
7368 str_parms_destroy(reply);
7369 }
7370 if (query) {
7371 str_parms_destroy(query);
7372 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007373 ALOGE("in_get_parameters: failed to create query or reply");
7374 return NULL;
7375 }
7376
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007377 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007378
7379 voice_extn_in_get_parameters(in, query, reply);
7380
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007381 stream_get_parameter_channels(query, reply,
7382 &in->supported_channel_masks[0]);
7383 stream_get_parameter_formats(query, reply,
7384 &in->supported_formats[0]);
7385 stream_get_parameter_rates(query, reply,
7386 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007387 str = str_parms_to_str(reply);
7388 str_parms_destroy(query);
7389 str_parms_destroy(reply);
7390
7391 ALOGV("%s: exit: returns - %s", __func__, str);
7392 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007393}
7394
Aalique Grahame22e49102018-12-18 14:23:57 -08007395static int in_set_gain(struct audio_stream_in *stream,
7396 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007397{
Aalique Grahame22e49102018-12-18 14:23:57 -08007398 struct stream_in *in = (struct stream_in *)stream;
7399 char mixer_ctl_name[128];
7400 struct mixer_ctl *ctl;
7401 int ctl_value;
7402
7403 ALOGV("%s: gain %f", __func__, gain);
7404
7405 if (stream == NULL)
7406 return -EINVAL;
7407
7408 /* in_set_gain() only used to silence MMAP capture for now */
7409 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
7410 return -ENOSYS;
7411
7412 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
7413
7414 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
7415 if (!ctl) {
7416 ALOGW("%s: Could not get ctl for mixer cmd - %s",
7417 __func__, mixer_ctl_name);
7418 return -ENOSYS;
7419 }
7420
7421 if (gain < RECORD_GAIN_MIN)
7422 gain = RECORD_GAIN_MIN;
7423 else if (gain > RECORD_GAIN_MAX)
7424 gain = RECORD_GAIN_MAX;
7425 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
7426
7427 mixer_ctl_set_value(ctl, 0, ctl_value);
7428
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007429 return 0;
7430}
7431
7432static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
7433 size_t bytes)
7434{
7435 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05307436
7437 if (in == NULL) {
7438 ALOGE("%s: stream_in ptr is NULL", __func__);
7439 return -EINVAL;
7440 }
7441
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007442 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05307443 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307444 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007445
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007446 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05307447
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007448 if (in->is_st_session) {
7449 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
7450 /* Read from sound trigger HAL */
7451 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08007452 if (in->standby) {
George Gao3018ede2019-10-23 13:23:00 -07007453 if (adev->num_va_sessions < UINT_MAX)
7454 adev->num_va_sessions++;
Quinn Malef6050362019-01-30 15:55:40 -08007455 in->standby = 0;
7456 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007457 pthread_mutex_unlock(&in->lock);
7458 return bytes;
7459 }
7460
Haynes Mathew George16081042017-05-31 17:16:49 -07007461 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
7462 ret = -ENOSYS;
7463 goto exit;
7464 }
7465
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007466 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
7467 !in->standby && adev->adm_routing_changed) {
7468 ret = -ENOSYS;
7469 goto exit;
7470 }
7471
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007472 if (in->standby) {
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007473 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
7474
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007475 pthread_mutex_lock(&adev->lock);
7476 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
7477 ret = voice_extn_compress_voip_start_input_stream(in);
7478 else
7479 ret = start_input_stream(in);
George Gao3018ede2019-10-23 13:23:00 -07007480 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
7481 if (adev->num_va_sessions < UINT_MAX)
7482 adev->num_va_sessions++;
7483 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007484 pthread_mutex_unlock(&adev->lock);
7485 if (ret != 0) {
7486 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007487 }
7488 in->standby = 0;
Dechen Chai22768452021-07-30 09:29:16 +05307489#ifndef LINUX_ENABLED
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007490 // log startup time in ms.
7491 simple_stats_log(
7492 &in->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Dechen Chai22768452021-07-30 09:29:16 +05307493#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007494 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007495
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05307496 /* Avoid read if capture_stopped is set */
7497 if (android_atomic_acquire_load(&(in->capture_stopped)) > 0) {
7498 ALOGD("%s: force stopped catpure session, ignoring read request", __func__);
7499 ret = -EINVAL;
7500 goto exit;
7501 }
7502
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007503 // what's the duration requested by the client?
7504 long ns = 0;
7505
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307506 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007507 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
7508 in->config.rate;
7509
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007510 ret = request_in_focus(in, ns);
7511 if (ret != 0)
7512 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007513 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007514
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307515 if (audio_extn_cin_attached_usecase(in)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307516 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
7517 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307518 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007519 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307520 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07007521 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007522 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007523 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07007524 } else if (audio_extn_ffv_get_stream() == in) {
7525 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307526 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007527 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307528 /* data from DSP comes in 24_8 format, convert it to 8_24 */
7529 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
7530 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
7531 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307532 ret = -EINVAL;
7533 goto exit;
7534 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307535 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307536 ret = -errno;
7537 }
7538 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307539 /* bytes read is always set to bytes for non compress usecases */
7540 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007541 }
7542
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007543 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007544
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007545 /*
Quinn Malef6050362019-01-30 15:55:40 -08007546 * Instead of writing zeroes here, we could trust the hardware to always
7547 * provide zeroes when muted. This is also muted with voice recognition
7548 * usecases so that other clients do not have access to voice recognition
7549 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007550 */
Quinn Malef6050362019-01-30 15:55:40 -08007551 if ((ret == 0 && voice_get_mic_mute(adev) &&
7552 !voice_is_in_call_rec_stream(in) &&
Zhou Song62ea0282020-03-22 19:53:01 +08007553 (in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY &&
7554 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY2)) ||
Quinn Malef6050362019-01-30 15:55:40 -08007555 (adev->num_va_sessions &&
7556 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
7557 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
7558 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007559 memset(buffer, 0, bytes);
7560
7561exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307562 frame_size = audio_stream_in_frame_size(stream);
7563 if (frame_size > 0)
7564 in->frames_read += bytes_read/frame_size;
7565
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007566 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307567 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007568 pthread_mutex_unlock(&in->lock);
7569
7570 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307571 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307572 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307573 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307574 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307575 in->standby = true;
7576 }
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307577 if (!audio_extn_cin_attached_usecase(in)) {
Sharad Sangled17c9122017-03-20 15:58:52 +05307578 bytes_read = bytes;
7579 memset(buffer, 0, bytes);
7580 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007581 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007582 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7583 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007584 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05307585 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05307586 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007587 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307588 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007589}
7590
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007591static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007592{
7593 return 0;
7594}
7595
Aalique Grahame22e49102018-12-18 14:23:57 -08007596static int in_get_capture_position(const struct audio_stream_in *stream,
7597 int64_t *frames, int64_t *time)
7598{
7599 if (stream == NULL || frames == NULL || time == NULL) {
7600 return -EINVAL;
7601 }
7602 struct stream_in *in = (struct stream_in *)stream;
7603 int ret = -ENOSYS;
7604
7605 lock_input_stream(in);
7606 // note: ST sessions do not close the alsa pcm driver synchronously
7607 // on standby. Therefore, we may return an error even though the
7608 // pcm stream is still opened.
7609 if (in->standby) {
7610 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
7611 "%s stream in standby but pcm not NULL for non ST session", __func__);
7612 goto exit;
7613 }
7614 if (in->pcm) {
7615 struct timespec timestamp;
7616 unsigned int avail;
7617 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
7618 *frames = in->frames_read + avail;
Robert Lee58215542019-07-15 20:55:12 +08007619 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec
George Gao9ba8a142020-07-23 14:30:03 -07007620 - platform_capture_latency(in) * 1000LL;
Kakanaboina Ramanjaneyulu8cedb092021-03-15 15:55:29 +05307621 //Adjustment accounts for A2dp decoder latency for recording usecase
7622 // Note: decoder latency is returned in ms, while platform_capture_latency in ns.
7623 if (is_a2dp_in_device_type(&in->device_list))
7624 *time -= audio_extn_a2dp_get_decoder_latency() * 1000000LL;
Aalique Grahame22e49102018-12-18 14:23:57 -08007625 ret = 0;
7626 }
7627 }
7628exit:
7629 pthread_mutex_unlock(&in->lock);
7630 return ret;
7631}
7632
Carter Hsu2e429db2019-05-14 18:50:52 +08007633static int in_update_effect_list(bool add, effect_handle_t effect,
7634 struct listnode *head)
7635{
7636 struct listnode *node;
7637 struct in_effect_list *elist = NULL;
7638 struct in_effect_list *target = NULL;
7639 int ret = 0;
7640
7641 if (!head)
7642 return ret;
7643
7644 list_for_each(node, head) {
7645 elist = node_to_item(node, struct in_effect_list, list);
7646 if (elist->handle == effect) {
7647 target = elist;
7648 break;
7649 }
7650 }
7651
7652 if (add) {
7653 if (target) {
7654 ALOGD("effect %p already exist", effect);
7655 return ret;
7656 }
7657
7658 target = (struct in_effect_list *)
7659 calloc(1, sizeof(struct in_effect_list));
7660
7661 if (!target) {
7662 ALOGE("%s:fail to allocate memory", __func__);
7663 return -ENOMEM;
7664 }
7665
7666 target->handle = effect;
7667 list_add_tail(head, &target->list);
7668 } else {
7669 if (target) {
7670 list_remove(&target->list);
7671 free(target);
7672 }
7673 }
7674
7675 return ret;
7676}
7677
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007678static int add_remove_audio_effect(const struct audio_stream *stream,
7679 effect_handle_t effect,
7680 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007681{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007682 struct stream_in *in = (struct stream_in *)stream;
7683 int status = 0;
7684 effect_descriptor_t desc;
7685
7686 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007687 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
7688
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007689 if (status != 0)
7690 return status;
7691
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007692 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007693 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08007694 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08007695 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
7696 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007697 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08007698
7699 in_update_effect_list(enable, effect, &in->aec_list);
7700 enable = !list_empty(&in->aec_list);
7701 if (enable == in->enable_aec)
7702 goto exit;
7703
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007704 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007705 ALOGD("AEC enable %d", enable);
7706
Aalique Grahame22e49102018-12-18 14:23:57 -08007707 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7708 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
7709 in->dev->enable_voicerx = enable;
7710 struct audio_usecase *usecase;
7711 struct listnode *node;
7712 list_for_each(node, &in->dev->usecase_list) {
7713 usecase = node_to_item(node, struct audio_usecase, list);
7714 if (usecase->type == PCM_PLAYBACK)
7715 select_devices(in->dev, usecase->id);
7716 }
7717 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007718 if (!in->standby) {
7719 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
7720 select_devices(in->dev, in->usecase);
7721 }
7722
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007723 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007724 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
7725
7726 in_update_effect_list(enable, effect, &in->ns_list);
7727 enable = !list_empty(&in->ns_list);
7728 if (enable == in->enable_ns)
7729 goto exit;
7730
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007731 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007732 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007733 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08007734 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Ramu Gottipatifa5be522021-12-28 19:18:21 +05307735 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
kunleizd96526c2018-04-09 11:12:32 +08007736 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007737 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
7738 select_devices(in->dev, in->usecase);
7739 } else
7740 select_devices(in->dev, in->usecase);
7741 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007742 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007743exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007744 pthread_mutex_unlock(&in->dev->lock);
7745 pthread_mutex_unlock(&in->lock);
7746
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007747 return 0;
7748}
7749
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007750static int in_add_audio_effect(const struct audio_stream *stream,
7751 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007752{
Eric Laurent994a6932013-07-17 11:51:42 -07007753 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007754 return add_remove_audio_effect(stream, effect, true);
7755}
7756
7757static int in_remove_audio_effect(const struct audio_stream *stream,
7758 effect_handle_t effect)
7759{
Eric Laurent994a6932013-07-17 11:51:42 -07007760 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007761 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007762}
7763
Haynes Mathew George16081042017-05-31 17:16:49 -07007764static int in_stop(const struct audio_stream_in* stream)
7765{
7766 struct stream_in *in = (struct stream_in *)stream;
7767 struct audio_device *adev = in->dev;
7768
7769 int ret = -ENOSYS;
7770 ALOGV("%s", __func__);
7771 pthread_mutex_lock(&adev->lock);
7772 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7773 in->capture_started && in->pcm != NULL) {
7774 pcm_stop(in->pcm);
7775 ret = stop_input_stream(in);
7776 in->capture_started = false;
7777 }
7778 pthread_mutex_unlock(&adev->lock);
7779 return ret;
7780}
7781
7782static int in_start(const struct audio_stream_in* stream)
7783{
7784 struct stream_in *in = (struct stream_in *)stream;
7785 struct audio_device *adev = in->dev;
7786 int ret = -ENOSYS;
7787
7788 ALOGV("%s in %p", __func__, in);
7789 pthread_mutex_lock(&adev->lock);
7790 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7791 !in->capture_started && in->pcm != NULL) {
7792 if (!in->capture_started) {
7793 ret = start_input_stream(in);
7794 if (ret == 0) {
7795 in->capture_started = true;
7796 }
7797 }
7798 }
7799 pthread_mutex_unlock(&adev->lock);
7800 return ret;
7801}
7802
Phil Burke0a86d12019-02-16 22:28:11 -08007803// Read offset for the positional timestamp from a persistent vendor property.
7804// This is to workaround apparent inaccuracies in the timing information that
7805// is used by the AAudio timing model. The inaccuracies can cause glitches.
7806static int64_t in_get_mmap_time_offset() {
7807 const int32_t kDefaultOffsetMicros = 0;
7808 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08007809 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08007810 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
7811 return mmap_time_offset_micros * (int64_t)1000;
7812}
7813
Haynes Mathew George16081042017-05-31 17:16:49 -07007814static int in_create_mmap_buffer(const struct audio_stream_in *stream,
7815 int32_t min_size_frames,
7816 struct audio_mmap_buffer_info *info)
7817{
7818 struct stream_in *in = (struct stream_in *)stream;
7819 struct audio_device *adev = in->dev;
7820 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07007821 unsigned int offset1 = 0;
7822 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007823 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07007824 uint32_t mmap_size = 0;
7825 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007826
7827 pthread_mutex_lock(&adev->lock);
7828 ALOGV("%s in %p", __func__, in);
7829
Sharad Sanglec6f32552018-05-04 16:15:38 +05307830 if (CARD_STATUS_OFFLINE == in->card_status||
7831 CARD_STATUS_OFFLINE == adev->card_status) {
7832 ALOGW("in->card_status or adev->card_status offline, try again");
7833 ret = -EIO;
7834 goto exit;
7835 }
7836
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307837 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07007838 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
7839 ret = -EINVAL;
7840 goto exit;
7841 }
7842 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
7843 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
7844 ALOGV("%s in %p", __func__, in);
7845 ret = -ENOSYS;
7846 goto exit;
7847 }
7848 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
7849 if (in->pcm_device_id < 0) {
7850 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
7851 __func__, in->pcm_device_id, in->usecase);
7852 ret = -EINVAL;
7853 goto exit;
7854 }
7855
7856 adjust_mmap_period_count(&in->config, min_size_frames);
7857
7858 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
7859 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
7860 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
7861 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307862 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307863 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7864 in->card_status = CARD_STATUS_OFFLINE;
7865 adev->card_status = CARD_STATUS_OFFLINE;
7866 ret = -EIO;
7867 goto exit;
7868 }
7869
Haynes Mathew George16081042017-05-31 17:16:49 -07007870 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
7871 step = "open";
7872 ret = -ENODEV;
7873 goto exit;
7874 }
7875
7876 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
7877 if (ret < 0) {
7878 step = "begin";
7879 goto exit;
7880 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007881
juyuchen626833d2019-06-04 16:48:02 +08007882 info->flags = 0;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007883 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
7884 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
7885 info->burst_size_frames = in->config.period_size;
7886 ret = platform_get_mmap_data_fd(adev->platform,
7887 in->pcm_device_id, 1 /*capture*/,
7888 &info->shared_memory_fd,
7889 &mmap_size);
7890 if (ret < 0) {
7891 // Fall back to non exclusive mode
7892 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
7893 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07007894 in->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
7895 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, in->mmap_shared_memory_fd);
7896
Arun Mirpuri5d170872019-03-26 13:21:31 -07007897 if (mmap_size < buffer_size) {
7898 step = "mmap";
7899 goto exit;
7900 }
juyuchen626833d2019-06-04 16:48:02 +08007901 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007902 }
7903
7904 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07007905
7906 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
7907 if (ret < 0) {
7908 step = "commit";
7909 goto exit;
7910 }
7911
Phil Burke0a86d12019-02-16 22:28:11 -08007912 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
7913
Haynes Mathew George16081042017-05-31 17:16:49 -07007914 in->standby = false;
7915 ret = 0;
7916
7917 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
7918 __func__, info->shared_memory_address, info->buffer_size_frames);
7919
7920exit:
7921 if (ret != 0) {
7922 if (in->pcm == NULL) {
7923 ALOGE("%s: %s - %d", __func__, step, ret);
7924 } else {
7925 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
7926 pcm_close(in->pcm);
7927 in->pcm = NULL;
7928 }
7929 }
7930 pthread_mutex_unlock(&adev->lock);
7931 return ret;
7932}
7933
7934static int in_get_mmap_position(const struct audio_stream_in *stream,
7935 struct audio_mmap_position *position)
7936{
7937 struct stream_in *in = (struct stream_in *)stream;
7938 ALOGVV("%s", __func__);
7939 if (position == NULL) {
7940 return -EINVAL;
7941 }
Gautam Manam34d1f542021-01-05 20:24:37 +05307942 lock_input_stream(in);
Haynes Mathew George16081042017-05-31 17:16:49 -07007943 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
Gautam Manam34d1f542021-01-05 20:24:37 +05307944 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07007945 return -ENOSYS;
7946 }
7947 if (in->pcm == NULL) {
Gautam Manam34d1f542021-01-05 20:24:37 +05307948 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07007949 return -ENOSYS;
7950 }
7951 struct timespec ts = { 0, 0 };
7952 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
7953 if (ret < 0) {
7954 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
Gautam Manam34d1f542021-01-05 20:24:37 +05307955 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07007956 return ret;
7957 }
Phil Burke0a86d12019-02-16 22:28:11 -08007958 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7959 + in->mmap_time_offset_nanos;
Gautam Manam34d1f542021-01-05 20:24:37 +05307960 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07007961 return 0;
7962}
7963
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307964static int in_get_active_microphones(const struct audio_stream_in *stream,
7965 struct audio_microphone_characteristic_t *mic_array,
7966 size_t *mic_count) {
7967 struct stream_in *in = (struct stream_in *)stream;
7968 struct audio_device *adev = in->dev;
7969 ALOGVV("%s", __func__);
7970
7971 lock_input_stream(in);
7972 pthread_mutex_lock(&adev->lock);
7973 int ret = platform_get_active_microphones(adev->platform,
7974 audio_channel_count_from_in_mask(in->channel_mask),
7975 in->usecase, mic_array, mic_count);
7976 pthread_mutex_unlock(&adev->lock);
7977 pthread_mutex_unlock(&in->lock);
7978
7979 return ret;
7980}
7981
7982static int adev_get_microphones(const struct audio_hw_device *dev,
7983 struct audio_microphone_characteristic_t *mic_array,
7984 size_t *mic_count) {
7985 struct audio_device *adev = (struct audio_device *)dev;
7986 ALOGVV("%s", __func__);
7987
7988 pthread_mutex_lock(&adev->lock);
7989 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
7990 pthread_mutex_unlock(&adev->lock);
7991
7992 return ret;
7993}
juyuchendb308c22019-01-21 11:57:17 -07007994
7995static void in_update_sink_metadata(struct audio_stream_in *stream,
7996 const struct sink_metadata *sink_metadata) {
7997
7998 if (stream == NULL
7999 || sink_metadata == NULL
8000 || sink_metadata->tracks == NULL) {
8001 return;
8002 }
8003
8004 int error = 0;
8005 struct stream_in *in = (struct stream_in *)stream;
8006 struct audio_device *adev = in->dev;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008007 struct listnode devices;
8008
8009 list_init(&devices);
juyuchendb308c22019-01-21 11:57:17 -07008010
8011 if (sink_metadata->track_count != 0)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008012 reassign_device_list(&devices, sink_metadata->tracks->dest_device, "");
juyuchendb308c22019-01-21 11:57:17 -07008013
8014 lock_input_stream(in);
8015 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008016 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, get_device_types(&devices));
juyuchendb308c22019-01-21 11:57:17 -07008017
Zhou Song503196b2021-07-23 17:31:05 +08008018 if ((in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY ||
8019 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2) &&
8020 !list_empty(&devices) &&
8021 adev->voice_tx_output != NULL) {
juyuchendb308c22019-01-21 11:57:17 -07008022 /* Use the rx device from afe-proxy record to route voice call because
8023 there is no routing if tx device is on primary hal and rx device
8024 is on other hal during voice call. */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008025 assign_devices(&adev->voice_tx_output->device_list, &devices);
juyuchendb308c22019-01-21 11:57:17 -07008026
8027 if (!voice_is_call_state_active(adev)) {
8028 if (adev->mode == AUDIO_MODE_IN_CALL) {
8029 adev->current_call_output = adev->voice_tx_output;
8030 error = voice_start_call(adev);
8031 if (error != 0)
8032 ALOGE("%s: start voice call failed %d", __func__, error);
8033 }
8034 } else {
8035 adev->current_call_output = adev->voice_tx_output;
8036 voice_update_devices_for_all_voice_usecases(adev);
8037 }
8038 }
8039
8040 pthread_mutex_unlock(&adev->lock);
8041 pthread_mutex_unlock(&in->lock);
8042}
8043
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308044int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07008045 audio_io_handle_t handle,
8046 audio_devices_t devices,
8047 audio_output_flags_t flags,
8048 struct audio_config *config,
8049 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04008050 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008051{
8052 struct audio_device *adev = (struct audio_device *)dev;
8053 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05308054 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008055 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008056 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05308057 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008058 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
8059 bool is_usb_dev = audio_is_usb_out_device(devices) &&
8060 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
8061 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008062 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07008063 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
8064 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008065 bool force_haptic_path =
8066 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07008067 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008068#ifdef AUDIO_GKI_ENABLED
8069 __s32 *generic_dec;
8070#endif
Weiyin Jiang906db3c2021-03-02 13:17:04 +08008071 pthread_mutexattr_t latch_attr;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008072
kunleizdff872d2018-08-20 14:40:33 +08008073 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08008074 is_usb_dev = false;
8075 devices = AUDIO_DEVICE_OUT_SPEAKER;
8076 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
8077 __func__, devices);
Mingshu Pangdbd20562019-11-25 18:04:39 +08008078 if (config->format == AUDIO_FORMAT_DEFAULT)
8079 config->format = AUDIO_FORMAT_PCM_16_BIT;
8080 if (config->sample_rate == 0)
8081 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8082 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8083 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
kunleizd6a9e0c2018-07-30 15:38:52 +08008084 }
8085
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008086 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05308087
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008088 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
8089
Mingming Yin3a941d42016-02-17 18:08:05 -08008090 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04008091 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
8092 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308093
8094
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008095 if (!out) {
8096 return -ENOMEM;
8097 }
8098
Haynes Mathew George204045b2015-02-25 20:32:03 -08008099 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07008100 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Weiyin Jiang906db3c2021-03-02 13:17:04 +08008101 pthread_mutexattr_init(&latch_attr);
8102 pthread_mutexattr_settype(&latch_attr, PTHREAD_MUTEX_RECURSIVE);
8103 pthread_mutex_init(&out->latch_lock, &latch_attr);
8104 pthread_mutexattr_destroy(&latch_attr);
Zhou Song48453a02018-01-10 17:50:59 +08008105 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08008106 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
8107
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008108 if (devices == AUDIO_DEVICE_NONE)
8109 devices = AUDIO_DEVICE_OUT_SPEAKER;
8110
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008111 out->flags = flags;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008112 list_init(&out->device_list);
8113 update_device_list(&out->device_list, devices, address, true /* add devices */);
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07008114 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07008115 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008116 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05308117 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05308118 if (out->channel_mask == AUDIO_CHANNEL_NONE)
8119 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
8120 else
8121 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07008122 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07008123 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08008124 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308125 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308126 out->started = 0;
Zhou Songbaddf9f2020-11-20 13:57:39 +08008127 out->a2dp_muted = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008128 out->hal_output_suspend_supported = 0;
8129 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05308130 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05308131 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05308132 out->pspd_coeff_sent = false;
Phil Burkd898ba62019-06-20 12:49:01 -07008133 out->mmap_shared_memory_fd = -1; // not open
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008134
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05308135 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05308136 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07008137 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
8138
Aalique Grahame22e49102018-12-18 14:23:57 -08008139 if (direct_dev &&
8140 (audio_is_linear_pcm(out->format) ||
8141 config->format == AUDIO_FORMAT_DEFAULT) &&
8142 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
8143 audio_format_t req_format = config->format;
8144 audio_channel_mask_t req_channel_mask = config->channel_mask;
8145 uint32_t req_sample_rate = config->sample_rate;
8146
8147 pthread_mutex_lock(&adev->lock);
8148 if (is_hdmi) {
8149 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
8150 ret = read_hdmi_sink_caps(out);
8151 if (config->sample_rate == 0)
8152 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8153 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8154 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
8155 if (config->format == AUDIO_FORMAT_DEFAULT)
8156 config->format = AUDIO_FORMAT_PCM_16_BIT;
8157 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008158 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
8159 &config->format,
8160 &out->supported_formats[0],
8161 MAX_SUPPORTED_FORMATS,
8162 &config->channel_mask,
8163 &out->supported_channel_masks[0],
8164 MAX_SUPPORTED_CHANNEL_MASKS,
8165 &config->sample_rate,
8166 &out->supported_sample_rates[0],
8167 MAX_SUPPORTED_SAMPLE_RATES);
8168 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008169 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008170
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008171 pthread_mutex_unlock(&adev->lock);
8172 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08008173 if (ret == -ENOSYS) {
8174 /* ignore and go with default */
8175 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08008176 }
8177 // For MMAP NO IRQ, allow conversions in ADSP
8178 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
8179 goto error_open;
8180 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008181 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08008182 goto error_open;
8183 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008184
8185 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
8186 config->sample_rate = req_sample_rate;
8187 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
8188 config->channel_mask = req_channel_mask;
8189 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
8190 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08008191 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008192
8193 out->sample_rate = config->sample_rate;
8194 out->channel_mask = config->channel_mask;
8195 out->format = config->format;
8196 if (is_hdmi) {
8197 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
8198 out->config = pcm_config_hdmi_multi;
8199 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8200 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8201 out->config = pcm_config_mmap_playback;
8202 out->stream.start = out_start;
8203 out->stream.stop = out_stop;
8204 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8205 out->stream.get_mmap_position = out_get_mmap_position;
8206 } else {
8207 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
8208 out->config = pcm_config_hifi;
8209 }
8210
8211 out->config.rate = out->sample_rate;
8212 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
8213 if (is_hdmi) {
8214 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
8215 audio_bytes_per_sample(out->format));
8216 }
8217 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08008218 }
8219
Derek Chenf6318be2017-06-12 17:16:24 -04008220 /* validate bus device address */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008221 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008222 /* extract car audio stream index */
8223 out->car_audio_stream =
8224 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
8225 if (out->car_audio_stream < 0) {
8226 ALOGE("%s: invalid car audio stream %x",
8227 __func__, out->car_audio_stream);
8228 ret = -EINVAL;
8229 goto error_open;
8230 }
Derek Chen5f67a942020-02-24 23:08:13 -08008231 ALOGV("%s: car_audio_stream %x", __func__, out->car_audio_stream);
Derek Chenf6318be2017-06-12 17:16:24 -04008232 }
8233
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008234 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07008235 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008236 if (!voice_extn_is_compress_voip_supported()) {
8237 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
8238 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07008239 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
Lakshman Chaluvarajue7fc9482020-05-30 14:29:29 +05308240 config->channel_mask : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008241 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
8242 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07008243 out->volume_l = INVALID_OUT_VOLUME;
8244 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07008245
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008246 out->config = default_pcm_config_voip_copp;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008247 out->config.rate = out->sample_rate;
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07008248 uint32_t channel_count =
8249 audio_channel_count_from_out_mask(out->channel_mask);
Ramjee Singh968858a2020-08-06 16:30:48 +05308250 out->config.channels = channel_count;
8251
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07008252 uint32_t buffer_size = get_stream_buffer_size(DEFAULT_VOIP_BUF_DURATION_MS,
8253 out->sample_rate, out->format,
8254 channel_count, false);
8255 uint32_t frame_size = audio_bytes_per_sample(out->format) * channel_count;
8256 if (frame_size != 0)
8257 out->config.period_size = buffer_size / frame_size;
8258 else
8259 ALOGW("%s: frame size is 0 for format %#x", __func__, out->format);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008260 }
8261 } else {
8262 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
8263 voice_extn_compress_voip_is_active(out->dev)) &&
8264 (voice_extn_compress_voip_is_config_supported(config))) {
8265 ret = voice_extn_compress_voip_open_output_stream(out);
8266 if (ret != 0) {
8267 ALOGE("%s: Compress voip output cannot be opened, error:%d",
8268 __func__, ret);
8269 goto error_open;
8270 }
Sujin Panicker19027262019-09-16 18:28:06 +05308271 } else {
8272 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8273 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008274 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008275 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008276 } else if (audio_is_linear_pcm(out->format) &&
8277 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
8278 out->channel_mask = config->channel_mask;
8279 out->sample_rate = config->sample_rate;
8280 out->format = config->format;
8281 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
8282 // does this change?
8283 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
8284 out->config.rate = config->sample_rate;
8285 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
8286 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
8287 audio_bytes_per_sample(config->format));
8288 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07008289 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308290 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308291 pthread_mutex_lock(&adev->lock);
8292 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
8293 pthread_mutex_unlock(&adev->lock);
8294
8295 // reject offload during card offline to allow
8296 // fallback to s/w paths
8297 if (offline) {
8298 ret = -ENODEV;
8299 goto error_open;
8300 }
vivek mehta0ea887a2015-08-26 14:01:20 -07008301
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008302 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
8303 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
8304 ALOGE("%s: Unsupported Offload information", __func__);
8305 ret = -EINVAL;
8306 goto error_open;
8307 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008308
Atul Khare3fa6e542017-08-09 00:56:17 +05308309 if (config->offload_info.format == 0)
8310 config->offload_info.format = config->format;
8311 if (config->offload_info.sample_rate == 0)
8312 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008313
Mingming Yin90310102013-11-13 16:57:00 -08008314 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308315 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07008316 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008317 ret = -EINVAL;
8318 goto error_open;
8319 }
8320
Ben Romberger0f8c87b2017-05-24 17:41:11 -07008321 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
8322 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
8323 (audio_extn_passthru_is_passthrough_stream(out)) &&
8324 !((config->sample_rate == 48000) ||
8325 (config->sample_rate == 96000) ||
8326 (config->sample_rate == 192000))) {
8327 ALOGE("%s: Unsupported sample rate %d for audio format %x",
8328 __func__, config->sample_rate, config->offload_info.format);
8329 ret = -EINVAL;
8330 goto error_open;
8331 }
8332
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008333 out->compr_config.codec = (struct snd_codec *)
8334 calloc(1, sizeof(struct snd_codec));
8335
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008336 if (!out->compr_config.codec) {
8337 ret = -ENOMEM;
8338 goto error_open;
8339 }
8340
Dhananjay Kumarac341582017-02-23 23:42:25 +05308341 out->stream.pause = out_pause;
8342 out->stream.resume = out_resume;
8343 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05308344 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05308345 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07008346 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05308347 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07008348 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05308349 } else {
8350 out->usecase = get_offload_usecase(adev, false /* is_compress */);
8351 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07008352 }
vivek mehta446c3962015-09-14 10:57:35 -07008353
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308354 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8355 ALOGD("%s: Setting latency mode to true", __func__);
Meng Wang4c32fb42020-01-16 17:57:11 +08008356#ifdef AUDIO_GKI_ENABLED
8357 /* out->compr_config.codec->reserved[1] is for flags */
8358 out->compr_config.codec->reserved[1] |= audio_extn_utils_get_perf_mode_flag();
8359#else
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308360 out->compr_config.codec->flags |= audio_extn_utils_get_perf_mode_flag();
Meng Wang4c32fb42020-01-16 17:57:11 +08008361#endif
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308362 }
8363
vivek mehta446c3962015-09-14 10:57:35 -07008364 if (out->usecase == USECASE_INVALID) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008365 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Mingming Yin3a941d42016-02-17 18:08:05 -08008366 config->format == 0 && config->sample_rate == 0 &&
8367 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07008368 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08008369 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
8370 } else {
8371 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
8372 ret = -EEXIST;
8373 goto error_open;
8374 }
vivek mehta446c3962015-09-14 10:57:35 -07008375 }
8376
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008377 if (config->offload_info.channel_mask)
8378 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008379 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008380 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008381 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008382 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05308383 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008384 ret = -EINVAL;
8385 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008386 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008387
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008388 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008389 out->sample_rate = config->offload_info.sample_rate;
8390
Mingming Yin3ee55c62014-08-04 14:23:35 -07008391 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008392
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308393 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05308394 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308395 audio_extn_dolby_send_ddp_endp_params(adev);
8396 audio_extn_dolby_set_dmid(adev);
8397 }
vivek mehta0ea887a2015-08-26 14:01:20 -07008398
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008399 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08008400 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008401 out->compr_config.codec->bit_rate =
8402 config->offload_info.bit_rate;
8403 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05308404 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008405 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05308406 /* Update bit width only for non passthrough usecases.
8407 * For passthrough usecases, the output will always be opened @16 bit
8408 */
8409 if (!audio_extn_passthru_is_passthrough_stream(out))
8410 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308411
8412 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
Meng Wang4c32fb42020-01-16 17:57:11 +08008413#ifdef AUDIO_GKI_ENABLED
8414 /* out->compr_config.codec->reserved[1] is for flags */
8415 out->compr_config.codec->reserved[1] |= COMPRESSED_TIMESTAMP_FLAG;
8416 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->reserved[1]);
8417#else
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308418 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
8419 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
Meng Wang4c32fb42020-01-16 17:57:11 +08008420#endif
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308421
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008422 /*TODO: Do we need to change it for passthrough */
8423 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008424
Manish Dewangana6fc5442015-08-24 20:30:31 +05308425 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
8426 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308427 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05308428 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308429 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
8430 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308431
8432 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
8433 AUDIO_FORMAT_PCM) {
8434
8435 /*Based on platform support, configure appropriate alsa format for corresponding
8436 *hal input format.
8437 */
8438 out->compr_config.codec->format = hal_format_to_alsa(
8439 config->offload_info.format);
8440
Ashish Jain83a6cc22016-06-28 14:34:17 +05308441 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05308442 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308443 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308444
Dhananjay Kumarac341582017-02-23 23:42:25 +05308445 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05308446 *hal input format and alsa format might differ based on platform support.
8447 */
8448 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05308449 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308450
8451 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
8452
Deeraj Soman93155a62019-09-30 19:00:37 +05308453 if (property_get_bool("vendor.audio.offload.buffer.duration.enabled", false)) {
8454 if ((config->offload_info.duration_us >= MIN_OFFLOAD_BUFFER_DURATION_MS * 1000) &&
8455 (config->offload_info.duration_us <= MAX_OFFLOAD_BUFFER_DURATION_MS * 1000))
8456 out->info.duration_us = (int64_t)config->offload_info.duration_us;
8457 }
Deeraj Soman65358ab2019-02-07 15:40:49 +05308458
Ashish Jainf1eaa582016-05-23 20:54:24 +05308459 /* Check if alsa session is configured with the same format as HAL input format,
8460 * if not then derive correct fragment size needed to accomodate the
8461 * conversion of HAL input format to alsa format.
8462 */
8463 audio_extn_utils_update_direct_pcm_fragment_size(out);
8464
8465 /*if hal input and output fragment size is different this indicates HAL input format is
8466 *not same as the alsa format
8467 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308468 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05308469 /*Allocate a buffer to convert input data to the alsa configured format.
8470 *size of convert buffer is equal to the size required to hold one fragment size
8471 *worth of pcm data, this is because flinger does not write more than fragment_size
8472 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308473 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
8474 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05308475 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
8476 ret = -ENOMEM;
8477 goto error_open;
8478 }
8479 }
8480 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
8481 out->compr_config.fragment_size =
8482 audio_extn_passthru_get_buffer_size(&config->offload_info);
8483 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8484 } else {
8485 out->compr_config.fragment_size =
8486 platform_get_compress_offload_buffer_size(&config->offload_info);
8487 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8488 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008489
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308490 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8491 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
8492 }
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008493 if (config->offload_info.format == AUDIO_FORMAT_FLAC) {
8494#ifdef AUDIO_GKI_ENABLED
8495 generic_dec =
8496 &(out->compr_config.codec->options.generic.reserved[1]);
8497 ((struct snd_generic_dec_flac *)generic_dec)->sample_size =
8498 AUDIO_OUTPUT_BIT_WIDTH;
8499#else
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05308500 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008501#endif
8502 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008503
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05308504 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
8505 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
8506 }
8507
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008508 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
8509 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008510
Manish Dewangan69426c82017-01-30 17:35:36 +05308511 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
8512 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
8513 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
8514 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8515 out->render_mode = RENDER_MODE_AUDIO_MASTER;
8516 } else {
8517 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
8518 }
Alexy Josephaa54c872014-12-03 02:46:47 -08008519
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05308520 memset(&out->channel_map_param, 0,
8521 sizeof(struct audio_out_channel_map_param));
8522
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008523 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05308524 out->send_next_track_params = false;
8525 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008526 out->offload_state = OFFLOAD_STATE_IDLE;
8527 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08008528 out->writeAt.tv_sec = 0;
8529 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008530
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008531 audio_extn_dts_create_state_notifier_node(out->usecase);
8532
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008533 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
8534 __func__, config->offload_info.version,
8535 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05308536
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308537 /* Check if DSD audio format is supported in codec
8538 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308539 */
8540
8541 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308542 (!platform_check_codec_dsd_support(adev->platform) ||
8543 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308544 ret = -EINVAL;
8545 goto error_open;
8546 }
8547
Ashish Jain5106d362016-05-11 19:23:33 +05308548 /* Disable gapless if any of the following is true
8549 * passthrough playback
8550 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05308551 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05308552 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308553 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308554 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07008555 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308556 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308557 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05308558 check_and_set_gapless_mode(adev, false);
8559 } else
8560 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07008561
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308562 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07008563 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
8564 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308565 if (config->format == AUDIO_FORMAT_DSD) {
8566 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
Meng Wang4c32fb42020-01-16 17:57:11 +08008567#ifdef AUDIO_GKI_ENABLED
8568 /* out->compr_config.codec->reserved[0] is for compr_passthr */
8569 out->compr_config.codec->reserved[0] = PASSTHROUGH_DSD;
8570#else
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308571 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
Meng Wang4c32fb42020-01-16 17:57:11 +08008572#endif
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308573 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07008574
8575 create_offload_callback_thread(out);
8576
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008577 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008578 switch (config->sample_rate) {
8579 case 0:
8580 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8581 break;
8582 case 8000:
8583 case 16000:
8584 case 48000:
8585 out->sample_rate = config->sample_rate;
8586 break;
8587 default:
8588 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
8589 config->sample_rate);
8590 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8591 ret = -EINVAL;
8592 goto error_open;
8593 }
8594 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8595 switch (config->channel_mask) {
8596 case AUDIO_CHANNEL_NONE:
8597 case AUDIO_CHANNEL_OUT_STEREO:
8598 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8599 break;
8600 default:
8601 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
8602 config->channel_mask);
8603 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8604 ret = -EINVAL;
8605 goto error_open;
8606 }
8607 switch (config->format) {
8608 case AUDIO_FORMAT_DEFAULT:
8609 case AUDIO_FORMAT_PCM_16_BIT:
8610 out->format = AUDIO_FORMAT_PCM_16_BIT;
8611 break;
8612 default:
8613 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
8614 config->format);
8615 config->format = AUDIO_FORMAT_PCM_16_BIT;
8616 ret = -EINVAL;
8617 goto error_open;
8618 }
8619
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05308620 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008621 if (ret != 0) {
8622 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008623 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008624 goto error_open;
8625 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008626 } else if (is_single_device_type_equal(&out->device_list,
8627 AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08008628 switch (config->sample_rate) {
8629 case 0:
8630 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
8631 break;
8632 case 8000:
8633 case 16000:
8634 case 48000:
8635 out->sample_rate = config->sample_rate;
8636 break;
8637 default:
8638 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
8639 config->sample_rate);
8640 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8641 ret = -EINVAL;
8642 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008643 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008644 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8645 switch (config->channel_mask) {
8646 case AUDIO_CHANNEL_NONE:
8647 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8648 break;
8649 case AUDIO_CHANNEL_OUT_STEREO:
8650 out->channel_mask = config->channel_mask;
8651 break;
8652 default:
8653 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
8654 config->channel_mask);
8655 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8656 ret = -EINVAL;
8657 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008658 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008659 switch (config->format) {
8660 case AUDIO_FORMAT_DEFAULT:
8661 out->format = AUDIO_FORMAT_PCM_16_BIT;
8662 break;
8663 case AUDIO_FORMAT_PCM_16_BIT:
8664 out->format = config->format;
8665 break;
8666 default:
8667 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
8668 config->format);
8669 config->format = AUDIO_FORMAT_PCM_16_BIT;
8670 ret = -EINVAL;
8671 break;
8672 }
8673 if (ret != 0)
8674 goto error_open;
8675
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008676 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
8677 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08008678 out->config.rate = out->sample_rate;
8679 out->config.channels =
8680 audio_channel_count_from_out_mask(out->channel_mask);
8681 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008682 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008683 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05308684 unsigned int channels = 0;
8685 /*Update config params to default if not set by the caller*/
8686 if (config->sample_rate == 0)
8687 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8688 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8689 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8690 if (config->format == AUDIO_FORMAT_DEFAULT)
8691 config->format = AUDIO_FORMAT_PCM_16_BIT;
8692
8693 channels = audio_channel_count_from_out_mask(out->channel_mask);
8694
Varun Balaraje49253e2017-07-06 19:48:56 +05308695 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
8696 out->usecase = get_interactive_usecase(adev);
8697 out->config = pcm_config_low_latency;
8698 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05308699 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008700 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
8701 out->flags);
8702 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07008703 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8704 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8705 out->config = pcm_config_mmap_playback;
8706 out->stream.start = out_start;
8707 out->stream.stop = out_stop;
8708 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8709 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308710 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8711 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008712 out->hal_output_suspend_supported =
8713 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
8714 out->dynamic_pm_qos_config_supported =
8715 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
8716 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08008717 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
8718 } else {
8719 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
8720 //the mixer path will be a string similar to "low-latency-playback resume"
8721 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
8722 strlcat(out->pm_qos_mixer_path,
8723 " resume", MAX_MIXER_PATH_LEN);
8724 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
8725 out->pm_qos_mixer_path);
8726 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308727 out->config = pcm_config_low_latency;
8728 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
8729 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
8730 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05308731 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
8732 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
8733 if (out->config.period_size <= 0) {
8734 ALOGE("Invalid configuration period size is not valid");
8735 ret = -EINVAL;
8736 goto error_open;
8737 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008738 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
8739 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
8740 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008741 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
8742 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
8743 out->config = pcm_config_haptics_audio;
8744 if (force_haptic_path)
8745 adev->haptics_config = pcm_config_haptics_audio;
8746 else
8747 adev->haptics_config = pcm_config_haptics;
8748
Meng Wangd08ce322020-04-02 08:59:20 +08008749 channels =
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008750 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
8751
8752 if (force_haptic_path) {
8753 out->config.channels = 1;
8754 adev->haptics_config.channels = 1;
8755 } else
8756 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 -08008757 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008758 ret = audio_extn_auto_hal_open_output_stream(out);
8759 if (ret) {
8760 ALOGE("%s: Failed to open output stream for bus device", __func__);
8761 ret = -EINVAL;
8762 goto error_open;
8763 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308764 } else {
8765 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008766 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8767 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308768 }
8769 out->hal_ip_format = format = out->format;
8770 out->config.format = hal_format_to_pcm(out->hal_ip_format);
8771 out->hal_op_format = pcm_format_to_hal(out->config.format);
8772 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
8773 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008774 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05308775 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308776 if (out->hal_ip_format != out->hal_op_format) {
8777 uint32_t buffer_size = out->config.period_size *
8778 format_to_bitwidth_table[out->hal_op_format] *
8779 out->config.channels;
8780 out->convert_buffer = calloc(1, buffer_size);
8781 if (out->convert_buffer == NULL){
8782 ALOGE("Allocation failed for convert buffer for size %d",
8783 out->compr_config.fragment_size);
8784 ret = -ENOMEM;
8785 goto error_open;
8786 }
8787 ALOGD("Convert buffer allocated of size %d", buffer_size);
8788 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008789 }
8790
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008791 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
8792 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308793
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008794 /* TODO remove this hardcoding and check why width is zero*/
8795 if (out->bit_width == 0)
8796 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308797 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008798 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008799 &out->device_list, out->flags,
8800 out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05308801 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05308802 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08008803 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08008804 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
8805 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008806 if(adev->primary_output == NULL)
8807 adev->primary_output = out;
8808 else {
8809 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008810 ret = -EEXIST;
8811 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008812 }
8813 }
8814
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008815 /* Check if this usecase is already existing */
8816 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07008817 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
8818 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008819 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008820 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008821 ret = -EEXIST;
8822 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008823 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008824
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008825 pthread_mutex_unlock(&adev->lock);
8826
8827 out->stream.common.get_sample_rate = out_get_sample_rate;
8828 out->stream.common.set_sample_rate = out_set_sample_rate;
8829 out->stream.common.get_buffer_size = out_get_buffer_size;
8830 out->stream.common.get_channels = out_get_channels;
8831 out->stream.common.get_format = out_get_format;
8832 out->stream.common.set_format = out_set_format;
8833 out->stream.common.standby = out_standby;
8834 out->stream.common.dump = out_dump;
8835 out->stream.common.set_parameters = out_set_parameters;
8836 out->stream.common.get_parameters = out_get_parameters;
8837 out->stream.common.add_audio_effect = out_add_audio_effect;
8838 out->stream.common.remove_audio_effect = out_remove_audio_effect;
8839 out->stream.get_latency = out_get_latency;
8840 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08008841#ifdef NO_AUDIO_OUT
8842 out->stream.write = out_write_for_no_output;
8843#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008844 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08008845#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008846 out->stream.get_render_position = out_get_render_position;
8847 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008848 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008849
Haynes Mathew George16081042017-05-31 17:16:49 -07008850 if (out->realtime)
8851 out->af_period_multiplier = af_period_multiplier;
8852 else
8853 out->af_period_multiplier = 1;
8854
Andy Hunga1f48fa2019-07-01 18:14:53 -07008855 out->kernel_buffer_size = out->config.period_size * out->config.period_count;
8856
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008857 out->standby = 1;
Zhou Songbaddf9f2020-11-20 13:57:39 +08008858 out->volume_l = PLAYBACK_GAIN_MAX;
8859 out->volume_r = PLAYBACK_GAIN_MAX;
Eric Laurenta9024de2013-04-04 09:19:12 -07008860 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008861 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008862
8863 config->format = out->stream.common.get_format(&out->stream.common);
8864 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
8865 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308866 register_format(out->format, out->supported_formats);
8867 register_channel_mask(out->channel_mask, out->supported_channel_masks);
8868 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008869
Dechen Chai22768452021-07-30 09:29:16 +05308870#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -08008871 out->error_log = error_log_create(
8872 ERROR_LOG_ENTRIES,
8873 1000000000 /* aggregate consecutive identical errors within one second in ns */);
Dechen Chai22768452021-07-30 09:29:16 +05308874#endif
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308875 /*
8876 By locking output stream before registering, we allow the callback
8877 to update stream's state only after stream's initial state is set to
8878 adev state.
8879 */
8880 lock_output_stream(out);
8881 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
8882 pthread_mutex_lock(&adev->lock);
8883 out->card_status = adev->card_status;
8884 pthread_mutex_unlock(&adev->lock);
8885 pthread_mutex_unlock(&out->lock);
8886
Aalique Grahame22e49102018-12-18 14:23:57 -08008887 stream_app_type_cfg_init(&out->app_type_cfg);
8888
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008889 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308890 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07008891 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008892
8893 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
8894 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
8895 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008896 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05308897 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008898 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07008899 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05308900 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
8901 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008902 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
8903 out->usecase, PCM_PLAYBACK);
8904 hdlr_stream_cfg.flags = out->flags;
8905 hdlr_stream_cfg.type = PCM_PLAYBACK;
8906 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
8907 &hdlr_stream_cfg);
8908 if (ret) {
8909 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
8910 out->adsp_hdlr_stream_handle = NULL;
8911 }
8912 }
Gangadhar Sb0210342019-02-22 17:39:41 +05308913 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
8914 is_direct_passthough, false);
8915 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
8916 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07008917 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07008918 if (ret < 0) {
8919 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
8920 out->ip_hdlr_handle = NULL;
8921 }
8922 }
Derek Chenf939fb72018-11-13 13:34:41 -08008923
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008924 ret = io_streams_map_insert(adev, &out->stream.common,
8925 out->handle, AUDIO_PATCH_HANDLE_NONE);
8926 if (ret != 0)
8927 goto error_open;
8928
Susan Wang6dd13092021-01-25 10:27:11 -05008929 out->out_ctxt.output = out;
Derek Chenf939fb72018-11-13 13:34:41 -08008930
8931 pthread_mutex_lock(&adev->lock);
Susan Wang6dd13092021-01-25 10:27:11 -05008932 list_add_tail(&adev->active_outputs_list, &out->out_ctxt.list);
Derek Chenf939fb72018-11-13 13:34:41 -08008933 pthread_mutex_unlock(&adev->lock);
8934
Eric Laurent994a6932013-07-17 11:51:42 -07008935 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008936 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008937
8938error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05308939 if (out->convert_buffer)
8940 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008941 free(out);
8942 *stream_out = NULL;
8943 ALOGD("%s: exit: ret %d", __func__, ret);
8944 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008945}
8946
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308947void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008948 struct audio_stream_out *stream)
8949{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008950 struct stream_out *out = (struct stream_out *)stream;
8951 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008952 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008953
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008954 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308955
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008956 io_streams_map_remove(adev, out->handle);
8957
Susan Wang6dd13092021-01-25 10:27:11 -05008958 // remove out_ctxt early to prevent the stream
8959 // being opened in a race condition
8960 pthread_mutex_lock(&adev->lock);
8961 list_remove(&out->out_ctxt.list);
8962 pthread_mutex_unlock(&adev->lock);
8963
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308964 // must deregister from sndmonitor first to prevent races
8965 // between the callback and close_stream
8966 audio_extn_snd_mon_unregister_listener(out);
8967
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008968 /* close adsp hdrl session before standby */
8969 if (out->adsp_hdlr_stream_handle) {
8970 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
8971 if (ret)
8972 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
8973 out->adsp_hdlr_stream_handle = NULL;
8974 }
8975
Manish Dewangan21a850a2017-08-14 12:03:55 +05308976 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07008977 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
8978 out->ip_hdlr_handle = NULL;
8979 }
8980
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008981 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308982 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008983 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308984 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308985 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008986 if(ret != 0)
8987 ALOGE("%s: Compress voip output cannot be closed, error:%d",
8988 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008989 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008990 out_standby(&stream->common);
8991
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008992 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008993 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008994 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008995 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008996 if (out->compr_config.codec != NULL)
8997 free(out->compr_config.codec);
8998 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008999
Zhou Songbaddf9f2020-11-20 13:57:39 +08009000 out->a2dp_muted = false;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05309001
Varun Balaraje49253e2017-07-06 19:48:56 +05309002 if (is_interactive_usecase(out->usecase))
9003 free_interactive_usecase(adev, out->usecase);
9004
Ashish Jain83a6cc22016-06-28 14:34:17 +05309005 if (out->convert_buffer != NULL) {
9006 free(out->convert_buffer);
9007 out->convert_buffer = NULL;
9008 }
9009
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009010 if (adev->voice_tx_output == out)
9011 adev->voice_tx_output = NULL;
9012
Dechen Chai22768452021-07-30 09:29:16 +05309013#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -08009014 error_log_destroy(out->error_log);
9015 out->error_log = NULL;
Dechen Chai22768452021-07-30 09:29:16 +05309016#endif
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05309017 if (adev->primary_output == out)
9018 adev->primary_output = NULL;
9019
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07009020 pthread_cond_destroy(&out->cond);
9021 pthread_mutex_destroy(&out->lock);
Weiyin Jiang280ea742020-09-08 20:28:22 +08009022 pthread_mutex_destroy(&out->pre_lock);
9023 pthread_mutex_destroy(&out->latch_lock);
9024 pthread_mutex_destroy(&out->position_query_lock);
Derek Chenf939fb72018-11-13 13:34:41 -08009025
9026 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009027 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08009028 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07009029 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009030}
9031
9032static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
9033{
9034 struct audio_device *adev = (struct audio_device *)dev;
9035 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009036 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07009037 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009038 int ret;
9039 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08009040 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08009041 struct listnode *node;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07009042 int controller = -1, stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009043
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009044 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009045 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009046
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05309047 if (!parms)
9048 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05309049
Derek Chen6f293672019-04-01 01:40:24 -07009050 /* notify adev and input/output streams on the snd card status */
9051 adev_snd_mon_cb((void *)adev, parms);
9052
Weiyin Jiang24f55292020-12-22 14:35:46 +08009053 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
9054 if (ret >= 0) {
9055 list_for_each(node, &adev->active_outputs_list) {
9056 streams_output_ctxt_t *out_ctxt = node_to_item(node,
9057 streams_output_ctxt_t,
9058 list);
9059 out_snd_mon_cb((void *)out_ctxt->output, parms);
9060 }
Derek Chen6f293672019-04-01 01:40:24 -07009061
Weiyin Jiang24f55292020-12-22 14:35:46 +08009062 list_for_each(node, &adev->active_inputs_list) {
9063 streams_input_ctxt_t *in_ctxt = node_to_item(node,
9064 streams_input_ctxt_t,
9065 list);
9066 in_snd_mon_cb((void *)in_ctxt->input, parms);
9067 }
Derek Chen6f293672019-04-01 01:40:24 -07009068 }
9069
Zhou Songd6d71752019-05-21 18:08:51 +08009070 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05309071 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
9072 if (ret >= 0) {
9073 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08009074 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05309075 adev->bt_sco_on = true;
Shalini Manjunatha3a2e06e2021-02-01 12:23:49 +05309076 /*
9077 * When ever BT_SCO=ON arrives, make sure to route
9078 * all use cases to SCO device, otherwise due to delay in
9079 * BT_SCO=ON and lack of synchronization with create audio patch
9080 * request for SCO device, some times use case not routed properly to
9081 * SCO device
9082 */
9083 struct audio_usecase *usecase;
9084 struct listnode *node;
9085 list_for_each(node, &adev->usecase_list) {
9086 usecase = node_to_item(node, struct audio_usecase, list);
Anver sadhiquef0efca32021-09-03 15:25:44 +05309087 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
Anver sadhique93f3c912021-08-11 11:19:45 +05309088 (!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 +05309089 ALOGD("BT_SCO ON, switch all in use case to it");
9090 select_devices(adev, usecase->id);
9091 }
Mingshu Pangef517202021-04-22 10:35:00 +08009092 if (usecase->stream.out && (usecase->type == PCM_PLAYBACK ||
9093 usecase->type == VOICE_CALL) &&
Anver sadhique93f3c912021-08-11 11:19:45 +05309094 (!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 +05309095 ALOGD("BT_SCO ON, switch all out use case to it");
9096 select_devices(adev, usecase->id);
9097 }
9098 }
9099 }
9100 else {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05309101 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08009102 audio_extn_sco_reset_configuration();
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08009103 }
9104 }
9105
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009106 status = voice_set_parameters(adev, parms);
9107 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08009108 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009109
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009110 status = platform_set_parameters(adev->platform, parms);
9111 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08009112 goto done;
9113
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009114 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
9115 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07009116 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009117 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
9118 adev->bluetooth_nrec = true;
9119 else
9120 adev->bluetooth_nrec = false;
9121 }
9122
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009123 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
9124 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009125 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
9126 adev->screen_off = false;
9127 else
9128 adev->screen_off = true;
Quinn Male70f20f32019-06-26 16:50:26 -07009129 audio_extn_sound_trigger_update_screen_status(adev->screen_off);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009130 }
9131
Eric Laurent4b084132018-10-19 17:33:43 -07009132 ret = str_parms_get_int(parms, "rotation", &val);
9133 if (ret >= 0) {
9134 bool reverse_speakers = false;
9135 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
9136 switch (val) {
9137 // FIXME: note that the code below assumes that the speakers are in the correct placement
9138 // relative to the user when the device is rotated 90deg from its default rotation. This
9139 // assumption is device-specific, not platform-specific like this code.
9140 case 270:
9141 reverse_speakers = true;
9142 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
9143 break;
9144 case 0:
9145 case 180:
9146 camera_rotation = CAMERA_ROTATION_PORTRAIT;
9147 break;
9148 case 90:
9149 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
9150 break;
9151 default:
9152 ALOGE("%s: unexpected rotation of %d", __func__, val);
9153 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07009154 }
Eric Laurent4b084132018-10-19 17:33:43 -07009155 if (status == 0) {
9156 // check and set swap
9157 // - check if orientation changed and speaker active
9158 // - set rotation and cache the rotation value
9159 adev->camera_orientation =
9160 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
9161 if (!audio_extn_is_maxx_audio_enabled())
9162 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
9163 }
9164 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07009165
Mingming Yin514a8bc2014-07-29 15:22:21 -07009166 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
9167 if (ret >= 0) {
9168 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
9169 adev->bt_wb_speech_enabled = true;
9170 else
9171 adev->bt_wb_speech_enabled = false;
9172 }
9173
Zhou Song12c29502019-03-16 10:37:18 +08009174 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
9175 if (ret >= 0) {
9176 val = atoi(value);
9177 adev->swb_speech_mode = val;
9178 }
9179
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07009180 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
9181 if (ret >= 0) {
9182 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309183 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08009184 if (audio_is_output_device(val) &&
9185 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07009186 ALOGV("cache new ext disp type and edid");
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07009187 platform_get_controller_stream_from_params(parms, &controller, &stream);
9188 platform_set_ext_display_device_v2(adev->platform, controller, stream);
9189 ret = platform_get_ext_disp_type_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07009190 if (ret < 0) {
9191 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05309192 } else {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07009193 platform_cache_edid_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07009194 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309195 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07009196 /*
9197 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
9198 * Per AudioPolicyManager, USB device is higher priority than WFD.
9199 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
9200 * If WFD use case occupies AFE proxy, it may result unintended behavior while
9201 * starting voice call on USB
9202 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08009203 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309204 if (ret >= 0)
9205 audio_extn_usb_add_device(device, atoi(value));
9206
Zhou Song6f862822017-11-06 17:27:57 +08009207 if (!audio_extn_usb_is_tunnel_supported()) {
9208 ALOGV("detected USB connect .. disable proxy");
9209 adev->allow_afe_proxy_usage = false;
9210 }
Zhou Song503196b2021-07-23 17:31:05 +08009211 } else if (audio_is_hearing_aid_out_device(device) &&
9212 property_get_bool("persist.vendor.audio.ha_proxy.enabled", false)) {
9213 adev->ha_proxy_enable = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07009214 }
9215 }
9216
9217 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
9218 if (ret >= 0) {
9219 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309220 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07009221 /*
9222 * The HDMI / Displayport disconnect handling has been moved to
9223 * audio extension to ensure that its parameters are not
9224 * invalidated prior to updating sysfs of the disconnect event
9225 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
9226 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309227 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08009228 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309229 if (ret >= 0)
9230 audio_extn_usb_remove_device(device, atoi(value));
9231
Zhou Song6f862822017-11-06 17:27:57 +08009232 if (!audio_extn_usb_is_tunnel_supported()) {
9233 ALOGV("detected USB disconnect .. enable proxy");
9234 adev->allow_afe_proxy_usage = true;
9235 }
Zhou Song503196b2021-07-23 17:31:05 +08009236 } else if (audio_is_hearing_aid_out_device(device)) {
9237 adev->ha_proxy_enable = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07009238 }
9239 }
9240
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009241 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08009242
9243 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08009244 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309245 struct audio_usecase *usecase;
9246 struct listnode *node;
9247 list_for_each(node, &adev->usecase_list) {
9248 usecase = node_to_item(node, struct audio_usecase, list);
Weiyin Jiangff56ff32020-05-08 14:32:21 +08009249 if ((usecase->stream.out == NULL) || (usecase->type != PCM_PLAYBACK))
9250 continue;
9251
9252 if (is_a2dp_out_device_type(&usecase->device_list)) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309253 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05309254 audio_extn_a2dp_set_handoff_mode(true);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05309255 ALOGD("Switching to speaker and muting the stream before select_devices");
9256 check_a2dp_restore_l(adev, usecase->stream.out, false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309257 //force device switch to re configure encoder
9258 select_devices(adev, usecase->id);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05309259 ALOGD("Unmuting the stream after select_devices");
Zhou Songbaddf9f2020-11-20 13:57:39 +08009260 check_a2dp_restore_l(adev, usecase->stream.out, true);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05309261 audio_extn_a2dp_set_handoff_mode(false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309262 break;
Zhou Songd01e7a22020-09-23 22:49:01 +08009263 } else if (is_offload_usecase(usecase->stream.out->usecase)) {
Weiyin Jiang280ea742020-09-08 20:28:22 +08009264 pthread_mutex_lock(&usecase->stream.out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +08009265 if (usecase->stream.out->a2dp_muted) {
Weiyin Jiang280ea742020-09-08 20:28:22 +08009266 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
9267 reassign_device_list(&usecase->stream.out->device_list,
9268 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, "");
9269 check_a2dp_restore_l(adev, usecase->stream.out, true);
9270 break;
9271 }
9272 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309273 }
9274 }
9275 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009276
9277 //handle vr audio setparam
9278 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9279 value, sizeof(value));
9280 if (ret >= 0) {
9281 ALOGI("Setting vr mode to be %s", value);
9282 if (!strncmp(value, "true", 4)) {
9283 adev->vr_audio_mode_enabled = true;
9284 ALOGI("Setting vr mode to true");
9285 } else if (!strncmp(value, "false", 5)) {
9286 adev->vr_audio_mode_enabled = false;
9287 ALOGI("Setting vr mode to false");
9288 } else {
9289 ALOGI("wrong vr mode set");
9290 }
9291 }
9292
Eric Laurent4b084132018-10-19 17:33:43 -07009293 //FIXME: to be replaced by proper video capture properties API
9294 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
9295 if (ret >= 0) {
9296 int camera_facing = CAMERA_FACING_BACK;
9297 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
9298 camera_facing = CAMERA_FACING_FRONT;
9299 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
9300 camera_facing = CAMERA_FACING_BACK;
9301 else {
9302 ALOGW("%s: invalid camera facing value: %s", __func__, value);
9303 goto done;
9304 }
9305 adev->camera_orientation =
9306 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
9307 struct audio_usecase *usecase;
9308 struct listnode *node;
9309 list_for_each(node, &adev->usecase_list) {
9310 usecase = node_to_item(node, struct audio_usecase, list);
9311 struct stream_in *in = usecase->stream.in;
9312 if (usecase->type == PCM_CAPTURE && in != NULL &&
9313 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
9314 select_devices(adev, in->usecase);
9315 }
9316 }
9317 }
9318
Naresh Tannirucd2353e2016-08-19 00:37:25 +05309319 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08009320done:
9321 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009322 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05309323error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009324 ALOGV("%s: exit with code(%d)", __func__, status);
9325 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009326}
9327
9328static char* adev_get_parameters(const struct audio_hw_device *dev,
9329 const char *keys)
9330{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05309331 ALOGD("%s:%s", __func__, keys);
9332
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009333 struct audio_device *adev = (struct audio_device *)dev;
9334 struct str_parms *reply = str_parms_create();
9335 struct str_parms *query = str_parms_create_str(keys);
9336 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05309337 char value[256] = {0};
9338 int ret = 0;
9339
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009340 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08009341 if (reply) {
9342 str_parms_destroy(reply);
9343 }
9344 if (query) {
9345 str_parms_destroy(query);
9346 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009347 ALOGE("adev_get_parameters: failed to create query or reply");
9348 return NULL;
9349 }
9350
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009351 //handle vr audio getparam
9352
9353 ret = str_parms_get_str(query,
9354 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9355 value, sizeof(value));
9356
9357 if (ret >= 0) {
9358 bool vr_audio_enabled = false;
9359 pthread_mutex_lock(&adev->lock);
9360 vr_audio_enabled = adev->vr_audio_mode_enabled;
9361 pthread_mutex_unlock(&adev->lock);
9362
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07009363 ALOGV("getting vr mode to %d", vr_audio_enabled);
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009364
9365 if (vr_audio_enabled) {
9366 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9367 "true");
9368 goto exit;
9369 } else {
9370 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9371 "false");
9372 goto exit;
9373 }
9374 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009375
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009376 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009377 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08009378 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08009379 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009380 platform_get_parameters(adev->platform, query, reply);
justinwengd5395152019-11-04 12:23:09 +08009381 audio_extn_ma_get_parameters(adev, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05309382 pthread_mutex_unlock(&adev->lock);
9383
Naresh Tannirud7205b62014-06-20 02:54:48 +05309384exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009385 str = str_parms_to_str(reply);
9386 str_parms_destroy(query);
9387 str_parms_destroy(reply);
9388
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07009389 ALOGV("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009390 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009391}
9392
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009393static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009394{
9395 return 0;
9396}
9397
9398static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
9399{
Haynes Mathew George5191a852013-09-11 14:19:36 -07009400 int ret;
9401 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08009402
9403 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
9404
Haynes Mathew George5191a852013-09-11 14:19:36 -07009405 pthread_mutex_lock(&adev->lock);
9406 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07009407 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07009408 pthread_mutex_unlock(&adev->lock);
9409 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009410}
9411
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009412static int adev_set_master_volume(struct audio_hw_device *dev __unused,
9413 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009414{
9415 return -ENOSYS;
9416}
9417
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009418static int adev_get_master_volume(struct audio_hw_device *dev __unused,
9419 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009420{
9421 return -ENOSYS;
9422}
9423
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009424static int adev_set_master_mute(struct audio_hw_device *dev __unused,
9425 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009426{
9427 return -ENOSYS;
9428}
9429
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009430static int adev_get_master_mute(struct audio_hw_device *dev __unused,
9431 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009432{
9433 return -ENOSYS;
9434}
9435
9436static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
9437{
9438 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07009439 struct listnode *node;
9440 struct audio_usecase *usecase = NULL;
9441 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08009442
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009443 pthread_mutex_lock(&adev->lock);
9444 if (adev->mode != mode) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309445 ALOGD("%s: mode %d , prev_mode %d \n", __func__, mode , adev->mode);
9446 adev->prev_mode = adev->mode; /* prev_mode is kept to handle voip concurrency*/
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009447 adev->mode = mode;
Weiyin Jiang96b96f72020-09-22 16:48:19 +08009448 if (mode == AUDIO_MODE_CALL_SCREEN) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309449 adev->current_call_output = adev->primary_output;
9450 voice_start_call(adev);
9451 } else if (voice_is_in_call_or_call_screen(adev) &&
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08009452 (mode == AUDIO_MODE_NORMAL ||
9453 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07009454 list_for_each(node, &adev->usecase_list) {
9455 usecase = node_to_item(node, struct audio_usecase, list);
9456 if (usecase->type == VOICE_CALL)
9457 break;
9458 }
9459 if (usecase &&
9460 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
9461 ret = audio_extn_usb_check_and_set_svc_int(usecase,
9462 true);
9463 if (ret != 0) {
9464 /* default service interval was successfully updated,
9465 reopen USB backend with new service interval */
9466 check_usecases_codec_backend(adev,
9467 usecase,
9468 usecase->out_snd_device);
9469 }
9470 }
9471
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009472 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07009473 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009474 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08009475 // restore device for other active usecases after stop call
9476 list_for_each(node, &adev->usecase_list) {
9477 usecase = node_to_item(node, struct audio_usecase, list);
9478 select_devices(adev, usecase->id);
9479 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009480 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009481 }
9482 pthread_mutex_unlock(&adev->lock);
9483 return 0;
9484}
9485
9486static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
9487{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009488 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08009489 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009490
9491 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08009492 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009493 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009494
Derek Chend2530072014-11-24 12:39:14 -08009495 if (adev->ext_hw_plugin)
9496 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009497
9498 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009499 pthread_mutex_unlock(&adev->lock);
9500
9501 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009502}
9503
9504static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
9505{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009506 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009507 return 0;
9508}
9509
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009510static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009511 const struct audio_config *config)
9512{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009513 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009514
Aalique Grahame22e49102018-12-18 14:23:57 -08009515 /* Don't know if USB HIFI in this context so use true to be conservative */
9516 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9517 true /*is_usb_hifi */) != 0)
9518 return 0;
9519
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009520 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
9521 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009522}
9523
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009524static bool adev_input_allow_hifi_record(struct audio_device *adev,
9525 audio_devices_t devices,
9526 audio_input_flags_t flags,
9527 audio_source_t source) {
9528 const bool allowed = true;
9529
9530 if (!audio_is_usb_in_device(devices))
9531 return !allowed;
9532
9533 switch (flags) {
9534 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009535 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07009536 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
9537 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009538 default:
9539 return !allowed;
9540 }
9541
9542 switch (source) {
9543 case AUDIO_SOURCE_DEFAULT:
9544 case AUDIO_SOURCE_MIC:
9545 case AUDIO_SOURCE_UNPROCESSED:
9546 break;
9547 default:
9548 return !allowed;
9549 }
9550
9551 switch (adev->mode) {
9552 case 0:
9553 break;
9554 default:
9555 return !allowed;
9556 }
9557
9558 return allowed;
9559}
9560
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009561static int adev_update_voice_comm_input_stream(struct stream_in *in,
9562 struct audio_config *config)
9563{
9564 bool valid_rate = (config->sample_rate == 8000 ||
9565 config->sample_rate == 16000 ||
9566 config->sample_rate == 32000 ||
9567 config->sample_rate == 48000);
9568 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
9569
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009570 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08009571 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009572 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9573 in->config = default_pcm_config_voip_copp;
9574 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
9575 DEFAULT_VOIP_BUF_DURATION_MS,
9576 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009577 } else {
9578 ALOGW("%s No valid input in voip, use defaults"
9579 "sample rate %u, channel mask 0x%X",
9580 __func__, config->sample_rate, in->channel_mask);
9581 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009582 in->config.rate = config->sample_rate;
9583 in->sample_rate = config->sample_rate;
9584 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009585 //XXX needed for voice_extn_compress_voip_open_input_stream
9586 in->config.rate = config->sample_rate;
9587 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
Shalini Manjunathaa763cc42019-08-23 15:13:46 +05309588 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009589 voice_extn_compress_voip_is_active(in->dev)) &&
9590 (voice_extn_compress_voip_is_format_supported(in->format)) &&
9591 valid_rate && valid_ch) {
9592 voice_extn_compress_voip_open_input_stream(in);
9593 // update rate entries to match config from AF
9594 in->config.rate = config->sample_rate;
9595 in->sample_rate = config->sample_rate;
9596 } else {
9597 ALOGW("%s compress voip not active, use defaults", __func__);
9598 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009599 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009600 return 0;
9601}
9602
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009603static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07009604 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009605 audio_devices_t devices,
9606 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009607 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309608 audio_input_flags_t flags,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009609 const char *address,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009610 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009611{
9612 struct audio_device *adev = (struct audio_device *)dev;
9613 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009614 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009615 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009616 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05309617 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009618 bool is_usb_dev = audio_is_usb_in_device(devices);
9619 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
9620 devices,
9621 flags,
9622 source);
Andy Hung94320602018-10-29 18:31:12 -07009623 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
9624 " sample_rate %u, channel_mask %#x, format %#x",
9625 __func__, flags, is_usb_dev, may_use_hifi_record,
9626 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309627
kunleizdff872d2018-08-20 14:40:33 +08009628 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08009629 is_usb_dev = false;
9630 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
9631 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
9632 __func__, devices);
9633 }
9634
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009635 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009636
9637 if (!(is_usb_dev && may_use_hifi_record)) {
9638 if (config->sample_rate == 0)
9639 config->sample_rate = 48000;
9640 if (config->channel_mask == AUDIO_CHANNEL_NONE)
9641 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9642 if (config->format == AUDIO_FORMAT_DEFAULT)
9643 config->format = AUDIO_FORMAT_PCM_16_BIT;
9644
9645 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
9646
Aalique Grahame22e49102018-12-18 14:23:57 -08009647 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9648 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009649 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05309650 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009651
9652 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009653
9654 if (!in) {
9655 ALOGE("failed to allocate input stream");
9656 return -ENOMEM;
9657 }
9658
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309659 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05309660 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
9661 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009662 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07009663 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009664
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009665 in->stream.common.get_sample_rate = in_get_sample_rate;
9666 in->stream.common.set_sample_rate = in_set_sample_rate;
9667 in->stream.common.get_buffer_size = in_get_buffer_size;
9668 in->stream.common.get_channels = in_get_channels;
9669 in->stream.common.get_format = in_get_format;
9670 in->stream.common.set_format = in_set_format;
9671 in->stream.common.standby = in_standby;
9672 in->stream.common.dump = in_dump;
9673 in->stream.common.set_parameters = in_set_parameters;
9674 in->stream.common.get_parameters = in_get_parameters;
9675 in->stream.common.add_audio_effect = in_add_audio_effect;
9676 in->stream.common.remove_audio_effect = in_remove_audio_effect;
9677 in->stream.set_gain = in_set_gain;
9678 in->stream.read = in_read;
9679 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08009680 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309681 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07009682 in->stream.set_microphone_direction = in_set_microphone_direction;
9683 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07009684 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009685
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009686 list_init(&in->device_list);
9687 update_device_list(&in->device_list, devices, address, true);
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009688 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009689 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009690 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009691 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009692 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07009693 in->bit_width = 16;
9694 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07009695 in->direction = MIC_DIRECTION_UNSPECIFIED;
9696 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08009697 list_init(&in->aec_list);
9698 list_init(&in->ns_list);
Phil Burkd898ba62019-06-20 12:49:01 -07009699 in->mmap_shared_memory_fd = -1; // not open
Haynes Mathew George46740472017-10-27 18:40:12 -07009700
Andy Hung94320602018-10-29 18:31:12 -07009701 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08009702 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
9703 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
9704 /* Force channel config requested to mono if incall
9705 record is being requested for only uplink/downlink */
9706 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
9707 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9708 ret = -EINVAL;
9709 goto err_open;
9710 }
9711 }
9712
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009713 if (is_usb_dev && may_use_hifi_record) {
9714 /* HiFi record selects an appropriate format, channel, rate combo
9715 depending on sink capabilities*/
9716 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
9717 &config->format,
9718 &in->supported_formats[0],
9719 MAX_SUPPORTED_FORMATS,
9720 &config->channel_mask,
9721 &in->supported_channel_masks[0],
9722 MAX_SUPPORTED_CHANNEL_MASKS,
9723 &config->sample_rate,
9724 &in->supported_sample_rates[0],
9725 MAX_SUPPORTED_SAMPLE_RATES);
9726 if (ret != 0) {
9727 ret = -EINVAL;
9728 goto err_open;
9729 }
9730 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009731 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309732 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05309733 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
9734 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
9735 in->config.format = PCM_FORMAT_S32_LE;
9736 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309737 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
9738 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
9739 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
9740 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
9741 bool ret_error = false;
9742 in->bit_width = 24;
9743 /* 24 bit is restricted to UNPROCESSED source only,also format supported
9744 from HAL is 24_packed and 8_24
9745 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
9746 24_packed return error indicating supported format is 24_packed
9747 *> In case of any other source requesting 24 bit or float return error
9748 indicating format supported is 16 bit only.
9749
9750 on error flinger will retry with supported format passed
9751 */
9752 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
9753 (source != AUDIO_SOURCE_CAMCORDER)) {
9754 config->format = AUDIO_FORMAT_PCM_16_BIT;
9755 if (config->sample_rate > 48000)
9756 config->sample_rate = 48000;
9757 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07009758 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
9759 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309760 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
9761 ret_error = true;
9762 }
9763
9764 if (ret_error) {
9765 ret = -EINVAL;
9766 goto err_open;
9767 }
9768 }
9769
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009770 in->channel_mask = config->channel_mask;
9771 in->format = config->format;
9772
9773 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309774
Huicheng Liu1404ba12020-09-11 01:03:25 -04009775 /* validate bus device address */
9776 if (compare_device_type(&in->device_list, AUDIO_DEVICE_IN_BUS)) {
9777 /* extract car audio stream index */
9778 in->car_audio_stream =
9779 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
9780 if (in->car_audio_stream < 0) {
9781 ALOGE("%s: invalid car audio stream %x",
9782 __func__, in->car_audio_stream);
9783 ret = -EINVAL;
9784 goto err_open;
9785 }
9786 ALOGV("%s: car_audio_stream 0x%x", __func__, in->car_audio_stream);
Huicheng Liuea4fd422021-01-12 18:34:50 -05009787 ret = audio_extn_auto_hal_open_input_stream(in);
9788 if (ret) {
9789 ALOGE("%s: Failed to open input stream for bus device", __func__);
9790 ret = -EINVAL;
9791 goto err_open;
9792 }
Huicheng Liu1404ba12020-09-11 01:03:25 -04009793 }
9794
Susan Wange3959562021-03-11 11:50:26 -05009795 /* reassign use case for echo reference stream on automotive platforms */
9796 if (in->source == AUDIO_SOURCE_ECHO_REFERENCE) {
9797 ret = audio_extn_auto_hal_open_echo_reference_stream(in);
9798 }
9799
Kogara Naveen Kumar379ff692022-01-31 11:56:51 +05309800 if ((in->source == AUDIO_SOURCE_FM_TUNER) || (devices == AUDIO_DEVICE_IN_FM_TUNER)) {
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309801 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
9802 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
9803 else {
9804 ret = -EINVAL;
9805 goto err_open;
9806 }
9807 }
9808
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +05309809 if ((config->sample_rate == 48000 ||
9810 config->sample_rate == 32000 ||
9811 config->sample_rate == 24000 ||
9812 config->sample_rate == 16000 ||
9813 config->sample_rate == 8000)&&
Deeraj Somanfa377bf2019-02-06 12:57:59 +05309814 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
9815 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009816 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
9817 is_low_latency = true;
9818#if LOW_LATENCY_CAPTURE_USE_CASE
Revathi Uddarajud9f23d92020-07-27 10:55:06 +05309819 if ((flags & AUDIO_INPUT_FLAG_VOIP_TX) != 0)
9820 in->usecase = USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY;
9821 else
9822 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009823#endif
9824 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08009825 if (!in->realtime) {
9826 in->config = pcm_config_audio_capture;
9827 frame_size = audio_stream_in_frame_size(&in->stream);
9828 buffer_size = get_input_buffer_size(config->sample_rate,
9829 config->format,
9830 channel_count,
9831 is_low_latency);
9832 in->config.period_size = buffer_size / frame_size;
9833 in->config.rate = config->sample_rate;
9834 in->af_period_multiplier = 1;
9835 } else {
9836 // period size is left untouched for rt mode playback
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +05309837 switch(config->sample_rate)
9838 {
9839 case 48000:
9840 in->config = pcm_config_audio_capture_rt_48KHz;
9841 break;
9842 case 32000:
9843 in->config = pcm_config_audio_capture_rt_32KHz;
9844 break;
9845 case 24000:
9846 in->config = pcm_config_audio_capture_rt_24KHz;
9847 break;
9848 case 16000:
9849 in->config = pcm_config_audio_capture_rt_16KHz;
9850 break;
9851 case 8000:
9852 in->config = pcm_config_audio_capture_rt_8KHz;
9853 break;
9854 default:
9855 in->config = pcm_config_audio_capture_rt_48KHz;
9856 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009857 in->af_period_multiplier = af_period_multiplier;
9858 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009859 }
9860
Susan Wangb803cb52021-10-14 12:03:36 -04009861 /* Additional sample rates added below must also be present
9862 in audio_policy_configuration.xml for mmap_no_irq_in */
9863 bool valid_mmap_record_rate = (config->sample_rate == 8000 ||
9864 config->sample_rate == 16000 ||
Susan Wang89da9042021-10-14 12:03:36 -04009865 config->sample_rate == 24000 ||
Susan Wangb803cb52021-10-14 12:03:36 -04009866 config->sample_rate == 32000 ||
9867 config->sample_rate == 48000);
9868 if (valid_mmap_record_rate &&
9869 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009870 in->realtime = 0;
9871 in->usecase = USECASE_AUDIO_RECORD_MMAP;
9872 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07009873 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009874 in->stream.start = in_start;
9875 in->stream.stop = in_stop;
9876 in->stream.create_mmap_buffer = in_create_mmap_buffer;
9877 in->stream.get_mmap_position = in_get_mmap_position;
Ramjee Singhbcb3b6c2021-11-17 13:19:16 +05309878 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009879 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
Haynes Mathew George46740472017-10-27 18:40:12 -07009880 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009881 in->usecase = USECASE_AUDIO_RECORD_HIFI;
9882 in->config = pcm_config_audio_capture;
9883 frame_size = audio_stream_in_frame_size(&in->stream);
9884 buffer_size = get_input_buffer_size(config->sample_rate,
9885 config->format,
9886 channel_count,
9887 false /*is_low_latency*/);
9888 in->config.period_size = buffer_size / frame_size;
9889 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009890 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07009891 switch (config->format) {
9892 case AUDIO_FORMAT_PCM_32_BIT:
9893 in->bit_width = 32;
9894 break;
9895 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
9896 case AUDIO_FORMAT_PCM_8_24_BIT:
9897 in->bit_width = 24;
9898 break;
9899 default:
9900 in->bit_width = 16;
9901 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009902 } else if (is_single_device_type_equal(&in->device_list,
9903 AUDIO_DEVICE_IN_TELEPHONY_RX) ||
9904 is_single_device_type_equal(&in->device_list,
9905 AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009906 if (config->sample_rate == 0)
9907 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9908 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
9909 config->sample_rate != 8000) {
9910 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9911 ret = -EINVAL;
9912 goto err_open;
9913 }
9914 if (config->format == AUDIO_FORMAT_DEFAULT)
9915 config->format = AUDIO_FORMAT_PCM_16_BIT;
9916 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
9917 config->format = AUDIO_FORMAT_PCM_16_BIT;
9918 ret = -EINVAL;
9919 goto err_open;
9920 }
9921
9922 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
Zhou Song62ea0282020-03-22 19:53:01 +08009923 if (adev->ha_proxy_enable &&
9924 is_single_device_type_equal(&in->device_list,
9925 AUDIO_DEVICE_IN_TELEPHONY_RX))
9926 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY2;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009927 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009928 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08009929 in->af_period_multiplier = 1;
9930 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
Shalini Manjunathaac412b32020-01-03 15:00:14 +05309931 (!voice_extn_is_compress_voip_supported()) &&
Aalique Grahame22e49102018-12-18 14:23:57 -08009932 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
9933 (config->sample_rate == 8000 ||
9934 config->sample_rate == 16000 ||
9935 config->sample_rate == 32000 ||
9936 config->sample_rate == 48000) &&
9937 channel_count == 1) {
9938 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9939 in->config = pcm_config_audio_capture;
9940 frame_size = audio_stream_in_frame_size(&in->stream);
9941 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
9942 config->sample_rate,
9943 config->format,
9944 channel_count, false /*is_low_latency*/);
9945 in->config.period_size = buffer_size / frame_size;
9946 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
9947 in->config.rate = config->sample_rate;
9948 in->af_period_multiplier = 1;
Mingshu Pangc2d65042021-01-14 16:19:10 +08009949 } else if (in->realtime) {
9950 in->config = pcm_config_audio_capture_rt;
9951 in->config.format = pcm_format_from_audio_format(config->format);
9952 in->af_period_multiplier = af_period_multiplier;
Haynes Mathew George46740472017-10-27 18:40:12 -07009953 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05309954 int ret_val;
9955 pthread_mutex_lock(&adev->lock);
9956 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
9957 in, config, &channel_mask_updated);
9958 pthread_mutex_unlock(&adev->lock);
9959
9960 if (!ret_val) {
9961 if (channel_mask_updated == true) {
9962 ALOGD("%s: return error to retry with updated channel mask (%#x)",
9963 __func__, config->channel_mask);
9964 ret = -EINVAL;
9965 goto err_open;
9966 }
9967 ALOGD("%s: created multi-channel session succesfully",__func__);
9968 } else if (audio_extn_compr_cap_enabled() &&
9969 audio_extn_compr_cap_format_supported(config->format) &&
9970 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
9971 audio_extn_compr_cap_init(in);
9972 } else if (audio_extn_cin_applicable_stream(in)) {
Deeraj Soman14230922019-01-30 16:39:30 +05309973 ret = audio_extn_cin_configure_input_stream(in, config);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309974 if (ret)
9975 goto err_open;
9976 } else {
9977 in->config = pcm_config_audio_capture;
9978 in->config.rate = config->sample_rate;
9979 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309980 in->format = config->format;
9981 frame_size = audio_stream_in_frame_size(&in->stream);
9982 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07009983 config->format,
9984 channel_count,
9985 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02009986 /* prevent division-by-zero */
9987 if (frame_size == 0) {
9988 ALOGE("%s: Error frame_size==0", __func__);
9989 ret = -EINVAL;
9990 goto err_open;
9991 }
9992
Revathi Uddarajud2634032017-12-07 14:42:34 +05309993 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08009994 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009995
Revathi Uddarajud2634032017-12-07 14:42:34 +05309996 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9997 /* optionally use VOIP usecase depending on config(s) */
9998 ret = adev_update_voice_comm_input_stream(in, config);
9999 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -080010000
Revathi Uddarajud2634032017-12-07 14:42:34 +053010001 if (ret) {
10002 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
10003 goto err_open;
10004 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -080010005 }
Jaideep Sharmad305a4a2020-02-27 14:29:04 +053010006
10007 /* assign concurrent capture usecase if record has to caried out from
10008 * actual hardware input source */
10009 if (audio_extn_is_concurrent_capture_enabled() &&
10010 !audio_is_virtual_input_source(in->source)) {
Samyak Jainc37062f2019-04-25 18:41:06 +053010011 /* Acquire lock to avoid two concurrent use cases initialized to
10012 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +080010013
Samyak Jainc37062f2019-04-25 18:41:06 +053010014 if (in->usecase == USECASE_AUDIO_RECORD) {
10015 pthread_mutex_lock(&adev->lock);
10016 if (!(adev->pcm_record_uc_state)) {
10017 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
10018 adev->pcm_record_uc_state = 1;
10019 pthread_mutex_unlock(&adev->lock);
Krishna Kishor Jha0f4d8482022-02-18 10:56:05 +053010020 } else if (audio_extn_is_concurrent_pcm_record_enabled()) {
10021 in->usecase = get_record_usecase(adev);
10022 pthread_mutex_unlock(&adev->lock);
Samyak Jainc37062f2019-04-25 18:41:06 +053010023 } else {
10024 pthread_mutex_unlock(&adev->lock);
10025 /* Assign compress record use case for second record */
10026 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
10027 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
10028 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
10029 if (audio_extn_cin_applicable_stream(in)) {
10030 in->sample_rate = config->sample_rate;
Deeraj Soman14230922019-01-30 16:39:30 +053010031 ret = audio_extn_cin_configure_input_stream(in, config);
Samyak Jainc37062f2019-04-25 18:41:06 +053010032 if (ret)
10033 goto err_open;
10034 }
10035 }
10036 }
kunleiz28c73e72019-03-27 17:24:04 +080010037 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -070010038 }
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +053010039 if (in->realtime) {
10040 switch(config->sample_rate)
10041 {
10042 case 48000:
10043 in->config = pcm_config_audio_capture_rt_48KHz;
10044 break;
10045 case 32000:
10046 in->config = pcm_config_audio_capture_rt_32KHz;
10047 break;
10048 case 24000:
10049 in->config = pcm_config_audio_capture_rt_24KHz;
10050 break;
10051 case 16000:
10052 in->config = pcm_config_audio_capture_rt_16KHz;
10053 break;
10054 case 8000:
10055 in->config = pcm_config_audio_capture_rt_8KHz;
10056 break;
10057 default:
10058 in->config = pcm_config_audio_capture_rt_48KHz;
10059 }
10060 in->config.format = pcm_format_from_audio_format(config->format);
10061 in->af_period_multiplier = af_period_multiplier;
10062 }
10063
Ramjee Singh82fd0c12019-08-21 16:31:33 +053010064 if (audio_extn_ssr_get_stream() != in)
10065 in->config.channels = channel_count;
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -070010066
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -070010067 in->sample_rate = in->config.rate;
10068
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010069 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
10070 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010071 &in->device_list, flags, in->format,
Haynes Mathew George4ffef292017-11-21 15:08:02 -080010072 in->sample_rate, in->bit_width,
10073 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +053010074 register_format(in->format, in->supported_formats);
10075 register_channel_mask(in->channel_mask, in->supported_channel_masks);
10076 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010077
Dechen Chai22768452021-07-30 09:29:16 +053010078#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -080010079 in->error_log = error_log_create(
10080 ERROR_LOG_ENTRIES,
10081 1000000000 /* aggregate consecutive identical errors within one second */);
Dechen Chai22768452021-07-30 09:29:16 +053010082#endif
Aalique Grahame22e49102018-12-18 14:23:57 -080010083
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010084 /* This stream could be for sound trigger lab,
10085 get sound trigger pcm if present */
10086 audio_extn_sound_trigger_check_and_get_session(in);
10087
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010088 lock_input_stream(in);
10089 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
10090 pthread_mutex_lock(&adev->lock);
10091 in->card_status = adev->card_status;
10092 pthread_mutex_unlock(&adev->lock);
10093 pthread_mutex_unlock(&in->lock);
10094
Aalique Grahame22e49102018-12-18 14:23:57 -080010095 stream_app_type_cfg_init(&in->app_type_cfg);
10096
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010097 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -080010098
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010099 ret = io_streams_map_insert(adev, &in->stream.common,
10100 handle, AUDIO_PATCH_HANDLE_NONE);
10101 if (ret != 0)
10102 goto err_open;
10103
Susan Wang6dd13092021-01-25 10:27:11 -050010104 in->in_ctxt.input = in;
Derek Chenf939fb72018-11-13 13:34:41 -080010105
10106 pthread_mutex_lock(&adev->lock);
Susan Wang6dd13092021-01-25 10:27:11 -050010107 list_add_tail(&adev->active_inputs_list, &in->in_ctxt.list);
Derek Chenf939fb72018-11-13 13:34:41 -080010108 pthread_mutex_unlock(&adev->lock);
10109
Eric Laurent994a6932013-07-17 11:51:42 -070010110 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -080010111 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010112
10113err_open:
Krishna Kishor Jha0f4d8482022-02-18 10:56:05 +053010114 if (audio_extn_is_concurrent_pcm_record_enabled() && is_pcm_record_usecase(in->usecase)) {
10115 free_record_usecase(adev, in->usecase);
10116 } else if (in->usecase == USECASE_AUDIO_RECORD) {
Samyak Jainc37062f2019-04-25 18:41:06 +053010117 pthread_mutex_lock(&adev->lock);
10118 adev->pcm_record_uc_state = 0;
10119 pthread_mutex_unlock(&adev->lock);
10120 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010121 free(in);
10122 *stream_in = NULL;
10123 return ret;
10124}
10125
10126static void adev_close_input_stream(struct audio_hw_device *dev,
10127 struct audio_stream_in *stream)
10128{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080010129 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -070010130 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -070010131 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +053010132
Sidipotu Ashokf43018c2014-05-02 16:21:50 +053010133 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080010134
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010135 if (in == NULL) {
10136 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
10137 return;
10138 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010139 io_streams_map_remove(adev, in->capture_handle);
10140
Susan Wang6dd13092021-01-25 10:27:11 -050010141 // remove out_ctxt early to prevent the stream
10142 // being opened in a race condition
10143 pthread_mutex_lock(&adev->lock);
10144 list_remove(&in->in_ctxt.list);
10145 pthread_mutex_unlock(&adev->lock);
10146
kunleiz70e57612018-12-28 17:50:23 +080010147 /* must deregister from sndmonitor first to prevent races
10148 * between the callback and close_stream
10149 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010150 audio_extn_snd_mon_unregister_listener(stream);
10151
kunleiz70e57612018-12-28 17:50:23 +080010152 /* Disable echo reference if there are no active input, hfp call
10153 * and sound trigger while closing input stream
10154 */
Eric Laurent637e2d42018-11-15 12:24:31 -080010155 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +080010156 !audio_extn_hfp_is_active(adev) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010157 !audio_extn_sound_trigger_check_ec_ref_enable()) {
10158 struct listnode out_devices;
10159 list_init(&out_devices);
10160 platform_set_echo_reference(adev, false, &out_devices);
10161 } else
kunleiz70e57612018-12-28 17:50:23 +080010162 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +053010163
Dechen Chai22768452021-07-30 09:29:16 +053010164#ifndef LINUX_ENABLED
Weiyin Jiang2995f662019-04-17 14:25:12 +080010165 error_log_destroy(in->error_log);
10166 in->error_log = NULL;
Dechen Chai22768452021-07-30 09:29:16 +053010167#endif
Pallavid7c7a272018-01-16 11:22:55 +053010168
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080010169 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +053010170 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080010171 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +053010172 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080010173 if (ret != 0)
10174 ALOGE("%s: Compress voip input cannot be closed, error:%d",
10175 __func__, ret);
10176 } else
10177 in_standby(&stream->common);
10178
Weiyin Jiang280ea742020-09-08 20:28:22 +080010179 pthread_mutex_destroy(&in->lock);
10180 pthread_mutex_destroy(&in->pre_lock);
10181
Revathi Uddarajud2634032017-12-07 14:42:34 +053010182 pthread_mutex_lock(&adev->lock);
Krishna Kishor Jha0f4d8482022-02-18 10:56:05 +053010183 if (audio_extn_is_concurrent_pcm_record_enabled() && is_pcm_record_usecase(in->usecase)) {
10184 free_record_usecase(adev, in->usecase);
10185 } else if (in->usecase == USECASE_AUDIO_RECORD) {
Samyak Jain15fda662018-12-18 16:40:52 +053010186 adev->pcm_record_uc_state = 0;
10187 }
10188
Kunlei Zhang5d5d8d92020-02-26 15:00:59 +080010189 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
10190 adev->enable_voicerx = false;
10191 }
10192
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -070010193 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -070010194 audio_extn_ssr_deinit();
10195 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010196
Garmond Leunge2433c32017-09-28 21:51:22 -070010197 if (audio_extn_ffv_get_stream() == in) {
10198 audio_extn_ffv_stream_deinit();
10199 }
10200
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010201 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -070010202 audio_extn_compr_cap_format_supported(in->config.format))
10203 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +053010204
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +053010205 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +053010206 audio_extn_cin_free_input_stream_resources(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010207
Mingming Yinfd7607b2016-01-22 12:48:44 -080010208 if (in->is_st_session) {
10209 ALOGV("%s: sound trigger pcm stop lab", __func__);
10210 audio_extn_sound_trigger_stop_lab(in);
10211 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010212 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +053010213 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010214 return;
10215}
10216
Aalique Grahame22e49102018-12-18 14:23:57 -080010217/* verifies input and output devices and their capabilities.
10218 *
10219 * This verification is required when enabling extended bit-depth or
10220 * sampling rates, as not all qcom products support it.
10221 *
10222 * Suitable for calling only on initialization such as adev_open().
10223 * It fills the audio_device use_case_table[] array.
10224 *
10225 * Has a side-effect that it needs to configure audio routing / devices
10226 * in order to power up the devices and read the device parameters.
10227 * It does not acquire any hw device lock. Should restore the devices
10228 * back to "normal state" upon completion.
10229 */
10230static int adev_verify_devices(struct audio_device *adev)
10231{
10232 /* enumeration is a bit difficult because one really wants to pull
10233 * the use_case, device id, etc from the hidden pcm_device_table[].
10234 * In this case there are the following use cases and device ids.
10235 *
10236 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
10237 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
10238 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
10239 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
10240 * [USECASE_AUDIO_RECORD] = {0, 0},
10241 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
10242 * [USECASE_VOICE_CALL] = {2, 2},
10243 *
10244 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
10245 * USECASE_VOICE_CALL omitted, but possible for either input or output.
10246 */
10247
10248 /* should be the usecases enabled in adev_open_input_stream() */
10249 static const int test_in_usecases[] = {
10250 USECASE_AUDIO_RECORD,
10251 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
10252 };
10253 /* should be the usecases enabled in adev_open_output_stream()*/
10254 static const int test_out_usecases[] = {
10255 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
10256 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
10257 };
10258 static const usecase_type_t usecase_type_by_dir[] = {
10259 PCM_PLAYBACK,
10260 PCM_CAPTURE,
10261 };
10262 static const unsigned flags_by_dir[] = {
10263 PCM_OUT,
10264 PCM_IN,
10265 };
10266
10267 size_t i;
10268 unsigned dir;
10269 const unsigned card_id = adev->snd_card;
10270
10271 for (dir = 0; dir < 2; ++dir) {
10272 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
10273 const unsigned flags_dir = flags_by_dir[dir];
10274 const size_t testsize =
10275 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
10276 const int *testcases =
10277 dir ? test_in_usecases : test_out_usecases;
10278 const audio_devices_t audio_device =
10279 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
10280
10281 for (i = 0; i < testsize; ++i) {
10282 const audio_usecase_t audio_usecase = testcases[i];
10283 int device_id;
10284 struct pcm_params **pparams;
10285 struct stream_out out;
10286 struct stream_in in;
10287 struct audio_usecase uc_info;
10288 int retval;
10289
10290 pparams = &adev->use_case_table[audio_usecase];
10291 pcm_params_free(*pparams); /* can accept null input */
10292 *pparams = NULL;
10293
10294 /* find the device ID for the use case (signed, for error) */
10295 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
10296 if (device_id < 0)
10297 continue;
10298
10299 /* prepare structures for device probing */
10300 memset(&uc_info, 0, sizeof(uc_info));
10301 uc_info.id = audio_usecase;
10302 uc_info.type = usecase_type;
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010303 list_init(&uc_info.device_list);
Aalique Grahame22e49102018-12-18 14:23:57 -080010304 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -080010305 memset(&in, 0, sizeof(in));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010306 list_init(&in.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010307 update_device_list(&in.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -080010308 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
10309 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -080010310 }
10311 memset(&out, 0, sizeof(out));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010312 list_init(&out.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010313 update_device_list(&out.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -080010314 uc_info.stream.out = &out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010315 update_device_list(&uc_info.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -080010316 uc_info.in_snd_device = SND_DEVICE_NONE;
10317 uc_info.out_snd_device = SND_DEVICE_NONE;
10318 list_add_tail(&adev->usecase_list, &uc_info.list);
10319
10320 /* select device - similar to start_(in/out)put_stream() */
10321 retval = select_devices(adev, audio_usecase);
10322 if (retval >= 0) {
10323 *pparams = pcm_params_get(card_id, device_id, flags_dir);
10324#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -070010325 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -080010326 if (*pparams) {
10327 ALOGV("%s: (%s) card %d device %d", __func__,
10328 dir ? "input" : "output", card_id, device_id);
10329 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
10330 } else {
10331 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
10332 }
10333#endif
10334 }
10335
10336 /* deselect device - similar to stop_(in/out)put_stream() */
10337 /* 1. Get and set stream specific mixer controls */
10338 retval = disable_audio_route(adev, &uc_info);
10339 /* 2. Disable the rx device */
10340 retval = disable_snd_device(adev,
10341 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
10342 list_remove(&uc_info.list);
10343 }
10344 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010345 return 0;
10346}
10347
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010348int update_patch(unsigned int num_sources,
10349 const struct audio_port_config *sources,
10350 unsigned int num_sinks,
10351 const struct audio_port_config *sinks,
10352 audio_patch_handle_t handle,
10353 struct audio_patch_info *p_info,
10354 patch_type_t patch_type, bool new_patch)
10355{
Aniket Kumar Latad13758f2020-08-06 15:11:36 -070010356 ALOGV("%s: enter", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010357
10358 if (p_info == NULL) {
10359 ALOGE("%s: Invalid patch pointer", __func__);
10360 return -EINVAL;
10361 }
10362
10363 if (new_patch) {
10364 p_info->patch = (struct audio_patch *) calloc(1, sizeof(struct audio_patch));
10365 if (p_info->patch == NULL) {
10366 ALOGE("%s: Could not allocate patch", __func__);
10367 return -ENOMEM;
10368 }
10369 }
10370
10371 p_info->patch->id = handle;
10372 p_info->patch->num_sources = num_sources;
10373 p_info->patch->num_sinks = num_sinks;
10374
10375 for (int i = 0; i < num_sources; i++)
10376 p_info->patch->sources[i] = sources[i];
10377 for (int i = 0; i < num_sinks; i++)
10378 p_info->patch->sinks[i] = sinks[i];
10379
10380 p_info->patch_type = patch_type;
10381 return 0;
10382}
10383
10384audio_patch_handle_t generate_patch_handle()
10385{
10386 static audio_patch_handle_t patch_handle = AUDIO_PATCH_HANDLE_NONE;
10387 if (++patch_handle < 0)
10388 patch_handle = AUDIO_PATCH_HANDLE_NONE + 1;
10389 return patch_handle;
10390}
10391
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010392int adev_create_audio_patch(struct audio_hw_device *dev,
10393 unsigned int num_sources,
10394 const struct audio_port_config *sources,
10395 unsigned int num_sinks,
10396 const struct audio_port_config *sinks,
10397 audio_patch_handle_t *handle)
10398{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010399 int ret = 0;
10400 struct audio_device *adev = (struct audio_device *)dev;
10401 struct audio_patch_info *p_info = NULL;
10402 patch_type_t patch_type = PATCH_NONE;
10403 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10404 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
10405 struct audio_stream_info *s_info = NULL;
10406 struct audio_stream *stream = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010407 struct listnode devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010408 audio_devices_t device_type = AUDIO_DEVICE_NONE;
10409 bool new_patch = false;
10410 char addr[AUDIO_DEVICE_MAX_ADDRESS_LEN];
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010411
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010412 ALOGD("%s: enter: num sources %d, num_sinks %d, handle %d", __func__,
10413 num_sources, num_sinks, *handle);
10414
10415 if (num_sources == 0 || num_sources > AUDIO_PATCH_PORTS_MAX ||
10416 num_sinks == 0 || num_sinks > AUDIO_PATCH_PORTS_MAX) {
10417 ALOGE("%s: Invalid patch arguments", __func__);
10418 ret = -EINVAL;
10419 goto done;
10420 }
10421
10422 if (num_sources > 1) {
10423 ALOGE("%s: Multiple sources are not supported", __func__);
10424 ret = -EINVAL;
10425 goto done;
10426 }
10427
10428 if (sources == NULL || sinks == NULL) {
10429 ALOGE("%s: Invalid sources or sinks port config", __func__);
10430 ret = -EINVAL;
10431 goto done;
10432 }
10433
10434 ALOGV("%s: source role %d, source type %d", __func__,
10435 sources[0].type, sources[0].role);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010436 list_init(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010437
10438 // Populate source/sink information and fetch stream info
10439 switch (sources[0].type) {
10440 case AUDIO_PORT_TYPE_DEVICE: // Patch for audio capture or loopback
10441 device_type = sources[0].ext.device.type;
10442 strlcpy(&addr[0], &sources[0].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010443 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010444 if (sinks[0].type == AUDIO_PORT_TYPE_MIX) {
10445 patch_type = PATCH_CAPTURE;
10446 io_handle = sinks[0].ext.mix.handle;
10447 input_source = sinks[0].ext.mix.usecase.source;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010448 ALOGD("%s: Capture patch from device %x to mix %d",
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010449 __func__, device_type, io_handle);
10450 } else {
10451 // Device to device patch is not implemented.
10452 // This space will need changes if audio HAL
10453 // handles device to device patches in the future.
10454 patch_type = PATCH_DEVICE_LOOPBACK;
10455 }
10456 break;
10457 case AUDIO_PORT_TYPE_MIX: // Patch for audio playback
10458 io_handle = sources[0].ext.mix.handle;
10459 for (int i = 0; i < num_sinks; i++) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010460 device_type = sinks[i].ext.device.type;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010461 strlcpy(&addr[0], &sinks[i].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010462 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010463 }
10464 patch_type = PATCH_PLAYBACK;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010465 ALOGD("%s: Playback patch from mix handle %d to device %x",
10466 __func__, io_handle, get_device_types(&devices));
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010467 break;
10468 case AUDIO_PORT_TYPE_SESSION:
10469 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010470 ALOGE("%s: Unsupported source type %d", __func__, sources[0].type);
10471 ret = -EINVAL;
10472 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010473 }
10474
10475 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010476
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010477 // Generate patch info and update patch
10478 if (*handle == AUDIO_PATCH_HANDLE_NONE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010479 *handle = generate_patch_handle();
10480 p_info = (struct audio_patch_info *)
10481 calloc(1, sizeof(struct audio_patch_info));
10482 if (p_info == NULL) {
10483 ALOGE("%s: Failed to allocate memory", __func__);
10484 pthread_mutex_unlock(&adev->lock);
10485 ret = -ENOMEM;
10486 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010487 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010488 new_patch = true;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010489 } else {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010490 p_info = fetch_patch_info_l(adev, *handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010491 if (p_info == NULL) {
10492 ALOGE("%s: Unable to fetch patch for received patch handle %d",
10493 __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010494 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010495 ret = -EINVAL;
10496 goto done;
10497 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010498 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010499 update_patch(num_sources, sources, num_sinks, sinks,
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010500 *handle, p_info, patch_type, new_patch);
10501
10502 // Fetch stream info of associated mix for playback or capture patches
10503 if (p_info->patch_type == PATCH_PLAYBACK ||
10504 p_info->patch_type == PATCH_CAPTURE) {
10505 s_info = hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10506 if (s_info == NULL) {
10507 ALOGE("%s: Failed to obtain stream info", __func__);
10508 if (new_patch)
10509 free(p_info);
10510 pthread_mutex_unlock(&adev->lock);
10511 ret = -EINVAL;
10512 goto done;
10513 }
10514 ALOGV("%s: Fetched stream info with io_handle %d", __func__, io_handle);
10515 s_info->patch_handle = *handle;
10516 stream = s_info->stream;
10517 }
10518 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010519
10520 // Update routing for stream
10521 if (stream != NULL) {
Revathi Uddaraju4255a632021-12-02 05:11:13 -080010522 if (p_info->patch_type == PATCH_PLAYBACK) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010523 ret = route_output_stream((struct stream_out *) stream, &devices);
Revathi Uddaraju4255a632021-12-02 05:11:13 -080010524 clear_devices(&devices);
10525 } else if (p_info->patch_type == PATCH_CAPTURE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010526 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Revathi Uddaraju4255a632021-12-02 05:11:13 -080010527 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010528 if (ret < 0) {
10529 pthread_mutex_lock(&adev->lock);
10530 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10531 if (new_patch)
10532 free(p_info);
10533 pthread_mutex_unlock(&adev->lock);
10534 ALOGE("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10535 goto done;
10536 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010537 }
10538
10539 // Add new patch to patch map
10540 if (!ret && new_patch) {
10541 pthread_mutex_lock(&adev->lock);
10542 hashmapPut(adev->patch_map, (void *) (intptr_t) *handle, (void *) p_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010543 ALOGD("%s: Added a new patch with handle %d", __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010544 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010545 }
10546
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010547done:
10548 audio_extn_hw_loopback_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010549 num_sources,
10550 sources,
10551 num_sinks,
10552 sinks,
10553 handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010554 audio_extn_auto_hal_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010555 num_sources,
10556 sources,
10557 num_sinks,
10558 sinks,
10559 handle);
10560 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010561}
10562
10563int adev_release_audio_patch(struct audio_hw_device *dev,
10564 audio_patch_handle_t handle)
10565{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010566 struct audio_device *adev = (struct audio_device *) dev;
10567 int ret = 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010568 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010569 struct audio_stream *stream = NULL;
Derek Chenf939fb72018-11-13 13:34:41 -080010570
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010571 if (handle == AUDIO_PATCH_HANDLE_NONE) {
10572 ALOGE("%s: Invalid patch handle %d", __func__, handle);
10573 ret = -EINVAL;
10574 goto done;
10575 }
10576
10577 ALOGD("%s: Remove patch with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010578 pthread_mutex_lock(&adev->lock);
10579 struct audio_patch_info *p_info = fetch_patch_info_l(adev, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010580 if (p_info == NULL) {
10581 ALOGE("%s: Patch info not found with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010582 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010583 ret = -EINVAL;
10584 goto done;
10585 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010586 struct audio_patch *patch = p_info->patch;
10587 if (patch == NULL) {
10588 ALOGE("%s: Patch not found for handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010589 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010590 ret = -EINVAL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010591 goto done;
10592 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010593 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10594 switch (patch->sources[0].type) {
10595 case AUDIO_PORT_TYPE_MIX:
10596 io_handle = patch->sources[0].ext.mix.handle;
10597 break;
10598 case AUDIO_PORT_TYPE_DEVICE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010599 if (p_info->patch_type == PATCH_CAPTURE)
10600 io_handle = patch->sinks[0].ext.mix.handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010601 break;
10602 case AUDIO_PORT_TYPE_SESSION:
10603 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010604 pthread_mutex_unlock(&adev->lock);
10605 ret = -EINVAL;
10606 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010607 }
10608
10609 // Remove patch and reset patch handle in stream info
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010610 patch_type_t patch_type = p_info->patch_type;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010611 patch_map_remove_l(adev, handle);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010612 if (patch_type == PATCH_PLAYBACK ||
10613 patch_type == PATCH_CAPTURE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010614 struct audio_stream_info *s_info =
10615 hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10616 if (s_info == NULL) {
10617 ALOGE("%s: stream for io_handle %d is not available", __func__, io_handle);
10618 pthread_mutex_unlock(&adev->lock);
10619 goto done;
10620 }
10621 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10622 stream = s_info->stream;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010623 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010624 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010625
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010626 if (stream != NULL) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010627 struct listnode devices;
10628 list_init(&devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010629 if (patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010630 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010631 else if (patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010632 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010633 }
10634
10635 if (ret < 0)
10636 ALOGW("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10637
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010638done:
10639 audio_extn_hw_loopback_release_audio_patch(dev, handle);
10640 audio_extn_auto_hal_release_audio_patch(dev, handle);
10641
10642 ALOGV("%s: Successfully released patch %d", __func__, handle);
Derek Chenf939fb72018-11-13 13:34:41 -080010643 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010644}
10645
10646int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
10647{
Derek Chenf13dd492018-11-13 14:53:51 -080010648 int ret = 0;
10649
10650 ret = audio_extn_hw_loopback_get_audio_port(dev, config);
10651 ret |= audio_extn_auto_hal_get_audio_port(dev, config);
10652 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010653}
10654
10655int adev_set_audio_port_config(struct audio_hw_device *dev,
10656 const struct audio_port_config *config)
10657{
Derek Chenf13dd492018-11-13 14:53:51 -080010658 int ret = 0;
10659
10660 ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
10661 ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
10662 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010663}
10664
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -070010665static int adev_dump(const audio_hw_device_t *device __unused,
10666 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010667{
10668 return 0;
10669}
10670
10671static int adev_close(hw_device_t *device)
10672{
Aalique Grahame22e49102018-12-18 14:23:57 -080010673 size_t i;
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010674 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -070010675
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010676 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -070010677 return 0;
10678
10679 pthread_mutex_lock(&adev_init_lock);
10680
10681 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +053010682 if (audio_extn_spkr_prot_is_enabled())
10683 audio_extn_spkr_prot_deinit();
Jaideep Sharmaa2b49672019-09-10 20:37:03 +053010684 audio_extn_battery_properties_listener_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010685 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010686 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -080010687 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010688 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -080010689 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010690 audio_extn_utils_release_streams_cfg_lists(
10691 &adev->streams_output_cfg_list,
10692 &adev->streams_input_cfg_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010693 if (audio_extn_qap_is_enabled())
10694 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010695 if (audio_extn_qaf_is_enabled())
10696 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -070010697 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +080010698 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -070010699 free(adev->snd_dev_ref_cnt);
10700 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010701 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
10702 pcm_params_free(adev->use_case_table[i]);
10703 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010704 if (adev->adm_deinit)
10705 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010706 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010707 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010708 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010709 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010710 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010711 if (adev->device_cfg_params) {
10712 free(adev->device_cfg_params);
10713 adev->device_cfg_params = NULL;
10714 }
Derek Chend2530072014-11-24 12:39:14 -080010715 if(adev->ext_hw_plugin)
10716 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -080010717 audio_extn_auto_hal_deinit();
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010718 free_map(adev->patch_map);
10719 free_map(adev->io_streams_map);
Kiran Kandi910e1862013-10-29 13:29:42 -070010720 free(device);
10721 adev = NULL;
10722 }
10723 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +053010724 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010725 return 0;
10726}
10727
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010728/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
10729 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
10730 * just that it _might_ work.
10731 */
10732static int period_size_is_plausible_for_low_latency(int period_size)
10733{
10734 switch (period_size) {
10735 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -070010736 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010737 case 240:
10738 case 320:
10739 case 480:
10740 return 1;
10741 default:
10742 return 0;
10743 }
10744}
10745
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010746static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
10747{
10748 bool is_snd_card_status = false;
10749 bool is_ext_device_status = false;
10750 char value[32];
10751 int card = -1;
10752 card_status_t status;
10753
10754 if (cookie != adev || !parms)
10755 return;
10756
10757 if (!parse_snd_card_status(parms, &card, &status)) {
10758 is_snd_card_status = true;
10759 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
10760 is_ext_device_status = true;
10761 } else {
10762 // not a valid event
10763 return;
10764 }
10765
10766 pthread_mutex_lock(&adev->lock);
10767 if (card == adev->snd_card || is_ext_device_status) {
10768 if (is_snd_card_status && adev->card_status != status) {
Jaideep Sharmacb402512020-09-24 17:51:07 +053010769 ALOGD("%s card_status %d", __func__, status);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010770 adev->card_status = status;
10771 platform_snd_card_update(adev->platform, status);
10772 audio_extn_fm_set_parameters(adev, parms);
Derek Chend6f371d2019-03-01 13:45:58 -080010773 audio_extn_auto_hal_set_parameters(adev, parms);
Zhou Song4f43e352019-07-02 00:32:23 +080010774 if (status == CARD_STATUS_OFFLINE)
10775 audio_extn_sco_reset_configuration();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010776 } else if (is_ext_device_status) {
10777 platform_set_parameters(adev->platform, parms);
10778 }
10779 }
10780 pthread_mutex_unlock(&adev->lock);
10781 return;
10782}
10783
Weiyin Jiang280ea742020-09-08 20:28:22 +080010784/* adev lock held */
10785int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010786{
10787 struct audio_usecase *uc_info;
Zhou Song407e5aa2020-12-27 19:13:04 +080010788 struct audio_usecase *usecase;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010789 struct listnode devices;
Zhou Song407e5aa2020-12-27 19:13:04 +080010790 struct listnode *node;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010791
10792 uc_info = get_usecase_from_list(adev, out->usecase);
10793 if (uc_info == NULL) {
10794 ALOGE("%s: Could not find the usecase (%d) in the list",
10795 __func__, out->usecase);
10796 return -EINVAL;
10797 }
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010798 list_init(&devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010799
Zhou Songbaddf9f2020-11-20 13:57:39 +080010800 ALOGD("%s: enter: usecase(%d: %s), a2dp muted %d", __func__,
10801 out->usecase, use_case_table[out->usecase], out->a2dp_muted);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010802
10803 if (restore) {
Weiyin Jiang280ea742020-09-08 20:28:22 +080010804 pthread_mutex_lock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010805 // restore A2DP device for active usecases and unmute if required
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010806 if (is_a2dp_out_device_type(&out->device_list)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010807 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
Zhou Songe5225132019-09-26 15:33:36 +080010808 if (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)
10809 select_devices(adev, uc_info->id);
Zhou Songbaddf9f2020-11-20 13:57:39 +080010810
10811 if (is_offload_usecase(out->usecase)) {
10812 if (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)
Weiyin Jiang280ea742020-09-08 20:28:22 +080010813 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
Zhou Songbaddf9f2020-11-20 13:57:39 +080010814 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
10815 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
10816 } else {
10817 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010818 }
Zhou Songbaddf9f2020-11-20 13:57:39 +080010819 out->a2dp_muted = false;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010820 }
Weiyin Jiang280ea742020-09-08 20:28:22 +080010821 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010822 } else {
Weiyin Jiang280ea742020-09-08 20:28:22 +080010823 pthread_mutex_lock(&out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +080010824 // mute stream and switch to speaker if suspended
10825 if (!out->a2dp_muted && !out->standby) {
Zhou Songbaddf9f2020-11-20 13:57:39 +080010826 assign_devices(&devices, &out->device_list);
10827 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Zhou Song407e5aa2020-12-27 19:13:04 +080010828 list_for_each(node, &adev->usecase_list) {
10829 usecase = node_to_item(node, struct audio_usecase, list);
Zhou Songe63b6fe2021-04-15 13:54:46 +080010830 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
10831 !is_a2dp_out_device_type(&usecase->stream.out->device_list) &&
Zhou Songcf77af02021-05-14 18:21:14 +080010832 !is_sco_out_device_type(&usecase->stream.out->device_list) &&
Zhou Songe63b6fe2021-04-15 13:54:46 +080010833 platform_check_backends_match(SND_DEVICE_OUT_SPEAKER,
10834 usecase->out_snd_device)) {
Zhou Song407e5aa2020-12-27 19:13:04 +080010835 assign_devices(&out->device_list, &usecase->stream.out->device_list);
10836 break;
10837 }
10838 }
Zhou Songcf77af02021-05-14 18:21:14 +080010839 if ((is_a2dp_out_device_type(&devices) && list_length(&devices) == 1) ||
10840 (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)) {
Zhou Song8edbbdb2021-01-14 16:48:03 +080010841 out->a2dp_muted = true;
10842 if (is_offload_usecase(out->usecase)) {
10843 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10844 compress_pause(out->compr);
10845 out_set_compr_volume(&out->stream, (float)0, (float)0);
Zhou Song8edbbdb2021-01-14 16:48:03 +080010846 } else {
Weiyin Jiang906db3c2021-03-02 13:17:04 +080010847 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
10848 out_set_voip_volume(&out->stream, (float)0, (float)0);
10849 else
10850 out_set_pcm_volume(&out->stream, (float)0, (float)0);
10851
Zhou Song8edbbdb2021-01-14 16:48:03 +080010852 /* wait for stale pcm drained before switching to speaker */
10853 uint32_t latency =
10854 (out->config.period_count * out->config.period_size * 1000) /
10855 (out->config.rate);
10856 usleep(latency * 1000);
10857 }
Zhou Songbaddf9f2020-11-20 13:57:39 +080010858 }
10859 select_devices(adev, out->usecase);
Zhou Song8edbbdb2021-01-14 16:48:03 +080010860 ALOGD("%s: switched to device:%s and stream muted:%d", __func__,
10861 platform_get_snd_device_name(uc_info->out_snd_device), out->a2dp_muted);
Zhou Songbaddf9f2020-11-20 13:57:39 +080010862 if (is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010863 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10864 compress_resume(out->compr);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010865 }
Zhou Songbaddf9f2020-11-20 13:57:39 +080010866 assign_devices(&out->device_list, &devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010867 }
Weiyin Jiang280ea742020-09-08 20:28:22 +080010868 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010869 }
10870 ALOGV("%s: exit", __func__);
10871 return 0;
10872}
10873
Haynes Mathew George01156f92018-04-13 15:29:54 -070010874void adev_on_battery_status_changed(bool charging)
10875{
10876 pthread_mutex_lock(&adev->lock);
10877 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
10878 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +080010879 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -070010880 pthread_mutex_unlock(&adev->lock);
10881}
10882
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010883static int adev_open(const hw_module_t *module, const char *name,
10884 hw_device_t **device)
10885{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010886 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -080010887 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010888 char mixer_ctl_name[128] = {0};
10889 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010890
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080010891 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010892 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
10893
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010894 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -070010895 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010896 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -070010897 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010898 ALOGD("%s: returning existing instance of adev", __func__);
10899 ALOGD("%s: exit", __func__);
10900 pthread_mutex_unlock(&adev_init_lock);
10901 return 0;
10902 }
10903
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010904 adev = calloc(1, sizeof(struct audio_device));
10905
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -070010906 if (!adev) {
10907 pthread_mutex_unlock(&adev_init_lock);
10908 return -ENOMEM;
10909 }
10910
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -070010911 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
10912
Weiyin Jiange6ce6312019-01-28 18:28:22 +080010913 // register audio ext hidl at the earliest
10914 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053010915#ifdef DYNAMIC_LOG_ENABLED
10916 register_for_dynamic_logging("hal");
10917#endif
10918
Derek Chenf939fb72018-11-13 13:34:41 -080010919 /* default audio HAL major version */
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010920 uint32_t maj_version = 3;
Derek Chenf939fb72018-11-13 13:34:41 -080010921 if(property_get("vendor.audio.hal.maj.version", value, NULL))
10922 maj_version = atoi(value);
10923
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010924 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -080010925 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010926 adev->device.common.module = (struct hw_module_t *)module;
10927 adev->device.common.close = adev_close;
10928
10929 adev->device.init_check = adev_init_check;
10930 adev->device.set_voice_volume = adev_set_voice_volume;
10931 adev->device.set_master_volume = adev_set_master_volume;
10932 adev->device.get_master_volume = adev_get_master_volume;
10933 adev->device.set_master_mute = adev_set_master_mute;
10934 adev->device.get_master_mute = adev_get_master_mute;
10935 adev->device.set_mode = adev_set_mode;
10936 adev->device.set_mic_mute = adev_set_mic_mute;
10937 adev->device.get_mic_mute = adev_get_mic_mute;
10938 adev->device.set_parameters = adev_set_parameters;
10939 adev->device.get_parameters = adev_get_parameters;
10940 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
10941 adev->device.open_output_stream = adev_open_output_stream;
10942 adev->device.close_output_stream = adev_close_output_stream;
10943 adev->device.open_input_stream = adev_open_input_stream;
10944 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010945 adev->device.create_audio_patch = adev_create_audio_patch;
10946 adev->device.release_audio_patch = adev_release_audio_patch;
10947 adev->device.get_audio_port = adev_get_audio_port;
10948 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010949 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +053010950 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010951
10952 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010953 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -080010954 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010955 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010956 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -080010957 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -070010958 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +053010959 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -070010960 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -070010961 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -070010962 /* Init audio and voice feature */
10963 audio_extn_feature_init();
10964 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070010965 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -080010966 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -080010967 list_init(&adev->active_inputs_list);
10968 list_init(&adev->active_outputs_list);
Rahul Sharma99770982019-03-06 17:05:26 +053010969 list_init(&adev->audio_patch_record_list);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010970 adev->io_streams_map = hashmapCreate(AUDIO_IO_PORTS_MAX, audio_extn_utils_hash_fn,
10971 audio_extn_utils_hash_eq);
10972 if (!adev->io_streams_map) {
10973 ALOGE("%s: Could not create io streams map", __func__);
10974 ret = -ENOMEM;
10975 goto adev_open_err;
10976 }
10977 adev->patch_map = hashmapCreate(AUDIO_PATCH_PORTS_MAX, audio_extn_utils_hash_fn,
10978 audio_extn_utils_hash_eq);
10979 if (!adev->patch_map) {
10980 ALOGE("%s: Could not create audio patch map", __func__);
10981 ret = -ENOMEM;
10982 goto adev_open_err;
10983 }
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -080010984 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -070010985 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +053010986 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +053010987 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +053010988 adev->perf_lock_opts[0] = 0x101;
10989 adev->perf_lock_opts[1] = 0x20E;
10990 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010991 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -070010992 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010993 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010994 adev->adm_routing_changed = false;
Revathi Uddarajub26e3932020-06-10 14:51:02 +053010995 adev->a2dp_started = false;
Zhou Song503196b2021-07-23 17:31:05 +080010996 adev->ha_proxy_enable = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +053010997
Zhou Song68ebc352019-12-05 17:11:15 +080010998 audio_extn_perf_lock_init();
10999
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011000 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -070011001 adev->platform = platform_init(adev);
11002 if (!adev->platform) {
Eric Laurentb23d5282013-05-14 15:27:20 -070011003 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011004 ret = -EINVAL;
11005 goto adev_open_err;
Eric Laurentb23d5282013-05-14 15:27:20 -070011006 }
Eric Laurentc4aef752013-09-12 17:45:53 -070011007
Aalique Grahame22e49102018-12-18 14:23:57 -080011008 adev->extspk = audio_extn_extspk_init(adev);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053011009 if (audio_extn_qap_is_enabled()) {
11010 ret = audio_extn_qap_init(adev);
11011 if (ret < 0) {
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053011012 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011013 goto adev_open_err;
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053011014 }
11015 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
11016 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
11017 }
Aalique Grahame22e49102018-12-18 14:23:57 -080011018
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053011019 if (audio_extn_qaf_is_enabled()) {
11020 ret = audio_extn_qaf_init(adev);
11021 if (ret < 0) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053011022 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011023 goto adev_open_err;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053011024 }
11025
11026 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
11027 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
11028 }
11029
Derek Chenae7b0342019-02-08 15:17:04 -080011030 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -080011031 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
11032
Eric Laurentc4aef752013-09-12 17:45:53 -070011033 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
11034 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
11035 if (adev->visualizer_lib == NULL) {
11036 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
11037 } else {
11038 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
11039 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080011040 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070011041 "visualizer_hal_start_output");
11042 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080011043 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070011044 "visualizer_hal_stop_output");
11045 }
11046 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +053011047 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080011048 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -080011049 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +080011050 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +053011051 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070011052 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -070011053
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080011054 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
11055 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
11056 if (adev->offload_effects_lib == NULL) {
11057 ALOGE("%s: DLOPEN failed for %s", __func__,
11058 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
11059 } else {
11060 ALOGV("%s: DLOPEN successful for %s", __func__,
11061 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
11062 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +053011063 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080011064 "offload_effects_bundle_hal_start_output");
11065 adev->offload_effects_stop_output =
11066 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
11067 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080011068 adev->offload_effects_set_hpx_state =
11069 (int (*)(bool))dlsym(adev->offload_effects_lib,
11070 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +053011071 adev->offload_effects_get_parameters =
11072 (void (*)(struct str_parms *, struct str_parms *))
11073 dlsym(adev->offload_effects_lib,
11074 "offload_effects_bundle_get_parameters");
11075 adev->offload_effects_set_parameters =
11076 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
11077 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080011078 }
11079 }
11080
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070011081 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
11082 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
11083 if (adev->adm_lib == NULL) {
11084 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
11085 } else {
11086 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
11087 adev->adm_init = (adm_init_t)
11088 dlsym(adev->adm_lib, "adm_init");
11089 adev->adm_deinit = (adm_deinit_t)
11090 dlsym(adev->adm_lib, "adm_deinit");
11091 adev->adm_register_input_stream = (adm_register_input_stream_t)
11092 dlsym(adev->adm_lib, "adm_register_input_stream");
11093 adev->adm_register_output_stream = (adm_register_output_stream_t)
11094 dlsym(adev->adm_lib, "adm_register_output_stream");
11095 adev->adm_deregister_stream = (adm_deregister_stream_t)
11096 dlsym(adev->adm_lib, "adm_deregister_stream");
11097 adev->adm_request_focus = (adm_request_focus_t)
11098 dlsym(adev->adm_lib, "adm_request_focus");
11099 adev->adm_abandon_focus = (adm_abandon_focus_t)
11100 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -070011101 adev->adm_set_config = (adm_set_config_t)
11102 dlsym(adev->adm_lib, "adm_set_config");
11103 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
11104 dlsym(adev->adm_lib, "adm_request_focus_v2");
11105 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
11106 dlsym(adev->adm_lib, "adm_is_noirq_avail");
11107 adev->adm_on_routing_change = (adm_on_routing_change_t)
11108 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070011109 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
11110 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070011111 }
11112 }
11113
Aalique Grahame22e49102018-12-18 14:23:57 -080011114 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070011115 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +080011116 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Kunlei Zhanga3c4cb02021-03-05 16:03:54 +080011117 adev->fluence_nn_usecase_id = USECASE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -080011118 //initialize this to false for now,
11119 //this will be set to true through set param
11120 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070011121
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -070011122 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011123 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -080011124
11125 if (k_enable_extended_precision)
11126 adev_verify_devices(adev);
11127
Xiaojun Sang785b5da2017-08-03 15:52:29 +080011128 adev->dsp_bit_width_enforce_mode =
11129 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011130
Dhananjay Kumard6d32152016-10-13 16:11:03 +053011131 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
11132 &adev->streams_output_cfg_list,
11133 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070011134
Kiran Kandi910e1862013-10-29 13:29:42 -070011135 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070011136
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070011137 int trial;
Manisha Agarwalc75a0202019-12-06 18:48:25 +053011138 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070011139 trial = atoi(value);
11140 if (period_size_is_plausible_for_low_latency(trial)) {
11141 pcm_config_low_latency.period_size = trial;
11142 pcm_config_low_latency.start_threshold = trial / 4;
11143 pcm_config_low_latency.avail_min = trial / 4;
11144 configured_low_latency_capture_period_size = trial;
11145 }
11146 }
ronghuiz93177262021-04-21 19:58:13 +080011147 if (property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070011148 trial = atoi(value);
11149 if (period_size_is_plausible_for_low_latency(trial)) {
11150 configured_low_latency_capture_period_size = trial;
11151 }
11152 }
11153
Vignesh Kulothungan7d374312018-02-21 17:12:00 -080011154 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
11155
Eric Laurent4b084132018-10-19 17:33:43 -070011156 adev->camera_orientation = CAMERA_DEFAULT;
11157
Manisha Agarwalc75a0202019-12-06 18:48:25 +053011158 if (property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -070011159 af_period_multiplier = atoi(value);
11160 if (af_period_multiplier < 0)
11161 af_period_multiplier = 2;
11162 else if (af_period_multiplier > 4)
11163 af_period_multiplier = 4;
11164
11165 ALOGV("new period_multiplier = %d", af_period_multiplier);
11166 }
11167
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080011168 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080011169
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -070011170 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070011171 pthread_mutex_unlock(&adev_init_lock);
11172
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070011173 if (adev->adm_init)
11174 adev->adm_data = adev->adm_init();
11175
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053011176 qahwi_init(*device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080011177 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053011178
11179 audio_extn_snd_mon_init();
11180 pthread_mutex_lock(&adev->lock);
11181 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
11182 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -070011183 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
11184 /*
11185 * if the battery state callback happens before charging can be queried,
11186 * it will be guarded with the adev->lock held in the cb function and so
11187 * the callback value will reflect the latest state
11188 */
11189 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053011190 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +080011191 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -070011192 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +080011193 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053011194 /* Allocate memory for Device config params */
11195 adev->device_cfg_params = (struct audio_device_config_param*)
11196 calloc(platform_get_max_codec_backend(),
11197 sizeof(struct audio_device_config_param));
11198 if (adev->device_cfg_params == NULL)
11199 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053011200
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053011201 /*
11202 * Check if new PSPD matrix mixer control is supported. If not
11203 * supported, then set flag so that old mixer ctrl is sent while
11204 * sending pspd coefficients on older kernel version. Query mixer
11205 * control for default pcm id and channel value one.
11206 */
11207 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
11208 "AudStr %d ChMixer Weight Ch %d", 0, 1);
11209
11210 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
11211 if (!ctl) {
11212 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
11213 __func__, mixer_ctl_name);
11214 adev->use_old_pspd_mix_ctrl = true;
11215 }
11216
Jaideep Sharma0fa53812020-09-17 09:00:11 +053011217 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011218 return 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011219
11220adev_open_err:
11221 free_map(adev->patch_map);
11222 free_map(adev->io_streams_map);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080011223 free(adev->snd_dev_ref_cnt);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011224 pthread_mutex_destroy(&adev->lock);
11225 free(adev);
11226 adev = NULL;
11227 *device = NULL;
11228 pthread_mutex_unlock(&adev_init_lock);
11229 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011230}
11231
11232static struct hw_module_methods_t hal_module_methods = {
11233 .open = adev_open,
11234};
11235
11236struct audio_module HAL_MODULE_INFO_SYM = {
11237 .common = {
11238 .tag = HARDWARE_MODULE_TAG,
11239 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
11240 .hal_api_version = HARDWARE_HAL_API_VERSION,
11241 .id = AUDIO_HARDWARE_MODULE_ID,
11242 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -080011243 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011244 .methods = &hal_module_methods,
11245 },
11246};