blob: d6a56847b23779a4858570fe674613adc1a19840 [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.
Sandhya Mutha Naga Venkataa597a962023-02-07 11:35:51 +053036 *
sasevsdec27fa2023-04-12 10:50:47 +053037 * Changes from Qualcomm Innovation Center are provided under the following license:
Sandhya Mutha Naga Venkataa597a962023-02-07 11:35:51 +053038 * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
sasevsdec27fa2023-04-12 10:50:47 +053039 * SPDX-License-Identifier: BSD-3-Clause-Clear
40 *
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080041 */
42
43#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070044#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080045/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070046/*#define VERY_VERY_VERBOSE_LOGGING*/
47#ifdef VERY_VERY_VERBOSE_LOGGING
48#define ALOGVV ALOGV
49#else
50#define ALOGVV(a...) do { } while(0)
51#endif
George Gao3018ede2019-10-23 13:23:00 -070052#include <limits.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <errno.h>
54#include <pthread.h>
55#include <stdint.h>
56#include <sys/time.h>
57#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080058#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070059#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070060#include <sys/resource.h>
61#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080062
Aalique Grahame22e49102018-12-18 14:23:57 -080063#include <log/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070064#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080065#include <cutils/str_parms.h>
66#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070067#include <cutils/atomic.h>
68#include <cutils/sched_policy.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070069#include <hardware/audio_effect.h>
Haynes Mathew George484e8d22017-07-31 18:55:17 -070070#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070071#include <system/thread_defs.h>
Haynes Mathew George16081042017-05-31 17:16:49 -070072#include <tinyalsa/asoundlib.h>
Andy Hunga1f48fa2019-07-01 18:14:53 -070073#include <utils/Timers.h> // systemTime
Eric Laurentb23d5282013-05-14 15:27:20 -070074#include <audio_effects/effect_aec.h>
75#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053076#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080077#include "audio_hw.h"
Wei Wangf7ca6c92017-11-21 14:51:20 -080078#include "audio_perf.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070079#include "platform_api.h"
80#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070081#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080082#include "voice_extn.h"
Ashish Jaind5694242017-09-05 20:09:06 +053083#include "ip_hdlr_intf.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080084
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070085#include "sound/compress_params.h"
Xiaojun Sang782e5b12020-06-29 21:13:06 +080086
87#ifdef AUDIO_GKI_ENABLED
88#include "sound/audio_compressed_formats.h"
89#endif
90
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080091#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080092
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053093#ifdef DYNAMIC_LOG_ENABLED
94#include <log_xml_parser.h>
95#define LOG_MASK HAL_MOD_FILE_AUDIO_HW
96#include <log_utils.h>
97#endif
98
Krishna Kishor Jhaaf83fd82022-11-15 17:54:07 +053099#define SKIP_INPUT_SOURCE_PRIORITY
100
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700101#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +0530102/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
103#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700104#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700105#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Arun Mirpuri5d170872019-03-26 13:21:31 -0700106#define MMAP_PLAYBACK_VOLUME_MAX 0x2000
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530107#define PCM_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530108#define DSD_VOLUME_MIN_DB (-110)
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700109#define INVALID_OUT_VOLUME -1
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700110#define AUDIO_IO_PORTS_MAX 32
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700111
Zhou Songbaddf9f2020-11-20 13:57:39 +0800112#define PLAYBACK_GAIN_MAX 1.0f
Aalique Grahame22e49102018-12-18 14:23:57 -0800113#define RECORD_GAIN_MIN 0.0f
114#define RECORD_GAIN_MAX 1.0f
115#define RECORD_VOLUME_CTL_MAX 0x2000
116
117/* treat as unsigned Q1.13 */
118#define APP_TYPE_GAIN_DEFAULT 0x2000
119
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700120#define PROXY_OPEN_RETRY_COUNT 100
121#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800122
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800123#define GET_USECASE_AUDIO_PLAYBACK_PRIMARY(db) \
124 (db)? USECASE_AUDIO_PLAYBACK_DEEP_BUFFER : \
125 USECASE_AUDIO_PLAYBACK_LOW_LATENCY
126#define GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(db) \
127 (db)? pcm_config_deep_buffer : pcm_config_low_latency
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800128
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700129#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700130#define DEFAULT_VOIP_BUF_DURATION_MS 20
131#define DEFAULT_VOIP_BIT_DEPTH_BYTE sizeof(int16_t)
132#define DEFAULT_VOIP_SAMP_RATE 48000
133
134#define VOIP_IO_BUF_SIZE(SR, DURATION_MS, BIT_DEPTH) (SR)/1000 * DURATION_MS * BIT_DEPTH
135
136struct pcm_config default_pcm_config_voip_copp = {
137 .channels = 1,
138 .rate = DEFAULT_VOIP_SAMP_RATE, /* changed when the stream is opened */
139 .period_size = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
140 .period_count = 2,
141 .format = PCM_FORMAT_S16_LE,
kunleiz95b597a2017-10-23 17:07:33 +0800142 .avail_min = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
143 .stop_threshold = INT_MAX,
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700144};
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700145
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700146#define MIN_CHANNEL_COUNT 1
147#define DEFAULT_CHANNEL_COUNT 2
148#define MAX_HIFI_CHANNEL_COUNT 8
149
Aalique Grahame22e49102018-12-18 14:23:57 -0800150#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
151#define MAX_CHANNEL_COUNT 1
152#else
153#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
154#define XSTR(x) STR(x)
155#define STR(x) #x
156#endif
157
Avinash Chandrad7296d42021-08-04 15:07:47 +0530158#define IS_USB_HIFI (MAX_HIFI_CHANNEL_COUNT >= MAX_CHANNEL_COUNT) ? \
159 true : false
160
Dechen Chai22768452021-07-30 09:29:16 +0530161#ifdef LINUX_ENABLED
162static inline int64_t audio_utils_ns_from_timespec(const struct timespec *ts)
163{
164 return ts->tv_sec * 1000000000LL + ts->tv_nsec;
165}
166#endif
167
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700168static unsigned int configured_low_latency_capture_period_size =
169 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
170
Haynes Mathew George16081042017-05-31 17:16:49 -0700171#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
172#define MMAP_PERIOD_COUNT_MIN 32
173#define MMAP_PERIOD_COUNT_MAX 512
174#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
175
Aalique Grahame22e49102018-12-18 14:23:57 -0800176/* This constant enables extended precision handling.
177 * TODO The flag is off until more testing is done.
178 */
179static const bool k_enable_extended_precision = false;
Arun Mirpurie008ed22019-03-21 11:21:04 -0700180extern int AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Aalique Grahame22e49102018-12-18 14:23:57 -0800181
Eric Laurentb23d5282013-05-14 15:27:20 -0700182struct pcm_config pcm_config_deep_buffer = {
183 .channels = 2,
184 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
185 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
186 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
187 .format = PCM_FORMAT_S16_LE,
188 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
189 .stop_threshold = INT_MAX,
190 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
191};
192
193struct pcm_config pcm_config_low_latency = {
194 .channels = 2,
195 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
196 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
197 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
198 .format = PCM_FORMAT_S16_LE,
199 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
200 .stop_threshold = INT_MAX,
201 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
202};
203
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800204struct pcm_config pcm_config_haptics_audio = {
205 .channels = 1,
206 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
207 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
208 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
209 .format = PCM_FORMAT_S16_LE,
210 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
211 .stop_threshold = INT_MAX,
212 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
213};
214
215struct pcm_config pcm_config_haptics = {
216 .channels = 1,
217 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
218 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
219 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
220 .format = PCM_FORMAT_S16_LE,
221 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
222 .stop_threshold = INT_MAX,
223 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
224};
225
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700226static int af_period_multiplier = 4;
227struct pcm_config pcm_config_rt = {
228 .channels = 2,
229 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
230 .period_size = ULL_PERIOD_SIZE, //1 ms
231 .period_count = 512, //=> buffer size is 512ms
232 .format = PCM_FORMAT_S16_LE,
233 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
234 .stop_threshold = INT_MAX,
235 .silence_threshold = 0,
236 .silence_size = 0,
237 .avail_min = ULL_PERIOD_SIZE, //1 ms
238};
239
Eric Laurentb23d5282013-05-14 15:27:20 -0700240struct pcm_config pcm_config_hdmi_multi = {
241 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
242 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
243 .period_size = HDMI_MULTI_PERIOD_SIZE,
244 .period_count = HDMI_MULTI_PERIOD_COUNT,
245 .format = PCM_FORMAT_S16_LE,
246 .start_threshold = 0,
247 .stop_threshold = INT_MAX,
248 .avail_min = 0,
249};
250
Haynes Mathew George16081042017-05-31 17:16:49 -0700251struct pcm_config pcm_config_mmap_playback = {
252 .channels = 2,
253 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
254 .period_size = MMAP_PERIOD_SIZE,
255 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
256 .format = PCM_FORMAT_S16_LE,
257 .start_threshold = MMAP_PERIOD_SIZE*8,
258 .stop_threshold = INT32_MAX,
259 .silence_threshold = 0,
260 .silence_size = 0,
261 .avail_min = MMAP_PERIOD_SIZE, //1 ms
262};
263
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700264struct pcm_config pcm_config_hifi = {
265 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
266 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
267 .period_size = HIFI_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
268 .period_count = HIFI_BUFFER_OUTPUT_PERIOD_COUNT,
269 .format = PCM_FORMAT_S24_3LE,
270 .start_threshold = 0,
271 .stop_threshold = INT_MAX,
272 .avail_min = 0,
273};
274
Eric Laurentb23d5282013-05-14 15:27:20 -0700275struct pcm_config pcm_config_audio_capture = {
276 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700277 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
278 .format = PCM_FORMAT_S16_LE,
279};
280
Haynes Mathew George16081042017-05-31 17:16:49 -0700281struct pcm_config pcm_config_mmap_capture = {
282 .channels = 2,
283 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
284 .period_size = MMAP_PERIOD_SIZE,
285 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
286 .format = PCM_FORMAT_S16_LE,
287 .start_threshold = 0,
288 .stop_threshold = INT_MAX,
289 .silence_threshold = 0,
290 .silence_size = 0,
291 .avail_min = MMAP_PERIOD_SIZE, //1 ms
292};
293
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700294#define AFE_PROXY_CHANNEL_COUNT 2
295#define AFE_PROXY_SAMPLING_RATE 48000
296
297#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
298#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
299
300struct pcm_config pcm_config_afe_proxy_playback = {
301 .channels = AFE_PROXY_CHANNEL_COUNT,
302 .rate = AFE_PROXY_SAMPLING_RATE,
303 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
304 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
305 .format = PCM_FORMAT_S16_LE,
306 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
307 .stop_threshold = INT_MAX,
308 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
309};
310
311#define AFE_PROXY_RECORD_PERIOD_SIZE 768
312#define AFE_PROXY_RECORD_PERIOD_COUNT 4
313
Aalique Grahame22e49102018-12-18 14:23:57 -0800314struct pcm_config pcm_config_audio_capture_rt = {
315 .channels = 2,
316 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
317 .period_size = ULL_PERIOD_SIZE,
318 .period_count = 512,
319 .format = PCM_FORMAT_S16_LE,
320 .start_threshold = 0,
321 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
322 .silence_threshold = 0,
323 .silence_size = 0,
324 .avail_min = ULL_PERIOD_SIZE, //1 ms
325};
326
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +0530327struct pcm_config pcm_config_audio_capture_rt_48KHz = {
328 .channels = 2,
329 .rate = 48000,
330 .period_size = 48,
331 .period_count = 512,
332 .format = PCM_FORMAT_S16_LE,
333 .start_threshold = 0,
334 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
335 .silence_threshold = 0,
336 .silence_size = 0,
337 .avail_min = 48, //1 ms
338};
339struct pcm_config pcm_config_audio_capture_rt_32KHz = {
340 .channels = 2,
341 .rate = 32000,
342 .period_size = 32,
343 .period_count = 512,
344 .format = PCM_FORMAT_S16_LE,
345 .start_threshold = 0,
346 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
347 .silence_threshold = 0,
348 .silence_size = 0,
349 .avail_min = 32, //1 ms
350};
351struct pcm_config pcm_config_audio_capture_rt_24KHz = {
352 .channels = 2,
353 .rate = 24000,
354 .period_size = 24,
355 .period_count = 512,
356 .format = PCM_FORMAT_S16_LE,
357 .start_threshold = 0,
358 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
359 .silence_threshold = 0,
360 .silence_size = 0,
361 .avail_min = 24, //1 ms
362};
363struct pcm_config pcm_config_audio_capture_rt_16KHz = {
364 .channels = 2,
365 .rate = 16000,
366 .period_size = 16,
367 .period_count = 512,
368 .format = PCM_FORMAT_S16_LE,
369 .start_threshold = 0,
370 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
371 .silence_threshold = 0,
372 .silence_size = 0,
373 .avail_min = 16, //1 ms
374};
375struct pcm_config pcm_config_audio_capture_rt_8KHz = {
376 .channels = 2,
377 .rate = 8000,
378 .period_size = 8,
379 .period_count = 512,
380 .format = PCM_FORMAT_S16_LE,
381 .start_threshold = 0,
382 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
383 .silence_threshold = 0,
384 .silence_size = 0,
385 .avail_min = 8, //1 ms
386};
387
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700388struct pcm_config pcm_config_afe_proxy_record = {
389 .channels = AFE_PROXY_CHANNEL_COUNT,
390 .rate = AFE_PROXY_SAMPLING_RATE,
391 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
392 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
393 .format = PCM_FORMAT_S16_LE,
394 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
395 .stop_threshold = INT_MAX,
396 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
397};
398
Ashish Jainf1eaa582016-05-23 20:54:24 +0530399#define AUDIO_MAX_PCM_FORMATS 7
400
401const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
402 [AUDIO_FORMAT_DEFAULT] = 0,
403 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
404 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
405 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
406 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
407 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
408 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
409};
410
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800411const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700412 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
413 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800414 [USECASE_AUDIO_PLAYBACK_WITH_HAPTICS] = "audio-with-haptics-playback",
Meng Wang51d8c2a2020-04-27 15:23:21 +0800415 [USECASE_AUDIO_PLAYBACK_HAPTICS] = "haptics-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700416 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
417 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700418 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700419 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700420 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
421 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
422 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
423 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
424 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
425 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
426 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
427 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
Haynes Mathew George16081042017-05-31 17:16:49 -0700428 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
429 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700430 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Aalique Grahame22e49102018-12-18 14:23:57 -0800431 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
vivek mehta0ea887a2015-08-26 14:01:20 -0700432
Eric Laurentb23d5282013-05-14 15:27:20 -0700433 [USECASE_AUDIO_RECORD] = "audio-record",
Krishna Kishor Jha0f4d8482022-02-18 10:56:05 +0530434 [USECASE_AUDIO_RECORD2] = "audio-record2",
435 [USECASE_AUDIO_RECORD3] = "audio-record3",
Mingming Yine62d7842013-10-25 16:26:03 -0700436 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530437 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
438 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
439 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Dhananjay Kumar376e38b2017-09-28 22:26:23 +0530440 [USECASE_AUDIO_RECORD_COMPRESS5] = "audio-record-compress5",
441 [USECASE_AUDIO_RECORD_COMPRESS6] = "audio-record-compress6",
Eric Laurentb23d5282013-05-14 15:27:20 -0700442 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Kogara Naveen Kumarc5758232022-11-07 20:25:40 +0530443 [USECASE_AUDIO_RECORD_LOW_LATENCY2] = "low-latency-record2",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700444 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700445 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700446 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700447
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800448 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800449 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Derek Chenf7092792017-05-23 12:23:53 -0400450 [USECASE_AUDIO_HFP_SCO_DOWNLINK] = "hfp-sco-downlink",
451 [USECASE_AUDIO_HFP_SCO_WB_DOWNLINK] = "hfp-sco-wb-downlink",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700452
Derek Chenf7092792017-05-23 12:23:53 -0400453 [USECASE_VOICE_CALL] = "voice-call",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700454 [USECASE_VOICE2_CALL] = "voice2-call",
455 [USECASE_VOLTE_CALL] = "volte-call",
456 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800457 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800458 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
459 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800460 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700461 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
462 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
463 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800464 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
465 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
466 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
467
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700468 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
469 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700470 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
471 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700472
473 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
474 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Zhou Song62ea0282020-03-22 19:53:01 +0800475 [USECASE_AUDIO_RECORD_AFE_PROXY2] = "afe-proxy-record2",
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +0530476 [USECASE_AUDIO_PLAYBACK_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700477
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530478 /* Transcode loopback cases */
Surendar Karka93cd25a2018-08-28 14:21:37 +0530479 [USECASE_AUDIO_TRANSCODE_LOOPBACK_RX] = "audio-transcode-loopback-rx",
480 [USECASE_AUDIO_TRANSCODE_LOOPBACK_TX] = "audio-transcode-loopback-tx",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700481
482 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
483 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Revathi Uddarajud9f23d92020-07-27 10:55:06 +0530484 [USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY] = "audio-record-voip-low-latency",
Varun Balaraje49253e2017-07-06 19:48:56 +0530485 /* For Interactive Audio Streams */
486 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
487 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
488 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
489 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
490 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
491 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
492 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
493 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700494
Aniket Kumar Lata7fd86e12018-02-20 19:26:10 -0800495 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture",
496
Derek Chenf6318be2017-06-12 17:16:24 -0400497 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
498
499 [USECASE_AUDIO_PLAYBACK_MEDIA] = "media-playback",
Kogara Naveen Kumarc5758232022-11-07 20:25:40 +0530500 [USECASE_AUDIO_PLAYBACK_MEDIA_LL] = "media-playback-ll",
Derek Chenf6318be2017-06-12 17:16:24 -0400501 [USECASE_AUDIO_PLAYBACK_SYS_NOTIFICATION] = "sys-notification-playback",
502 [USECASE_AUDIO_PLAYBACK_NAV_GUIDANCE] = "nav-guidance-playback",
Kogara Naveen Kumarc5758232022-11-07 20:25:40 +0530503 [USECASE_AUDIO_PLAYBACK_NAV_GUIDANCE_LL] = "nav-guidance-playback-ll",
Derek Chenf6318be2017-06-12 17:16:24 -0400504 [USECASE_AUDIO_PLAYBACK_PHONE] = "phone-playback",
Kogara Naveen Kumar65828fe2022-10-14 16:41:04 +0530505 [USECASE_AUDIO_PLAYBACK_PHONE_LL] = "phone-playback-ll",
Susan Wang117cf6f2022-04-06 20:11:46 -0400506 [USECASE_AUDIO_PLAYBACK_ALERTS] = "alerts-playback",
Kogara Naveen Kumarc5758232022-11-07 20:25:40 +0530507 [USECASE_AUDIO_PLAYBACK_ALERTS_LL] = "alerts-playback-ll",
Derek Chen1bcdc6b2020-02-06 22:44:53 -0800508 [USECASE_AUDIO_PLAYBACK_FRONT_PASSENGER] = "front-passenger-playback",
Derek Chendf05eea2019-08-01 13:57:49 -0700509 [USECASE_AUDIO_PLAYBACK_REAR_SEAT] = "rear-seat-playback",
Rahul Sharma99770982019-03-06 17:05:26 +0530510 [USECASE_AUDIO_FM_TUNER_EXT] = "fm-tuner-ext",
Derek Chena30a5f42019-12-03 11:17:09 -0500511 [USECASE_ICC_CALL] = "icc-call",
Huicheng Liu1404ba12020-09-11 01:03:25 -0400512
513 [USECASE_AUDIO_RECORD_BUS] = "audio-record",
514 [USECASE_AUDIO_RECORD_BUS_FRONT_PASSENGER] = "front-passenger-record",
515 [USECASE_AUDIO_RECORD_BUS_REAR_SEAT] = "rear-seat-record",
Fei Tongaffdf732020-02-20 20:39:05 +0800516 [USECASE_AUDIO_PLAYBACK_SYNTHESIZER] = "synth-loopback",
Susan Wange3959562021-03-11 11:50:26 -0500517 [USECASE_AUDIO_RECORD_ECHO_REF_EXT] = "echo-reference-external",
Eric Laurentb23d5282013-05-14 15:27:20 -0700518};
519
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700520static const audio_usecase_t offload_usecases[] = {
521 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700522 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
523 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
524 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
525 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
526 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
527 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
528 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
529 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700530};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800531
Varun Balaraje49253e2017-07-06 19:48:56 +0530532static const audio_usecase_t interactive_usecases[] = {
533 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
534 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
535 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
536 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
537 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
538 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
539 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
540 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
541};
542
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800543#define STRING_TO_ENUM(string) { #string, string }
544
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800545struct string_to_enum {
546 const char *name;
547 uint32_t value;
548};
549
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700550static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800551 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800552 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
553 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
554 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700555 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800556 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
557 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800558 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700559 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
560 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
561 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
562 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
563 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
564 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
565 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
566 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
567 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
568 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
569 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800570};
571
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700572static const struct string_to_enum formats_name_to_enum_table[] = {
573 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
574 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
575 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700576 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
577 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
578 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700579 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800580 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
581 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700582 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800583};
584
585//list of all supported sample rates by HDMI specification.
586static const int out_hdmi_sample_rates[] = {
587 32000, 44100, 48000, 88200, 96000, 176400, 192000,
588};
589
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700590static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800591 STRING_TO_ENUM(32000),
592 STRING_TO_ENUM(44100),
593 STRING_TO_ENUM(48000),
594 STRING_TO_ENUM(88200),
595 STRING_TO_ENUM(96000),
596 STRING_TO_ENUM(176400),
597 STRING_TO_ENUM(192000),
Mingshu pange8aedf12019-10-25 15:38:27 +0800598 STRING_TO_ENUM(352800),
599 STRING_TO_ENUM(384000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700600};
601
Carter Hsu2e429db2019-05-14 18:50:52 +0800602struct in_effect_list {
603 struct listnode list;
604 effect_handle_t handle;
605};
606
Krishna Kishor Jha0f4d8482022-02-18 10:56:05 +0530607static const audio_usecase_t record_usecases[] = {
608 USECASE_AUDIO_RECORD,
609 USECASE_AUDIO_RECORD2,
610 USECASE_AUDIO_RECORD3,
611};
612
Kogara Naveen Kumarc5758232022-11-07 20:25:40 +0530613static const audio_usecase_t low_latency_record_usecases[] = {
614 USECASE_AUDIO_RECORD_LOW_LATENCY,
615 USECASE_AUDIO_RECORD_LOW_LATENCY2,
616};
617
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700618static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700619static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700620static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700621//cache last MBDRC cal step level
622static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700623
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530624static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Arun Mirpuri5d170872019-03-26 13:21:31 -0700625static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800626static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530627static int out_set_pcm_volume(struct audio_stream_out *stream, float left, float right);
Krishna Kishor Jha10ad39f2022-02-21 17:02:47 +0530628#ifdef SOFT_VOLUME
629static int out_set_soft_volume_params(struct audio_stream_out *stream);
630#endif
Derek Chen6f293672019-04-01 01:40:24 -0700631static void adev_snd_mon_cb(void *cookie, struct str_parms *parms);
632static void in_snd_mon_cb(void * stream, struct str_parms * parms);
633static void out_snd_mon_cb(void * stream, struct str_parms * parms);
634
Zhou Song331c8e52019-08-26 14:16:12 +0800635static int configure_btsco_sample_rate(snd_device_t snd_device);
636
Vatsal Buchac09ae062018-11-14 13:25:08 +0530637#ifdef AUDIO_FEATURE_ENABLED_GCOV
638extern void __gcov_flush();
639static void enable_gcov()
640{
641 __gcov_flush();
642}
643#else
644static void enable_gcov()
645{
646}
647#endif
648
justinweng20fb6d82019-02-21 18:49:00 -0700649static int in_set_microphone_direction(const struct audio_stream_in *stream,
650 audio_microphone_direction_t dir);
651static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom);
652
Krishna Kishor Jha0f4d8482022-02-18 10:56:05 +0530653static bool is_pcm_record_usecase(audio_usecase_t uc_id)
654{
655 unsigned int record_uc_index;
656 unsigned int num_usecase = sizeof(record_usecases)/sizeof(record_usecases[0]);
657
658 for (record_uc_index = 0; record_uc_index < num_usecase; record_uc_index++) {
659 if (uc_id == record_usecases[record_uc_index])
660 return true;
661 }
662 return false;
663}
664
665static audio_usecase_t get_record_usecase(struct audio_device *adev)
666{
667 audio_usecase_t ret_uc = USECASE_INVALID;
668 unsigned int record_uc_index;
669 unsigned int num_usecase = sizeof(record_usecases)/sizeof(record_usecases[0]);
670
671 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
672 for (record_uc_index = 0; record_uc_index < num_usecase; record_uc_index++) {
673 if (!(adev->pcm_record_uc_state & (0x1 << record_uc_index))) {
674 adev->pcm_record_uc_state |= 0x1 << record_uc_index;
675 ret_uc = record_usecases[record_uc_index];
676 break;
677 }
678 }
679
680 ALOGV("%s: pcm record usecase is %d", __func__, ret_uc);
681 return ret_uc;
682}
683
684static void free_record_usecase(struct audio_device *adev,
685 audio_usecase_t uc_id)
686{
687 unsigned int record_uc_index;
688 unsigned int num_usecase = sizeof(record_usecases)/sizeof(record_usecases[0]);
689
690 for (record_uc_index = 0; record_uc_index < num_usecase; record_uc_index++) {
691 if (record_usecases[record_uc_index] == uc_id) {
692 adev->pcm_record_uc_state &= ~(0x1 << record_uc_index);
693 break;
694 }
695 }
696 ALOGV("%s: free pcm record usecase %d", __func__, uc_id);
697}
698
Kogara Naveen Kumarc5758232022-11-07 20:25:40 +0530699static bool is_pcm_low_latency_record_usecase(audio_usecase_t uc_id)
700{
701 unsigned int record_uc_index;
702 unsigned int num_usecase = sizeof(low_latency_record_usecases)/sizeof(low_latency_record_usecases[0]);
703 ALOGD("%s: Check low latency pcm record usecase", __func__);
704
705 for (record_uc_index = 0; record_uc_index < num_usecase; record_uc_index++) {
706 if (uc_id == low_latency_record_usecases[record_uc_index])
707 return true;
708 }
709 return false;
710}
711
712static audio_usecase_t get_low_latency_record_usecase(struct audio_device *adev)
713{
714 audio_usecase_t ret_uc = USECASE_INVALID;
715 unsigned int record_uc_index;
716 unsigned int num_usecase = sizeof(low_latency_record_usecases)/sizeof(low_latency_record_usecases[0]);
717
718 ALOGD("%s: get_low_latency_record_usecase: %d", __func__, num_usecase);
719 for (record_uc_index = 0; record_uc_index < num_usecase; record_uc_index++) {
720 if (!(adev->pcm_low_latency_record_uc_state & (0x1 << record_uc_index))) {
721 adev->pcm_low_latency_record_uc_state |= 0x1 << record_uc_index;
722 ALOGD("%s: get_low_latency_record_usecase: %d", __func__, record_uc_index);
723 ret_uc = low_latency_record_usecases[record_uc_index];
724 break;
725 }
726 }
727
728 ALOGD("%s: low latency pcm record usecase is %d", __func__, ret_uc);
729 return ret_uc;
730}
731
732static void free_low_latency_record_usecase(struct audio_device *adev,
733 audio_usecase_t uc_id)
734{
735 unsigned int record_uc_index;
736 unsigned int num_usecase = sizeof(low_latency_record_usecases)/sizeof(low_latency_record_usecases[0]);
737
738 for (record_uc_index = 0; record_uc_index < num_usecase; record_uc_index++) {
739 if (low_latency_record_usecases[record_uc_index] == uc_id) {
740 adev->pcm_low_latency_record_uc_state &= ~(0x1 << record_uc_index);
741 break;
742 }
743 }
744 ALOGD("%s: free low latency pcm record usecase %d", __func__, uc_id);
745}
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700746static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
747 int flags __unused)
748{
749 int dir = 0;
750 switch (uc_id) {
751 case USECASE_AUDIO_RECORD_LOW_LATENCY:
Revathi Uddarajud9f23d92020-07-27 10:55:06 +0530752 case USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY:
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700753 dir = 1;
754 case USECASE_AUDIO_PLAYBACK_ULL:
755 break;
756 default:
757 return false;
758 }
759
760 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
761 PCM_PLAYBACK : PCM_CAPTURE);
762 if (adev->adm_is_noirq_avail)
763 return adev->adm_is_noirq_avail(adev->adm_data,
764 adev->snd_card, dev_id, dir);
765 return false;
766}
767
768static void register_out_stream(struct stream_out *out)
769{
770 struct audio_device *adev = out->dev;
771 if (is_offload_usecase(out->usecase) ||
772 !adev->adm_register_output_stream)
773 return;
774
775 // register stream first for backward compatibility
776 adev->adm_register_output_stream(adev->adm_data,
777 out->handle,
778 out->flags);
779
780 if (!adev->adm_set_config)
781 return;
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +0530782#ifdef PLATFORM_AUTO
Kogara Naveen Kumar6db5fb02022-05-07 00:22:50 +0530783 if (out->realtime || (out->flags & AUDIO_OUTPUT_FLAG_SYS_NOTIFICATION))
784 adev->adm_set_config(adev->adm_data,
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700785 out->handle,
786 out->pcm, &out->config);
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +0530787#else
788 if (out->realtime)
789 adev->adm_set_config(adev->adm_data,
790 out->handle,
791 out->pcm, &out->config);
792#endif
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700793}
794
795static void register_in_stream(struct stream_in *in)
796{
797 struct audio_device *adev = in->dev;
798 if (!adev->adm_register_input_stream)
799 return;
800
801 adev->adm_register_input_stream(adev->adm_data,
802 in->capture_handle,
803 in->flags);
804
805 if (!adev->adm_set_config)
806 return;
807
808 if (in->realtime)
809 adev->adm_set_config(adev->adm_data,
810 in->capture_handle,
811 in->pcm,
812 &in->config);
813}
814
815static void request_out_focus(struct stream_out *out, long ns)
816{
817 struct audio_device *adev = out->dev;
818
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700819 if (adev->adm_request_focus_v2)
820 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
821 else if (adev->adm_request_focus)
822 adev->adm_request_focus(adev->adm_data, out->handle);
823}
824
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700825static int request_in_focus(struct stream_in *in, long ns)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700826{
827 struct audio_device *adev = in->dev;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700828 int ret = 0;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700829
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700830 if (adev->adm_request_focus_v2_1)
831 ret = adev->adm_request_focus_v2_1(adev->adm_data, in->capture_handle, ns);
832 else if (adev->adm_request_focus_v2)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700833 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
834 else if (adev->adm_request_focus)
835 adev->adm_request_focus(adev->adm_data, in->capture_handle);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700836
837 return ret;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700838}
839
840static void release_out_focus(struct stream_out *out)
841{
842 struct audio_device *adev = out->dev;
843
844 if (adev->adm_abandon_focus)
845 adev->adm_abandon_focus(adev->adm_data, out->handle);
846}
847
848static void release_in_focus(struct stream_in *in)
849{
850 struct audio_device *adev = in->dev;
851 if (adev->adm_abandon_focus)
852 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
853}
854
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530855static int parse_snd_card_status(struct str_parms *parms, int *card,
856 card_status_t *status)
857{
858 char value[32]={0};
859 char state[32]={0};
860
861 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
862 if (ret < 0)
863 return -1;
864
865 // sscanf should be okay as value is of max length 32.
866 // same as sizeof state.
867 if (sscanf(value, "%d,%s", card, state) < 2)
868 return -1;
869
870 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
871 CARD_STATUS_OFFLINE;
872 return 0;
873}
874
Avinash Chandrad7296d42021-08-04 15:07:47 +0530875bool is_combo_audio_input_device(struct listnode *devices){
876
Sandhya Mutha Naga Venkata153d95e2022-07-12 14:54:43 +0530877 if ((devices == NULL) || (!list_empty(devices)))
Avinash Chandrad7296d42021-08-04 15:07:47 +0530878 return false;
879
880 if(compare_device_type(devices, AUDIO_DEVICE_IN_BUILTIN_MIC|AUDIO_DEVICE_IN_SPEAKER_MIC2))
881 return true;
882 else
883 return false;
884}
885
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700886static inline void adjust_frames_for_device_delay(struct stream_out *out,
887 uint32_t *dsp_frames) {
888 // Adjustment accounts for A2dp encoder latency with offload usecases
889 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -0800890 if (is_a2dp_out_device_type(&out->device_list)) {
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700891 unsigned long offset =
892 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
893 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
894 }
895}
896
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700897static inline bool free_entry(void *key __unused,
898 void *value, void *context __unused)
899{
900 free(value);
901 return true;
902}
903
904static inline void free_map(Hashmap *map)
905{
906 if (map) {
907 hashmapForEach(map, free_entry, (void *) NULL);
908 hashmapFree(map);
909 }
910}
911
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800912static inline void patch_map_remove_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700913 audio_patch_handle_t patch_handle)
914{
915 if (patch_handle == AUDIO_PATCH_HANDLE_NONE)
916 return;
917
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700918 struct audio_patch_info *p_info =
919 hashmapGet(adev->patch_map, (void *) (intptr_t) patch_handle);
920 if (p_info) {
921 ALOGV("%s: Remove patch %d", __func__, patch_handle);
922 hashmapRemove(adev->patch_map, (void *) (intptr_t) patch_handle);
923 free(p_info->patch);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700924 free(p_info);
925 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700926}
927
928static inline int io_streams_map_insert(struct audio_device *adev,
929 struct audio_stream *stream,
930 audio_io_handle_t handle,
931 audio_patch_handle_t patch_handle)
932{
933 struct audio_stream_info *s_info =
934 (struct audio_stream_info *) calloc(1, sizeof(struct audio_stream_info));
935
936 if (s_info == NULL) {
937 ALOGE("%s: Could not allocate stream info", __func__);
938 return -ENOMEM;
939 }
940 s_info->stream = stream;
941 s_info->patch_handle = patch_handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700942
943 pthread_mutex_lock(&adev->lock);
944 struct audio_stream_info *stream_info =
945 hashmapPut(adev->io_streams_map, (void *) (intptr_t) handle, (void *) s_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700946 if (stream_info != NULL)
947 free(stream_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800948 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Latad13758f2020-08-06 15:11:36 -0700949 ALOGV("%s: Added stream in io_streams_map with handle %d", __func__, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700950 return 0;
951}
952
953static inline void io_streams_map_remove(struct audio_device *adev,
954 audio_io_handle_t handle)
955{
956 pthread_mutex_lock(&adev->lock);
957 struct audio_stream_info *s_info =
958 hashmapRemove(adev->io_streams_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700959 if (s_info == NULL)
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800960 goto done;
Aniket Kumar Latad13758f2020-08-06 15:11:36 -0700961 ALOGV("%s: Removed stream with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800962 patch_map_remove_l(adev, s_info->patch_handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700963 free(s_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800964done:
965 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700966 return;
967}
968
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800969static struct audio_patch_info* fetch_patch_info_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700970 audio_patch_handle_t handle)
971{
972 struct audio_patch_info *p_info = NULL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700973 p_info = (struct audio_patch_info *)
974 hashmapGet(adev->patch_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700975 return p_info;
976}
977
vivek mehtaa76401a2015-04-24 14:12:15 -0700978__attribute__ ((visibility ("default")))
979bool audio_hw_send_gain_dep_calibration(int level) {
980 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700981 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700982
983 pthread_mutex_lock(&adev_init_lock);
984
985 if (adev != NULL && adev->platform != NULL) {
986 pthread_mutex_lock(&adev->lock);
987 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700988
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530989 // cache level info for any of the use case which
990 // was not started.
991 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700992
vivek mehtaa76401a2015-04-24 14:12:15 -0700993 pthread_mutex_unlock(&adev->lock);
994 } else {
995 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
996 }
997
998 pthread_mutex_unlock(&adev_init_lock);
999
1000 return ret_val;
1001}
1002
Ashish Jain5106d362016-05-11 19:23:33 +05301003static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
1004{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08001005 bool gapless_enabled = false;
1006 const char *mixer_ctl_name = "Compress Gapless Playback";
1007 struct mixer_ctl *ctl;
1008
1009 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07001010 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +05301011
1012 /*Disable gapless if its AV playback*/
1013 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08001014
1015 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1016 if (!ctl) {
1017 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1018 __func__, mixer_ctl_name);
1019 return -EINVAL;
1020 }
1021
1022 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
1023 ALOGE("%s: Could not set gapless mode %d",
1024 __func__, gapless_enabled);
1025 return -EINVAL;
1026 }
1027 return 0;
1028}
Haynes Mathew George5191a852013-09-11 14:19:36 -07001029
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -07001030__attribute__ ((visibility ("default")))
1031int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
1032 int table_size) {
1033 int ret_val = 0;
1034 ALOGV("%s: enter ... ", __func__);
1035
1036 pthread_mutex_lock(&adev_init_lock);
1037 if (adev == NULL) {
1038 ALOGW("%s: adev is NULL .... ", __func__);
1039 goto done;
1040 }
1041
1042 pthread_mutex_lock(&adev->lock);
1043 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
1044 pthread_mutex_unlock(&adev->lock);
1045done:
1046 pthread_mutex_unlock(&adev_init_lock);
1047 ALOGV("%s: exit ... ", __func__);
1048 return ret_val;
1049}
1050
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001051bool audio_hw_send_qdsp_parameter(int stream_type, float vol, bool active)
Aalique Grahame22e49102018-12-18 14:23:57 -08001052{
1053 bool ret = false;
1054 ALOGV("%s: enter ...", __func__);
1055
1056 pthread_mutex_lock(&adev_init_lock);
1057
1058 if (adev != NULL && adev->platform != NULL) {
1059 pthread_mutex_lock(&adev->lock);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001060 ret = audio_extn_qdsp_set_state(adev, stream_type, vol, active);
Aalique Grahame22e49102018-12-18 14:23:57 -08001061 pthread_mutex_unlock(&adev->lock);
1062 }
1063
1064 pthread_mutex_unlock(&adev_init_lock);
1065
1066 ALOGV("%s: exit with ret %d", __func__, ret);
1067 return ret;
1068}
Aalique Grahame22e49102018-12-18 14:23:57 -08001069
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001070static bool is_supported_format(audio_format_t format)
1071{
Eric Laurent86e17132013-09-12 17:49:30 -07001072 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +05301073 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +05301074 format == AUDIO_FORMAT_AAC_LC ||
1075 format == AUDIO_FORMAT_AAC_HE_V1 ||
1076 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +05301077 format == AUDIO_FORMAT_AAC_ADTS_LC ||
1078 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
1079 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05301080 format == AUDIO_FORMAT_AAC_LATM_LC ||
1081 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
1082 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +05301083 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
1084 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +05301085 format == AUDIO_FORMAT_PCM_FLOAT ||
1086 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -07001087 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301088 format == AUDIO_FORMAT_AC3 ||
1089 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -07001090 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301091 format == AUDIO_FORMAT_DTS ||
1092 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001093 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301094 format == AUDIO_FORMAT_ALAC ||
1095 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301096 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301097 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001098 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05301099 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07001100 format == AUDIO_FORMAT_APTX ||
1101 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08001102 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001103
1104 return false;
1105}
1106
Kunlei Zhang67cc7072020-12-18 17:16:49 +08001107static bool is_supported_conc_usecase_for_power_mode_call(struct audio_device *adev)
1108{
1109 struct listnode *node;
1110 struct audio_usecase *usecase;
1111
1112 list_for_each(node, &adev->usecase_list) {
1113 usecase = node_to_item(node, struct audio_usecase, list);
1114 if (usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1115 ALOGD("%s: FM usecase is active, not setting power mode", __func__);
1116 return false;
1117 }
1118 }
1119
1120 return true;
1121}
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001122static inline bool is_mmap_usecase(audio_usecase_t uc_id)
1123{
1124 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
Zhou Song62ea0282020-03-22 19:53:01 +08001125 (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY2) ||
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001126 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
1127}
1128
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07001129static inline bool is_valid_volume(float left, float right)
1130{
1131 return ((left >= 0.0f && right >= 0.0f) ? true : false);
1132}
1133
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301134static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301135{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301136 ALOGV("%s", __func__);
1137 audio_route_apply_and_update_path(adev->audio_route,
1138 "asrc-mode");
1139 adev->asrc_mode_enabled = true;
1140}
1141
1142static void disable_asrc_mode(struct audio_device *adev)
1143{
1144 ALOGV("%s", __func__);
1145 audio_route_reset_and_update_path(adev->audio_route,
1146 "asrc-mode");
1147 adev->asrc_mode_enabled = false;
1148}
1149
Saurav Kumarc1411662020-10-14 10:50:45 +05301150static void check_and_configure_headphone(struct audio_device *adev,
1151 struct audio_usecase *uc_info,
1152 snd_device_t snd_device)
1153{
1154 struct listnode *node;
1155 struct audio_usecase *usecase;
1156 int new_backend_idx, usecase_backend_idx;
1157 bool spkr_hph_single_be_native_concurrency;
1158
1159 new_backend_idx = platform_get_backend_index(snd_device);
1160 spkr_hph_single_be_native_concurrency = platform_get_spkr_hph_single_be_native_concurrency_flag();
Zhou Songd4b18c42021-01-14 15:15:29 +08001161 if ((spkr_hph_single_be_native_concurrency && (new_backend_idx == DEFAULT_CODEC_BACKEND)) ||
1162 uc_info->id == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
Saurav Kumarc1411662020-10-14 10:50:45 +05301163 list_for_each(node, &adev->usecase_list) {
1164 usecase = node_to_item(node, struct audio_usecase, list);
1165 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
1166 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
1167 if (((usecase_backend_idx == HEADPHONE_BACKEND) ||
1168 (usecase_backend_idx == HEADPHONE_44_1_BACKEND)) &&
1169 ((usecase->stream.out->sample_rate % OUTPUT_SAMPLING_RATE_44100) == 0)) {
1170 disable_audio_route(adev, usecase);
1171 disable_snd_device(adev, usecase->out_snd_device);
1172 usecase->stream.out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Saurav Kumar70902382020-10-28 11:16:04 +05301173 platform_check_and_set_codec_backend_cfg(adev, usecase,
1174 usecase->out_snd_device);
Saurav Kumarc1411662020-10-14 10:50:45 +05301175 enable_snd_device(adev, usecase->out_snd_device);
Zhou Songd4b18c42021-01-14 15:15:29 +08001176 enable_audio_route(adev, usecase);
Saurav Kumarc1411662020-10-14 10:50:45 +05301177 }
1178 }
Revathi Uddaraju2c0eac02021-07-27 02:06:42 -07001179 else if ((usecase->type != PCM_CAPTURE) && (usecase == uc_info)) {
1180 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
1181 if (((usecase_backend_idx == HEADPHONE_BACKEND) ||
1182 (usecase_backend_idx == HEADPHONE_44_1_BACKEND)) &&
1183 ((usecase->stream.out->sample_rate % OUTPUT_SAMPLING_RATE_44100) == 0)) {
1184 usecase->stream.out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1185 platform_check_and_set_codec_backend_cfg(adev, usecase,
1186 usecase->out_snd_device);
1187 }
1188 }
Saurav Kumarc1411662020-10-14 10:50:45 +05301189 }
1190 }
1191}
1192
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301193/*
1194 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
1195 * 44.1 or Native DSD backends are enabled for any of current use case.
1196 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
1197 * - Disable current mix path use case(Headphone backend) and re-enable it with
1198 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
1199 * e.g. Naitve DSD or Headphone 44.1 -> + 48
1200 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301201static void check_and_set_asrc_mode(struct audio_device *adev,
1202 struct audio_usecase *uc_info,
1203 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301204{
1205 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301206 int i, num_new_devices = 0;
1207 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
1208 /*
1209 *Split snd device for new combo use case
1210 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
1211 */
1212 if (platform_split_snd_device(adev->platform,
1213 snd_device,
1214 &num_new_devices,
1215 split_new_snd_devices) == 0) {
1216 for (i = 0; i < num_new_devices; i++)
1217 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
1218 } else {
1219 int new_backend_idx = platform_get_backend_index(snd_device);
1220 if (((new_backend_idx == HEADPHONE_BACKEND) ||
1221 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
1222 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
1223 !adev->asrc_mode_enabled) {
1224 struct listnode *node = NULL;
1225 struct audio_usecase *uc = NULL;
1226 struct stream_out *curr_out = NULL;
1227 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
1228 int i, num_devices, ret = 0;
1229 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301230
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301231 list_for_each(node, &adev->usecase_list) {
1232 uc = node_to_item(node, struct audio_usecase, list);
1233 curr_out = (struct stream_out*) uc->stream.out;
1234 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
1235 /*
1236 *Split snd device for existing combo use case
1237 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
1238 */
1239 ret = platform_split_snd_device(adev->platform,
1240 uc->out_snd_device,
1241 &num_devices,
1242 split_snd_devices);
1243 if (ret < 0 || num_devices == 0) {
1244 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
1245 split_snd_devices[0] = uc->out_snd_device;
1246 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -08001247 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301248 for (i = 0; i < num_devices; i++) {
1249 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
1250 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
1251 if((new_backend_idx == HEADPHONE_BACKEND) &&
1252 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
1253 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07001254 ALOGV("%s:DSD or native stream detected enabling asrcmode in hardware",
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301255 __func__);
1256 enable_asrc_mode(adev);
1257 break;
1258 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
1259 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
1260 (usecase_backend_idx == HEADPHONE_BACKEND)) {
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07001261 ALOGV("%s: 48K stream detected, disabling and enabling it \
1262 with asrcmode in hardware", __func__);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301263 disable_audio_route(adev, uc);
1264 disable_snd_device(adev, uc->out_snd_device);
1265 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
1266 if (new_backend_idx == DSD_NATIVE_BACKEND)
1267 audio_route_apply_and_update_path(adev->audio_route,
1268 "hph-true-highquality-mode");
1269 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
1270 (curr_out->bit_width >= 24))
1271 audio_route_apply_and_update_path(adev->audio_route,
1272 "hph-highquality-mode");
1273 enable_asrc_mode(adev);
1274 enable_snd_device(adev, uc->out_snd_device);
1275 enable_audio_route(adev, uc);
1276 break;
1277 }
1278 }
1279 // reset split devices count
1280 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -08001281 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301282 if (adev->asrc_mode_enabled)
1283 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301284 }
1285 }
1286 }
1287}
1288
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001289static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
1290 struct audio_effect_config effect_config,
1291 unsigned int param_value)
1292{
1293 char mixer_ctl_name[] = "Audio Effect";
1294 struct mixer_ctl *ctl;
1295 long set_values[6];
Eric Laurent637e2d42018-11-15 12:24:31 -08001296 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001297
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001298 if (in == NULL) {
1299 ALOGE("%s: active input stream is NULL", __func__);
1300 return -EINVAL;
1301 }
1302
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001303 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1304 if (!ctl) {
1305 ALOGE("%s: Could not get mixer ctl - %s",
1306 __func__, mixer_ctl_name);
1307 return -EINVAL;
1308 }
1309
1310 set_values[0] = 1; //0:Rx 1:Tx
1311 set_values[1] = in->app_type_cfg.app_type;
1312 set_values[2] = (long)effect_config.module_id;
1313 set_values[3] = (long)effect_config.instance_id;
1314 set_values[4] = (long)effect_config.param_id;
1315 set_values[5] = param_value;
1316
1317 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
1318
1319 return 0;
1320
1321}
1322
1323static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
1324 int effect_type, unsigned int *param_value)
1325{
1326 int ret = 0;
1327 struct audio_effect_config other_effect_config;
1328 struct audio_usecase *usecase = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08001329 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001330
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001331 if (in == NULL) {
1332 ALOGE("%s: active input stream is NULL", __func__);
1333 return -EINVAL;
1334 }
1335
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001336 usecase = get_usecase_from_list(adev, in->usecase);
1337 if (!usecase)
1338 return -EINVAL;
1339
1340 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
1341 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
1342 if (ret < 0) {
1343 ALOGE("%s Failed to get effect params %d", __func__, ret);
1344 return ret;
1345 }
1346
1347 if (module_id == other_effect_config.module_id) {
1348 //Same module id for AEC/NS. Values need to be combined
1349 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
1350 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
1351 *param_value |= other_effect_config.param_value;
1352 }
1353 }
1354
1355 return ret;
1356}
1357
1358static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
Gangadhar Sb0210342019-02-22 17:39:41 +05301359{
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001360 struct audio_effect_config effect_config;
1361 struct audio_usecase *usecase = NULL;
1362 int ret = 0;
1363 unsigned int param_value = 0;
Eric Laurent637e2d42018-11-15 12:24:31 -08001364 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001365
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001366 if(!voice_extn_is_dynamic_ecns_enabled())
1367 return ENOSYS;
1368
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001369 if (!in) {
1370 ALOGE("%s: Invalid input stream", __func__);
1371 return -EINVAL;
1372 }
1373
1374 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
1375
1376 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +08001377 if (usecase == NULL) {
1378 ALOGE("%s: Could not find the usecase (%d) in the list",
1379 __func__, in->usecase);
1380 return -EINVAL;
1381 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001382
1383 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
1384 if (ret < 0) {
1385 ALOGE("%s Failed to get module id %d", __func__, ret);
1386 return ret;
1387 }
1388 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
1389 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
1390
1391 if(enable)
1392 param_value = effect_config.param_value;
1393
1394 /*Special handling for AEC & NS effects Param values need to be
1395 updated if module ids are same*/
1396
1397 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
1398 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
1399 if (ret < 0)
1400 return ret;
1401 }
1402
1403 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
1404
1405 return ret;
1406}
1407
1408static void check_and_enable_effect(struct audio_device *adev)
1409{
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001410 if(!voice_extn_is_dynamic_ecns_enabled())
1411 return;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001412
Eric Laurent637e2d42018-11-15 12:24:31 -08001413 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001414
Eric Laurent637e2d42018-11-15 12:24:31 -08001415 if (in != NULL && !in->standby) {
1416 if (in->enable_aec)
1417 enable_disable_effect(adev, EFFECT_AEC, true);
1418
1419 if (in->enable_ns &&
1420 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1421 enable_disable_effect(adev, EFFECT_NS, true);
1422 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001423 }
1424}
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001425
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001426int pcm_ioctl(struct pcm *pcm, int request, ...)
1427{
1428 va_list ap;
1429 void * arg;
1430 int pcm_fd = *(int*)pcm;
1431
1432 va_start(ap, request);
1433 arg = va_arg(ap, void *);
1434 va_end(ap);
1435
1436 return ioctl(pcm_fd, request, arg);
1437}
1438
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001439int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001440 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001441{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001442 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001443 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +05301444 struct stream_out *out = NULL;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301445 struct stream_in *in = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001446 struct listnode out_devices;
Soumya Managoli6993b762018-06-28 16:04:57 +05301447 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001448
1449 if (usecase == NULL)
1450 return -EINVAL;
1451
1452 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
1453
Carter Hsu2e429db2019-05-14 18:50:52 +08001454 if (usecase->type == PCM_CAPTURE) {
1455 struct stream_in *in = usecase->stream.in;
1456 struct audio_usecase *uinfo;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001457 snd_device = usecase->in_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001458
1459 if (in) {
1460 if (in->enable_aec || in->enable_ec_port) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001461 list_init(&out_devices);
1462 update_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "", true);
Carter Hsu2e429db2019-05-14 18:50:52 +08001463 struct listnode *node;
1464 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1465 USECASE_AUDIO_PLAYBACK_VOIP);
1466 if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001467 assign_devices(&out_devices,
1468 &voip_usecase->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001469 } else if (adev->primary_output &&
1470 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001471 assign_devices(&out_devices,
1472 &adev->primary_output->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001473 } else {
1474 list_for_each(node, &adev->usecase_list) {
1475 uinfo = node_to_item(node, struct audio_usecase, list);
1476 if (uinfo->type != PCM_CAPTURE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001477 assign_devices(&out_devices,
1478 &uinfo->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001479 break;
1480 }
1481 }
1482 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001483
1484 platform_set_echo_reference(adev, true, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001485 in->ec_opened = true;
Zhenlin Lian4f947842022-05-14 15:50:52 +05301486 clear_devices(&out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001487 }
1488 }
Guodong Huf5e614d2019-06-24 18:42:03 +08001489 } else if ((usecase->type == TRANSCODE_LOOPBACK_TX) || ((usecase->type == PCM_HFP_CALL) &&
1490 ((usecase->id == USECASE_AUDIO_HFP_SCO) || (usecase->id == USECASE_AUDIO_HFP_SCO_WB)) &&
1491 (usecase->in_snd_device == SND_DEVICE_IN_VOICE_SPEAKER_MIC_HFP_MMSECNS))) {
Carter Hsu2e429db2019-05-14 18:50:52 +08001492 snd_device = usecase->in_snd_device;
1493 } else {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001494 snd_device = usecase->out_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001495 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001496
Kunlei Zhanga3c4cb02021-03-05 16:03:54 +08001497 if (usecase->type == PCM_CAPTURE) {
1498 if (platform_get_fluence_nn_state(adev->platform) == 0) {
1499 platform_set_fluence_nn_state(adev->platform, true);
1500 ALOGD("%s: set fluence nn capture state", __func__);
1501 }
1502 }
1503
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001504#ifdef DS1_DOLBY_DAP_ENABLED
1505 audio_extn_dolby_set_dmid(adev);
1506 audio_extn_dolby_set_endpoint(adev);
1507#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001508 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001509 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301510 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001511 audio_extn_utils_send_app_type_cfg(adev, usecase);
Jasmine Cha4dcc1092019-03-04 18:12:47 +08001512 if (audio_extn_is_maxx_audio_enabled())
1513 audio_extn_ma_set_device(usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301514 audio_extn_utils_send_audio_calibration(adev, usecase);
Zhou Songbaddf9f2020-11-20 13:57:39 +08001515 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1516 out = usecase->stream.out;
1517 if (out && out->compr)
Manish Dewangan58229382017-02-02 15:48:41 +05301518 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1519 }
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301520
1521 if (usecase->type == PCM_CAPTURE) {
Kunlei Zhanga3c4cb02021-03-05 16:03:54 +08001522 if (platform_get_fluence_nn_state(adev->platform) == 1 &&
1523 adev->fluence_nn_usecase_id == USECASE_INVALID ) {
1524 adev->fluence_nn_usecase_id = usecase->id;
1525 ALOGD("%s: assign fluence nn usecase %d", __func__, usecase->id);
1526 }
1527 }
1528
1529 if (usecase->type == PCM_CAPTURE) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301530 in = usecase->stream.in;
Avinash Chandrad7296d42021-08-04 15:07:47 +05301531 if ((in && is_loopback_input_device(get_device_types(&in->device_list))) ||
1532 (in && is_combo_audio_input_device(&in->device_list)) ||
1533 (in && ((compare_device_type(&in->device_list, AUDIO_DEVICE_IN_BUILTIN_MIC) ||
1534 compare_device_type(&in->device_list, AUDIO_DEVICE_IN_LINE)) &&
1535 (snd_device == SND_DEVICE_IN_HANDSET_GENERIC_6MIC)))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301536 ALOGD("%s: set custom mtmx params v1", __func__);
1537 audio_extn_set_custom_mtmx_params_v1(adev, usecase, true);
1538 }
1539 } else {
1540 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
1541 }
Manish Dewangan58229382017-02-02 15:48:41 +05301542
Andy Hung756ecc12018-10-19 17:47:12 -07001543 // we shouldn't truncate mixer_path
1544 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1545 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1546 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001547 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001548 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301549 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1550 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1551 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1552 if (parms) {
1553 audio_extn_fm_set_parameters(adev, parms);
1554 str_parms_destroy(parms);
1555 }
1556 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001557 ALOGV("%s: exit", __func__);
1558 return 0;
1559}
1560
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001561int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001562 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001563{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001564 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001565 char mixer_path[MIXER_PATH_MAX_LENGTH];
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301566 struct stream_in *in = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001567
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301568 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001569 return -EINVAL;
1570
1571 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301572 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001573 snd_device = usecase->in_snd_device;
1574 else
1575 snd_device = usecase->out_snd_device;
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001576
1577 /* disable island and power mode on supported device for voice call */
1578 if (usecase->type == VOICE_CALL) {
1579 if (usecase->in_snd_device != SND_DEVICE_NONE) {
1580 if (platform_get_island_cfg_on_device(adev->platform, usecase->in_snd_device) &&
1581 platform_get_power_mode_on_device(adev->platform, usecase->in_snd_device)) {
1582 platform_set_island_cfg_on_device(adev, usecase->in_snd_device, false);
1583 platform_set_power_mode_on_device(adev, usecase->in_snd_device, false);
1584 platform_reset_island_power_status(adev->platform, usecase->in_snd_device);
Kunlei Zhang91c4b332020-07-20 17:53:14 +08001585 if (voice_is_lte_call_active(adev))
1586 platform_set_tx_lpi_mode(adev->platform, false);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001587 ALOGD("%s: disable island cfg and power mode in voice tx path",
1588 __func__);
1589 }
1590 }
1591 if (usecase->out_snd_device != SND_DEVICE_NONE) {
1592 if (platform_get_island_cfg_on_device(adev->platform, usecase->out_snd_device) &&
1593 platform_get_power_mode_on_device(adev->platform, usecase->out_snd_device)) {
1594 platform_set_island_cfg_on_device(adev, usecase->out_snd_device, false);
1595 platform_set_power_mode_on_device(adev, usecase->out_snd_device, false);
1596 platform_reset_island_power_status(adev->platform, usecase->out_snd_device);
1597 ALOGD("%s: disable island cfg and power mode in voice rx path",
1598 __func__);
1599 }
1600 }
1601 }
1602
Andy Hung756ecc12018-10-19 17:47:12 -07001603 // we shouldn't truncate mixer_path
1604 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1605 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1606 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001607 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001608 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001609 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Carter Hsu2e429db2019-05-14 18:50:52 +08001610 if (usecase->type == PCM_CAPTURE) {
1611 struct stream_in *in = usecase->stream.in;
1612 if (in && in->ec_opened) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001613 struct listnode out_devices;
1614 list_init(&out_devices);
1615 platform_set_echo_reference(in->dev, false, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001616 in->ec_opened = false;
Zhenlin Lian4f947842022-05-14 15:50:52 +05301617 clear_devices(&out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001618 }
1619 }
Kunlei Zhanga3c4cb02021-03-05 16:03:54 +08001620 if (usecase->id == adev->fluence_nn_usecase_id) {
1621 platform_set_fluence_nn_state(adev->platform, false);
1622 adev->fluence_nn_usecase_id = USECASE_INVALID;
1623 ALOGD("%s: reset fluence nn capture state", __func__);
1624 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001625 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301626 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301627
1628 if (usecase->type == PCM_CAPTURE) {
1629 in = usecase->stream.in;
Avinash Chandrad7296d42021-08-04 15:07:47 +05301630 if ((in && is_loopback_input_device(get_device_types(&in->device_list))) ||
1631 (in && is_combo_audio_input_device(&in->device_list)) ||
1632 (in && ((compare_device_type(&in->device_list, AUDIO_DEVICE_IN_BUILTIN_MIC) ||
1633 compare_device_type(&in->device_list, AUDIO_DEVICE_IN_LINE)) &&
1634 (snd_device == SND_DEVICE_IN_HANDSET_GENERIC_6MIC)))){
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301635 ALOGD("%s: reset custom mtmx params v1", __func__);
1636 audio_extn_set_custom_mtmx_params_v1(adev, usecase, false);
1637 }
1638 } else {
1639 audio_extn_set_custom_mtmx_params_v2(adev, usecase, false);
1640 }
1641
Weiyin Jiang298ffd92019-06-03 14:29:30 +08001642 if ((usecase->type == PCM_PLAYBACK) &&
1643 (usecase->stream.out != NULL))
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05301644 usecase->stream.out->pspd_coeff_sent = false;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301645
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001646 ALOGV("%s: exit", __func__);
1647 return 0;
1648}
1649
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001650int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001651 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001652{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301653 int i, num_devices = 0;
1654 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001655 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1656
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001657 if (snd_device < SND_DEVICE_MIN ||
1658 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001659 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001660 return -EINVAL;
1661 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001662
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001663 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001664 ALOGE("%s: Invalid sound device returned", __func__);
1665 return -EINVAL;
1666 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001667
1668 adev->snd_dev_ref_cnt[snd_device]++;
1669
1670 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1671 (platform_split_snd_device(adev->platform,
1672 snd_device,
1673 &num_devices,
1674 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001675 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001676 __func__, snd_device, device_name);
Aniket Kumar Lata990de552019-07-11 14:20:23 -07001677 /* Set backend config for A2DP to ensure slimbus configuration
1678 is correct if A2DP is already active and backend is closed
1679 and re-opened */
1680 if (snd_device == SND_DEVICE_OUT_BT_A2DP)
1681 audio_extn_a2dp_set_source_backend_cfg();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001682 return 0;
1683 }
1684
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001685 if (audio_extn_spkr_prot_is_enabled())
1686 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001687
Aalique Grahame22e49102018-12-18 14:23:57 -08001688 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1689
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001690 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1691 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001692 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1693 goto err;
1694 }
1695 audio_extn_dev_arbi_acquire(snd_device);
1696 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001697 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001698 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001699 goto err;
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001700 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001701 } else if (platform_split_snd_device(adev->platform,
1702 snd_device,
1703 &num_devices,
1704 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301705 for (i = 0; i < num_devices; i++) {
1706 enable_snd_device(adev, new_snd_devices[i]);
1707 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001708 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001709 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001710 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301711
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001712 /* enable island and power mode on supported device */
1713 if (platform_get_island_cfg_on_device(adev->platform, snd_device) &&
1714 platform_get_power_mode_on_device(adev->platform, snd_device)) {
1715 platform_set_island_cfg_on_device(adev, snd_device, true);
1716 platform_set_power_mode_on_device(adev, snd_device, true);
Kunlei Zhang91c4b332020-07-20 17:53:14 +08001717 if (voice_is_lte_call_active(adev) &&
1718 (snd_device >= SND_DEVICE_IN_BEGIN &&
1719 snd_device < SND_DEVICE_IN_END))
1720 platform_set_tx_lpi_mode(adev->platform, true);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001721 ALOGD("%s: enable island cfg and power mode on: %s",
1722 __func__, device_name);
1723 }
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301724
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301725 if (SND_DEVICE_OUT_BT_A2DP == snd_device) {
Ramjee Singh2d2944a2021-12-14 14:13:41 +05301726
1727 struct audio_usecase *usecase;
1728 struct listnode *node;
1729 /* Disable SCO Devices and enable handset mic for active input stream */
1730 list_for_each(node, &adev->usecase_list) {
1731 usecase = node_to_item(node, struct audio_usecase, list);
1732 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
1733 is_sco_in_device_type(&usecase->stream.in->device_list)) {
1734 ALOGD("a2dp resumed, switch bt sco mic to handset mic");
1735 reassign_device_list(&usecase->stream.in->device_list,
1736 AUDIO_DEVICE_IN_BUILTIN_MIC, "");
1737 select_devices(adev, usecase->id);
1738 }
1739 }
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301740 if (audio_extn_a2dp_start_playback() < 0) {
1741 ALOGE(" fail to configure A2dp Source control path ");
1742 goto err;
1743 } else {
1744 adev->a2dp_started = true;
1745 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001746 }
Florian Pfister1a84f312018-07-19 14:38:18 +02001747
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001748 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1749 (audio_extn_a2dp_start_capture() < 0)) {
1750 ALOGE(" fail to configure A2dp Sink control path ");
1751 goto err;
1752 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301753
Mingshu Pang7be5b1d2020-03-04 15:24:38 +08001754 if ((SND_DEVICE_OUT_BT_SCO_SWB == snd_device) ||
1755 (SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC == snd_device) ||
1756 (SND_DEVICE_IN_BT_SCO_MIC_SWB == snd_device)) {
1757 if (!adev->bt_sco_on || (audio_extn_sco_start_configuration() < 0)) {
1758 ALOGE(" fail to configure sco control path ");
1759 goto err;
1760 }
Zhou Song12c29502019-03-16 10:37:18 +08001761 }
1762
Zhou Song331c8e52019-08-26 14:16:12 +08001763 configure_btsco_sample_rate(snd_device);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001764 /* due to the possibility of calibration overwrite between listen
1765 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001766 audio_extn_sound_trigger_update_device_status(snd_device,
1767 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301768 audio_extn_listen_update_device_status(snd_device,
1769 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001770 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001771 audio_extn_sound_trigger_update_device_status(snd_device,
1772 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301773 audio_extn_listen_update_device_status(snd_device,
1774 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001775 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001776 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001777 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001778 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301779
1780 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1781 !adev->native_playback_enabled &&
1782 audio_is_true_native_stream_active(adev)) {
1783 ALOGD("%s: %d: napb: enabling native mode in hardware",
1784 __func__, __LINE__);
1785 audio_route_apply_and_update_path(adev->audio_route,
1786 "true-native-mode");
1787 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301788 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301789 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1790 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001791 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001792 ALOGD("%s: init ec ref loopback", __func__);
1793 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1794 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001795 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001796 return 0;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001797err:
1798 adev->snd_dev_ref_cnt[snd_device]--;
1799 return -EINVAL;;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001800}
1801
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001802int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001803 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001804{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301805 int i, num_devices = 0;
1806 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001807 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1808
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001809 if (snd_device < SND_DEVICE_MIN ||
1810 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001811 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001812 return -EINVAL;
1813 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001814
1815 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1816 ALOGE("%s: Invalid sound device returned", __func__);
1817 return -EINVAL;
1818 }
1819
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001820 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1821 ALOGE("%s: device ref cnt is already 0", __func__);
1822 return -EINVAL;
1823 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001824
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001825 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001826
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001827
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001828 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001829 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301830
Aalique Grahame22e49102018-12-18 14:23:57 -08001831 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1832
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001833 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1834 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001835 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001836
1837 // when speaker device is disabled, reset swap.
1838 // will be renabled on usecase start
1839 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001840 } else if (platform_split_snd_device(adev->platform,
1841 snd_device,
1842 &num_devices,
1843 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301844 for (i = 0; i < num_devices; i++) {
1845 disable_snd_device(adev, new_snd_devices[i]);
1846 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001847 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001848 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001849 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001850 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001851
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301852 if (snd_device == SND_DEVICE_OUT_BT_A2DP) {
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301853 audio_extn_a2dp_stop_playback();
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301854 adev->a2dp_started = false;
1855 } else if (snd_device == SND_DEVICE_IN_BT_A2DP)
Florian Pfister1a84f312018-07-19 14:38:18 +02001856 audio_extn_a2dp_stop_capture();
Zhou Songd6d71752019-05-21 18:08:51 +08001857 else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001858 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
Ashish Jain81eb2a82015-05-13 10:52:34 +05301859 adev->is_channel_status_set = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001860 else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301861 adev->native_playback_enabled) {
1862 ALOGD("%s: %d: napb: disabling native mode in hardware",
1863 __func__, __LINE__);
1864 audio_route_reset_and_update_path(adev->audio_route,
1865 "true-native-mode");
1866 adev->native_playback_enabled = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001867 } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301868 adev->asrc_mode_enabled) {
1869 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301870 disable_asrc_mode(adev);
1871 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001872 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301873 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001874 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001875 ALOGD("%s: deinit ec ref loopback", __func__);
1876 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1877 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001878
1879 audio_extn_utils_release_snd_device(snd_device);
1880 } else {
1881 if (platform_split_snd_device(adev->platform,
1882 snd_device,
1883 &num_devices,
1884 new_snd_devices) == 0) {
1885 for (i = 0; i < num_devices; i++) {
1886 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1887 }
1888 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001889 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001890
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001891 return 0;
1892}
1893
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001894/*
1895 legend:
1896 uc - existing usecase
1897 new_uc - new usecase
1898 d1, d11, d2 - SND_DEVICE enums
1899 a1, a2 - corresponding ANDROID device enums
1900 B1, B2 - backend strings
1901
1902case 1
1903 uc->dev d1 (a1) B1
1904 new_uc->dev d1 (a1), d2 (a2) B1, B2
1905
1906 resolution: disable and enable uc->dev on d1
1907
1908case 2
1909 uc->dev d1 (a1) B1
1910 new_uc->dev d11 (a1) B1
1911
1912 resolution: need to switch uc since d1 and d11 are related
1913 (e.g. speaker and voice-speaker)
1914 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1915
1916case 3
1917 uc->dev d1 (a1) B1
1918 new_uc->dev d2 (a2) B2
1919
1920 resolution: no need to switch uc
1921
1922case 4
1923 uc->dev d1 (a1) B1
1924 new_uc->dev d2 (a2) B1
1925
1926 resolution: disable enable uc-dev on d2 since backends match
1927 we cannot enable two streams on two different devices if they
1928 share the same backend. e.g. if offload is on speaker device using
1929 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1930 using the same backend, offload must also be switched to voice-handset.
1931
1932case 5
1933 uc->dev d1 (a1) B1
1934 new_uc->dev d1 (a1), d2 (a2) B1
1935
1936 resolution: disable enable uc-dev on d2 since backends match
1937 we cannot enable two streams on two different devices if they
1938 share the same backend.
1939
1940case 6
1941 uc->dev d1 (a1) B1
1942 new_uc->dev d2 (a1) B2
1943
1944 resolution: no need to switch
1945
1946case 7
1947 uc->dev d1 (a1), d2 (a2) B1, B2
1948 new_uc->dev d1 (a1) B1
1949
1950 resolution: no need to switch
1951
Zhou Song4ba65882018-07-09 14:48:07 +08001952case 8
1953 uc->dev d1 (a1) B1
1954 new_uc->dev d11 (a1), d2 (a2) B1, B2
1955 resolution: compared to case 1, for this case, d1 and d11 are related
1956 then need to do the same as case 2 to siwtch to new uc
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301957
1958case 9
1959 uc->dev d1 (a1), d2(a2) B1 B2
1960 new_uc->dev d1 (a1), d22 (a2) B1, B2
1961 resolution: disable enable uc-dev on d2 since backends match
1962 we cannot enable two streams on two different devices if they
1963 share the same backend. This is special case for combo use case
1964 with a2dp and sco devices which uses same backend.
1965 e.g. speaker-a2dp and speaker-btsco
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001966*/
1967static snd_device_t derive_playback_snd_device(void * platform,
1968 struct audio_usecase *uc,
1969 struct audio_usecase *new_uc,
1970 snd_device_t new_snd_device)
1971{
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001972 struct listnode a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001973
1974 snd_device_t d1 = uc->out_snd_device;
1975 snd_device_t d2 = new_snd_device;
Sandhya Mutha Naga Venkataa597a962023-02-07 11:35:51 +05301976 int ret = 0;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001977
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001978 list_init(&a1);
1979 list_init(&a2);
1980
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301981 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301982 case TRANSCODE_LOOPBACK_RX :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001983 assign_devices(&a1, &uc->stream.inout->out_config.device_list);
1984 assign_devices(&a2, &new_uc->stream.inout->out_config.device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301985 break;
1986 default :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001987 assign_devices(&a1, &uc->stream.out->device_list);
1988 assign_devices(&a2, &new_uc->stream.out->device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301989 break;
1990 }
1991
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001992 // Treat as a special case when a1 and a2 are not disjoint
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001993 if (!compare_devices(&a1, &a2) &&
1994 compare_devices_for_any_match(&a1 ,&a2)) {
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001995 snd_device_t d3[2];
1996 int num_devices = 0;
Sandhya Mutha Naga Venkataa597a962023-02-07 11:35:51 +05301997 ret = platform_split_snd_device(platform,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001998 list_length(&a1) > 1 ? d1 : d2,
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001999 &num_devices,
2000 d3);
2001 if (ret < 0) {
2002 if (ret != -ENOSYS) {
2003 ALOGW("%s failed to split snd_device %d",
2004 __func__,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002005 list_length(&a1) > 1 ? d1 : d2);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07002006 }
Sandhya Mutha Naga Venkata4c6fc9f2022-10-14 19:38:02 +05302007 ret = d2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07002008 goto end;
2009 }
2010
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07002011 if (platform_check_backends_match(d3[0], d3[1])) {
Sandhya Mutha Naga Venkata4c6fc9f2022-10-14 19:38:02 +05302012 ret = d2;
2013 goto end; // case 5
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07002014 } else {
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05302015 if ((list_length(&a1) > 1) && (list_length(&a2) > 1) &&
Sandhya Mutha Naga Venkata4c6fc9f2022-10-14 19:38:02 +05302016 platform_check_backends_match(d1, d2)) {
2017 ret = d2;
2018 goto end; //case 9
2019 }
2020 if (list_length(&a1) > 1) {
2021 ret = d1;
2022 goto end; //case 7
2023 }
Garmond Leungb9eeba42018-09-18 11:10:41 -07002024 // check if d1 is related to any of d3's
Sandhya Mutha Naga Venkata4c6fc9f2022-10-14 19:38:02 +05302025 if (d1 == d3[0] || d1 == d3[1]) {
2026 ret = d1;
2027 goto end; // case 1
2028 } else {
2029 ret = d3[1];
2030 goto end; // case 8
2031 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07002032 }
2033 } else {
2034 if (platform_check_backends_match(d1, d2)) {
Sandhya Mutha Naga Venkata4c6fc9f2022-10-14 19:38:02 +05302035 ret = d2;
2036 goto end; // case 2, 4
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07002037 } else {
Sandhya Mutha Naga Venkata4c6fc9f2022-10-14 19:38:02 +05302038 ret = d1;
2039 goto end; // case 6, 3
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07002040 }
2041 }
2042
2043end:
Sandhya Mutha Naga Venkata4c6fc9f2022-10-14 19:38:02 +05302044 clear_devices(&a1);
2045 clear_devices(&a2);
2046 return ret; // return whatever was calculated before.
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07002047}
2048
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002049static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05302050 struct audio_usecase *uc_info,
2051 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002052{
2053 struct listnode *node;
2054 struct audio_usecase *usecase;
2055 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05302056 snd_device_t uc_derive_snd_device;
2057 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08002058 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
2059 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08002060 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302061 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002062 /*
2063 * This function is to make sure that all the usecases that are active on
2064 * the hardware codec backend are always routed to any one device that is
2065 * handled by the hardware codec.
2066 * For example, if low-latency and deep-buffer usecases are currently active
2067 * on speaker and out_set_parameters(headset) is received on low-latency
2068 * output, then we have to make sure deep-buffer is also switched to headset,
2069 * because of the limitation that both the devices cannot be enabled
2070 * at the same time as they share the same backend.
2071 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07002072 /*
2073 * This call is to check if we need to force routing for a particular stream
2074 * If there is a backend configuration change for the device when a
2075 * new stream starts, then ADM needs to be closed and re-opened with the new
2076 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08002077 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07002078 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08002079 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
2080 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302081 /* For a2dp device reconfigure all active sessions
2082 * with new AFE encoder format based on a2dp state
2083 */
2084 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05302085 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device ||
2086 SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP == snd_device) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302087 audio_extn_a2dp_is_force_device_switch()) {
2088 force_routing = true;
2089 force_restart_session = true;
2090 }
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08002091
2092 /*
2093 * Island cfg and power mode config needs to set before AFE port start.
2094 * Set force routing in case of voice device was enable before.
2095 */
2096 if (uc_info->type == VOICE_CALL &&
2097 voice_extn_is_voice_power_mode_supported() &&
Kunlei Zhang67cc7072020-12-18 17:16:49 +08002098 is_supported_conc_usecase_for_power_mode_call(adev) &&
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08002099 platform_check_and_update_island_power_status(adev->platform,
2100 uc_info,
2101 snd_device)) {
2102 force_routing = true;
2103 ALOGD("%s:becf: force routing %d for power mode supported device",
2104 __func__, force_routing);
2105 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302106 ALOGD("%s:becf: force routing %d", __func__, force_routing);
2107
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002108 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002109 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002110 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002111 for (i = 0; i < AUDIO_USECASE_MAX; i++)
2112 switch_device[i] = false;
2113
2114 list_for_each(node, &adev->usecase_list) {
2115 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08002116
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05302117 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
2118 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302119 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05302120 platform_get_snd_device_name(usecase->out_snd_device),
2121 platform_check_backends_match(snd_device, usecase->out_snd_device));
Rahul Sharma99770982019-03-06 17:05:26 +05302122 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
2123 (usecase->type != PCM_PASSTHROUGH)) {
Ashish Jain6a65b352017-03-21 17:24:40 +05302124 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
2125 usecase, uc_info, snd_device);
2126 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002127 (is_codec_backend_out_device_type(&usecase->device_list) ||
2128 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
2129 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_DEVICE) ||
2130 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_HEADSET) ||
2131 is_a2dp_out_device_type(&usecase->device_list) ||
2132 is_sco_out_device_type(&usecase->device_list)) &&
Ashish Jain6a65b352017-03-21 17:24:40 +05302133 ((force_restart_session) ||
2134 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05302135 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
2136 __func__, use_case_table[usecase->id],
2137 platform_get_snd_device_name(usecase->out_snd_device));
2138 disable_audio_route(adev, usecase);
2139 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05302140 /* Enable existing usecase on derived playback device */
2141 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05302142 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05302143 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002144 }
2145 }
2146
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302147 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
2148 num_uc_to_switch);
2149
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002150 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07002151 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002152
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05302153 /* Make sure the previous devices to be disabled first and then enable the
2154 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002155 list_for_each(node, &adev->usecase_list) {
2156 usecase = node_to_item(node, struct audio_usecase, list);
2157 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08002158 /* Check if output sound device to be switched can be split and if any
2159 of the split devices match with derived sound device */
2160 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
2161 &num_devices, split_snd_devices) == 0) {
2162 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
2163 for (i = 0; i < num_devices; i++) {
2164 /* Disable devices that do not match with derived sound device */
2165 if (split_snd_devices[i] != derive_snd_device[usecase->id])
2166 disable_snd_device(adev, split_snd_devices[i]);
2167 }
2168 } else {
2169 disable_snd_device(adev, usecase->out_snd_device);
2170 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002171 }
2172 }
2173
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07002174 list_for_each(node, &adev->usecase_list) {
2175 usecase = node_to_item(node, struct audio_usecase, list);
2176 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08002177 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
2178 &num_devices, split_snd_devices) == 0) {
2179 /* Enable derived sound device only if it does not match with
2180 one of the split sound devices. This is because the matching
2181 sound device was not disabled */
2182 bool should_enable = true;
2183 for (i = 0; i < num_devices; i++) {
2184 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
2185 should_enable = false;
2186 break;
2187 }
2188 }
2189 if (should_enable)
2190 enable_snd_device(adev, derive_snd_device[usecase->id]);
2191 } else {
2192 enable_snd_device(adev, derive_snd_device[usecase->id]);
2193 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07002194 }
2195 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002196
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002197 /* Re-route all the usecases on the shared backend other than the
2198 specified usecase to new snd devices */
2199 list_for_each(node, &adev->usecase_list) {
2200 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05302201 /* Update the out_snd_device only before enabling the audio route */
2202 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05302203 usecase->out_snd_device = derive_snd_device[usecase->id];
Lakshman Chaluvarajuab7e5572020-10-28 19:29:23 +05302204 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
2205 use_case_table[usecase->id],
2206 platform_get_snd_device_name(usecase->out_snd_device));
2207 /* Update voc calibration before enabling Voice/VoIP route */
2208 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL)
2209 status = platform_switch_voice_call_device_post(adev->platform,
2210 usecase->out_snd_device,
2211 platform_get_input_snd_device(
2212 adev->platform, NULL,
2213 &uc_info->device_list,
2214 usecase->type));
2215 enable_audio_route(adev, usecase);
2216 if (usecase->stream.out && usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
2217 out_set_voip_volume(&usecase->stream.out->stream,
2218 usecase->stream.out->volume_l,
2219 usecase->stream.out->volume_r);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05302220 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002221 }
2222 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002223 }
2224}
2225
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302226static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002227 struct audio_usecase *uc_info,
2228 snd_device_t snd_device)
2229{
2230 struct listnode *node;
2231 struct audio_usecase *usecase;
2232 bool switch_device[AUDIO_USECASE_MAX];
2233 int i, num_uc_to_switch = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002234 int backend_check_cond = is_codec_backend_out_device_type(&uc_info->device_list);
kunleiz5cd52b82016-11-07 17:22:52 +08002235 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002236
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302237 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
2238 snd_device);
2239 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05302240
2241 /*
2242 * Make sure out devices is checked against out codec backend device and
2243 * also in devices against in codec backend. Checking out device against in
2244 * codec backend or vice versa causes issues.
2245 */
2246 if (uc_info->type == PCM_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002247 backend_check_cond = is_codec_backend_in_device_type(&uc_info->device_list);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08002248
2249 /*
2250 * Island cfg and power mode config needs to set before AFE port start.
2251 * Set force routing in case of voice device was enable before.
2252 */
2253
2254 if (uc_info->type == VOICE_CALL &&
2255 voice_extn_is_voice_power_mode_supported() &&
Kunlei Zhang67cc7072020-12-18 17:16:49 +08002256 is_supported_conc_usecase_for_power_mode_call(adev) &&
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08002257 platform_check_and_update_island_power_status(adev->platform,
2258 uc_info,
2259 snd_device)) {
2260 force_routing = true;
2261 ALOGD("%s:becf: force routing %d for power mode supported device",
2262 __func__, force_routing);
2263 }
2264
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002265 /*
2266 * This function is to make sure that all the active capture usecases
2267 * are always routed to the same input sound device.
2268 * For example, if audio-record and voice-call usecases are currently
2269 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
2270 * is received for voice call then we have to make sure that audio-record
2271 * usecase is also switched to earpiece i.e. voice-dmic-ef,
2272 * because of the limitation that two devices cannot be enabled
2273 * at the same time if they share the same backend.
2274 */
2275 for (i = 0; i < AUDIO_USECASE_MAX; i++)
2276 switch_device[i] = false;
2277
2278 list_for_each(node, &adev->usecase_list) {
2279 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05302280 /*
2281 * TODO: Enhance below condition to handle BT sco/USB multi recording
2282 */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302283
2284 bool capture_uc_needs_routing = usecase->type != PCM_PLAYBACK && (usecase != uc_info &&
2285 (usecase->in_snd_device != snd_device || force_routing));
2286 bool call_proxy_snd_device = platform_is_call_proxy_snd_device(snd_device) ||
2287 platform_is_call_proxy_snd_device(usecase->in_snd_device);
2288 if (capture_uc_needs_routing && !call_proxy_snd_device &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002289 ((backend_check_cond &&
2290 (is_codec_backend_in_device_type(&usecase->device_list) ||
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08002291 (usecase->type == VOIP_CALL))) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08002292 ((uc_info->type == VOICE_CALL &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002293 is_single_device_type_equal(&usecase->device_list,
2294 AUDIO_DEVICE_IN_VOICE_CALL)) ||
Anver sadhique4fdc6992022-01-21 12:26:28 +05302295 platform_check_all_backends_match(snd_device,\
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002296 usecase->in_snd_device))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07002297 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05302298 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..",
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002299 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07002300 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002301 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002302 switch_device[usecase->id] = true;
2303 num_uc_to_switch++;
2304 }
2305 }
2306
2307 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07002308 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002309
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05302310 /* Make sure the previous devices to be disabled first and then enable the
2311 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002312 list_for_each(node, &adev->usecase_list) {
2313 usecase = node_to_item(node, struct audio_usecase, list);
2314 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002315 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08002316 }
2317 }
2318
2319 list_for_each(node, &adev->usecase_list) {
2320 usecase = node_to_item(node, struct audio_usecase, list);
2321 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002322 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002323 }
2324 }
2325
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002326 /* Re-route all the usecases on the shared backend other than the
2327 specified usecase to new snd devices */
2328 list_for_each(node, &adev->usecase_list) {
2329 usecase = node_to_item(node, struct audio_usecase, list);
2330 /* Update the in_snd_device only before enabling the audio route */
2331 if (switch_device[usecase->id] ) {
2332 usecase->in_snd_device = snd_device;
Lakshman Chaluvarajuab7e5572020-10-28 19:29:23 +05302333 /* Update voc calibration before enabling Voice/VoIP route */
2334 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
2335 snd_device_t voip_snd_device;
2336 voip_snd_device = platform_get_output_snd_device(adev->platform,
2337 usecase->stream.out,
2338 usecase->type);
2339 status = platform_switch_voice_call_device_post(adev->platform,
2340 voip_snd_device,
2341 usecase->in_snd_device);
kunleiz5cd52b82016-11-07 17:22:52 +08002342 }
Lakshman Chaluvarajuab7e5572020-10-28 19:29:23 +05302343 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002344 }
2345 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002346 }
2347}
2348
Mingming Yin3a941d42016-02-17 18:08:05 -08002349static void reset_hdmi_sink_caps(struct stream_out *out) {
2350 int i = 0;
2351
2352 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
2353 out->supported_channel_masks[i] = 0;
2354 }
2355 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
2356 out->supported_formats[i] = 0;
2357 }
2358 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
2359 out->supported_sample_rates[i] = 0;
2360 }
2361}
2362
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002363/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08002364static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002365{
Mingming Yin3a941d42016-02-17 18:08:05 -08002366 int ret = 0, i = 0, j = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002367 int channels = platform_edid_get_max_channels_v2(out->dev->platform,
2368 out->extconn.cs.controller,
2369 out->extconn.cs.stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002370
Mingming Yin3a941d42016-02-17 18:08:05 -08002371 reset_hdmi_sink_caps(out);
2372
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002373 /* Cache ext disp type */
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002374 ret = platform_get_ext_disp_type_v2(adev->platform,
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002375 out->extconn.cs.controller,
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002376 out->extconn.cs.stream);
2377 if(ret < 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002378 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07002379 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002380 }
2381
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002382 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002383 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08002384 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002385 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08002386 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
2387 case 6:
2388 ALOGV("%s: HDMI supports 5.1 channels", __func__);
2389 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
2390 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
2391 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
2392 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
2393 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002394 break;
2395 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08002396 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002397 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002398 break;
2399 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002400
2401 // check channel format caps
2402 i = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002403 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_AC3,
2404 out->extconn.cs.controller,
2405 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002406 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
2407 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
2408 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
2409 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
2410 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
2411 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
2412 }
2413
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002414 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD,
2415 out->extconn.cs.controller,
2416 out->extconn.cs.stream)) {
Ben Romberger1aaaf862017-04-06 17:49:46 -07002417 ALOGV(":%s HDMI supports TRUE HD format", __func__);
2418 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
2419 }
2420
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002421 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS,
2422 out->extconn.cs.controller,
2423 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002424 ALOGV(":%s HDMI supports DTS format", __func__);
2425 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
2426 }
2427
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002428 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS_HD,
2429 out->extconn.cs.controller,
2430 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002431 ALOGV(":%s HDMI supports DTS HD format", __func__);
2432 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
2433 }
2434
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002435 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_IEC61937,
2436 out->extconn.cs.controller,
2437 out->extconn.cs.stream)) {
Naresh Tanniru928f0862017-04-07 16:44:23 -07002438 ALOGV(":%s HDMI supports IEC61937 format", __func__);
2439 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
2440 }
2441
Mingming Yin3a941d42016-02-17 18:08:05 -08002442
2443 // check sample rate caps
2444 i = 0;
2445 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002446 if (platform_is_edid_supported_sample_rate_v2(out->dev->platform, out_hdmi_sample_rates[j],
2447 out->extconn.cs.controller,
2448 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002449 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
2450 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
2451 }
2452 }
2453
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002454 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002455}
2456
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002457static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
2458 uint32_t *supported_sample_rates __unused,
2459 uint32_t max_rates __unused)
2460{
2461 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
2462 supported_sample_rates,
2463 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05302464 ssize_t i = 0;
2465
2466 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002467 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
2468 supported_sample_rates[i]);
2469 }
2470 return count;
2471}
2472
2473static inline int read_usb_sup_channel_masks(bool is_playback,
2474 audio_channel_mask_t *supported_channel_masks,
2475 uint32_t max_masks)
2476{
2477 int channels = audio_extn_usb_get_max_channels(is_playback);
2478 int channel_count;
2479 uint32_t num_masks = 0;
2480 if (channels > MAX_HIFI_CHANNEL_COUNT)
2481 channels = MAX_HIFI_CHANNEL_COUNT;
2482
2483 if (is_playback) {
Eric Laurent68a87112019-05-01 18:07:29 -07002484 // start from 2 channels as framework currently doesn't support mono.
2485 if (channels >= FCC_2) {
2486 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(FCC_2);
2487 }
2488 for (channel_count = FCC_2;
2489 channel_count <= channels && num_masks < max_masks;
2490 ++channel_count) {
2491 supported_channel_masks[num_masks++] =
2492 audio_channel_mask_for_index_assignment_from_count(channel_count);
2493 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002494 } else {
vincenttewf51c94e2019-05-07 10:28:53 +08002495 // For capture we report all supported channel masks from 1 channel up.
2496 channel_count = MIN_CHANNEL_COUNT;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002497 // audio_channel_in_mask_from_count() does the right conversion to either positional or
2498 // indexed mask
Eric Laurent68a87112019-05-01 18:07:29 -07002499 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
2500 audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
2501 if (channel_count <= FCC_2) {
2502 mask = audio_channel_in_mask_from_count(channel_count);
2503 supported_channel_masks[num_masks++] = mask;
2504 }
2505 const audio_channel_mask_t index_mask =
2506 audio_channel_mask_for_index_assignment_from_count(channel_count);
2507 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
2508 supported_channel_masks[num_masks++] = index_mask;
2509 }
2510 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002511 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302512
vincenttewf51c94e2019-05-07 10:28:53 +08002513 for (size_t i = 0; i < num_masks; ++i) {
2514 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
2515 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302516 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002517 return num_masks;
2518}
2519
2520static inline int read_usb_sup_formats(bool is_playback __unused,
2521 audio_format_t *supported_formats,
2522 uint32_t max_formats __unused)
2523{
2524 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
2525 switch (bitwidth) {
2526 case 24:
2527 // XXX : usb.c returns 24 for s24 and s24_le?
2528 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
2529 break;
2530 case 32:
2531 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
2532 break;
2533 case 16:
2534 default :
2535 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
2536 break;
2537 }
2538 ALOGV("%s: %s supported format %d", __func__,
2539 is_playback ? "P" : "C", bitwidth);
2540 return 1;
2541}
2542
2543static inline int read_usb_sup_params_and_compare(bool is_playback,
2544 audio_format_t *format,
2545 audio_format_t *supported_formats,
2546 uint32_t max_formats,
2547 audio_channel_mask_t *mask,
2548 audio_channel_mask_t *supported_channel_masks,
2549 uint32_t max_masks,
2550 uint32_t *rate,
2551 uint32_t *supported_sample_rates,
2552 uint32_t max_rates) {
2553 int ret = 0;
2554 int num_formats;
2555 int num_masks;
2556 int num_rates;
2557 int i;
2558
2559 num_formats = read_usb_sup_formats(is_playback, supported_formats,
2560 max_formats);
2561 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
2562 max_masks);
2563
2564 num_rates = read_usb_sup_sample_rates(is_playback,
2565 supported_sample_rates, max_rates);
2566
2567#define LUT(table, len, what, dflt) \
2568 for (i=0; i<len && (table[i] != what); i++); \
2569 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
2570
2571 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
2572 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
2573 LUT(supported_sample_rates, num_rates, *rate, 0);
2574
2575#undef LUT
2576 return ret < 0 ? -EINVAL : 0; // HACK TBD
2577}
2578
Alexy Josephb1379942016-01-29 15:49:38 -08002579audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002580 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002581{
2582 struct audio_usecase *usecase;
2583 struct listnode *node;
2584
2585 list_for_each(node, &adev->usecase_list) {
2586 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002587 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002588 ALOGV("%s: usecase id %d", __func__, usecase->id);
2589 return usecase->id;
2590 }
2591 }
2592 return USECASE_INVALID;
2593}
2594
Alexy Josephb1379942016-01-29 15:49:38 -08002595struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002596 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002597{
2598 struct audio_usecase *usecase;
2599 struct listnode *node;
2600
2601 list_for_each(node, &adev->usecase_list) {
2602 usecase = node_to_item(node, struct audio_usecase, list);
2603 if (usecase->id == uc_id)
2604 return usecase;
2605 }
2606 return NULL;
2607}
2608
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302609/*
2610 * is a true native playback active
2611 */
2612bool audio_is_true_native_stream_active(struct audio_device *adev)
2613{
2614 bool active = false;
2615 int i = 0;
2616 struct listnode *node;
2617
2618 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
2619 ALOGV("%s:napb: not in true mode or non hdphones device",
2620 __func__);
2621 active = false;
2622 goto exit;
2623 }
2624
2625 list_for_each(node, &adev->usecase_list) {
2626 struct audio_usecase *uc;
2627 uc = node_to_item(node, struct audio_usecase, list);
2628 struct stream_out *curr_out =
2629 (struct stream_out*) uc->stream.out;
2630
2631 if (curr_out && PCM_PLAYBACK == uc->type) {
2632 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
2633 "(%d) device %s", __func__, i++, use_case_table[uc->id],
2634 uc->id, curr_out->sample_rate,
2635 curr_out->bit_width,
2636 platform_get_snd_device_name(uc->out_snd_device));
2637
2638 if (is_offload_usecase(uc->id) &&
2639 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
2640 active = true;
2641 ALOGD("%s:napb:native stream detected", __func__);
2642 }
2643 }
2644 }
2645exit:
2646 return active;
2647}
2648
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002649uint32_t adev_get_dsp_bit_width_enforce_mode()
2650{
2651 if (adev == NULL) {
2652 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
2653 return 0;
2654 }
2655 return adev->dsp_bit_width_enforce_mode;
2656}
2657
2658static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
2659{
2660 char value[PROPERTY_VALUE_MAX];
2661 int trial;
2662 uint32_t dsp_bit_width_enforce_mode = 0;
2663
2664 if (!mixer) {
2665 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
2666 __func__);
2667 return 0;
2668 }
2669
2670 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
2671 value, NULL) > 0) {
2672 trial = atoi(value);
2673 switch (trial) {
2674 case 16:
2675 dsp_bit_width_enforce_mode = 16;
2676 break;
2677 case 24:
2678 dsp_bit_width_enforce_mode = 24;
2679 break;
2680 case 32:
2681 dsp_bit_width_enforce_mode = 32;
2682 break;
2683 default:
2684 dsp_bit_width_enforce_mode = 0;
2685 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
2686 break;
2687 }
2688 }
2689
2690 return dsp_bit_width_enforce_mode;
2691}
2692
2693static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
2694 uint32_t enforce_mode,
2695 bool enable)
2696{
2697 struct mixer_ctl *ctl = NULL;
2698 const char *mixer_ctl_name = "ASM Bit Width";
2699 uint32_t asm_bit_width_mode = 0;
2700
2701 if (enforce_mode == 0) {
2702 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
2703 return;
2704 }
2705
2706 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
2707 if (!ctl) {
2708 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2709 __func__, mixer_ctl_name);
2710 return;
2711 }
2712
2713 if (enable)
2714 asm_bit_width_mode = enforce_mode;
2715 else
2716 asm_bit_width_mode = 0;
2717
2718 ALOGV("%s DSP bit width feature status is %d width=%d",
2719 __func__, enable, asm_bit_width_mode);
2720 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2721 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2722 asm_bit_width_mode);
2723
2724 return;
2725}
2726
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302727/*
2728 * if native DSD playback active
2729 */
2730bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2731{
2732 bool active = false;
2733 struct listnode *node = NULL;
2734 struct audio_usecase *uc = NULL;
2735 struct stream_out *curr_out = NULL;
2736
2737 list_for_each(node, &adev->usecase_list) {
2738 uc = node_to_item(node, struct audio_usecase, list);
2739 curr_out = (struct stream_out*) uc->stream.out;
2740
2741 if (curr_out && PCM_PLAYBACK == uc->type &&
2742 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2743 active = true;
2744 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302745 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302746 }
2747 }
2748 return active;
2749}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302750
2751static bool force_device_switch(struct audio_usecase *usecase)
2752{
2753 bool ret = false;
2754 bool is_it_true_mode = false;
2755
Zhou Song30f2c3e2018-02-08 14:02:15 +08002756 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302757 usecase->type == TRANSCODE_LOOPBACK_RX ||
2758 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002759 return false;
2760 }
2761
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002762 if(usecase->stream.out == NULL) {
2763 ALOGE("%s: stream.out is NULL", __func__);
2764 return false;
2765 }
2766
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302767 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002768 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002769 (compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADSET) ||
2770 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADPHONE))) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302771 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2772 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2773 (!is_it_true_mode && adev->native_playback_enabled)){
2774 ret = true;
2775 ALOGD("napb: time to toggle native mode");
2776 }
2777 }
2778
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302779 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302780 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2781 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002782 if(is_a2dp_out_device_type(&usecase->stream.out->device_list) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302783 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302784 ALOGD("Force a2dp device switch to update new encoder config");
2785 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002786 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302787
Florian Pfister1a84f312018-07-19 14:38:18 +02002788 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302789 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2790 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002791 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302792 return ret;
2793}
2794
Aalique Grahame22e49102018-12-18 14:23:57 -08002795static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2796{
2797 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2798}
2799
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302800bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2801{
2802 bool ret=false;
2803 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
Zhou Song5657f492019-08-07 11:30:39 +08002804 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
2805 out_snd_device == SND_DEVICE_OUT_BT_SCO_SWB) ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302806 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2807 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
Zhou Song5657f492019-08-07 11:30:39 +08002808 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302809 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
Mingshu Pang16093502020-04-20 11:21:16 +08002810 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC ||
2811 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC)
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302812 ret = true;
2813
2814 return ret;
2815}
2816
2817bool is_a2dp_device(snd_device_t out_snd_device)
2818{
2819 bool ret=false;
2820 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2821 ret = true;
2822
2823 return ret;
2824}
2825
2826bool is_bt_soc_on(struct audio_device *adev)
2827{
2828 struct mixer_ctl *ctl;
2829 char *mixer_ctl_name = "BT SOC status";
2830 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2831 bool bt_soc_status = true;
2832 if (!ctl) {
2833 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2834 __func__, mixer_ctl_name);
2835 /*This is to ensure we dont break targets which dont have the kernel change*/
2836 return true;
2837 }
2838 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2839 ALOGD("BT SOC status: %d",bt_soc_status);
2840 return bt_soc_status;
2841}
2842
Zhou Song331c8e52019-08-26 14:16:12 +08002843static int configure_btsco_sample_rate(snd_device_t snd_device)
2844{
2845 struct mixer_ctl *ctl = NULL;
2846 struct mixer_ctl *ctl_sr_rx = NULL, *ctl_sr_tx = NULL, *ctl_sr = NULL;
2847 char *rate_str = NULL;
2848 bool is_rx_dev = true;
2849
2850 if (is_btsco_device(snd_device, snd_device)) {
2851 ctl_sr_tx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate TX");
2852 ctl_sr_rx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate RX");
2853 if (!ctl_sr_tx || !ctl_sr_rx) {
2854 ctl_sr = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate");
2855 if (!ctl_sr)
2856 return -ENOSYS;
2857 }
2858
2859 switch (snd_device) {
2860 case SND_DEVICE_OUT_BT_SCO:
2861 rate_str = "KHZ_8";
2862 break;
2863 case SND_DEVICE_IN_BT_SCO_MIC_NREC:
2864 case SND_DEVICE_IN_BT_SCO_MIC:
2865 rate_str = "KHZ_8";
2866 is_rx_dev = false;
2867 break;
2868 case SND_DEVICE_OUT_BT_SCO_WB:
2869 rate_str = "KHZ_16";
2870 break;
2871 case SND_DEVICE_IN_BT_SCO_MIC_WB_NREC:
2872 case SND_DEVICE_IN_BT_SCO_MIC_WB:
2873 rate_str = "KHZ_16";
2874 is_rx_dev = false;
2875 break;
2876 default:
2877 return 0;
2878 }
2879
2880 ctl = (ctl_sr == NULL) ? (is_rx_dev ? ctl_sr_rx : ctl_sr_tx) : ctl_sr;
2881 if (mixer_ctl_set_enum_by_string(ctl, rate_str) != 0)
2882 return -ENOSYS;
2883 }
2884 return 0;
2885}
2886
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302887int out_standby_l(struct audio_stream *stream);
2888
Eric Laurent637e2d42018-11-15 12:24:31 -08002889struct stream_in *adev_get_active_input(const struct audio_device *adev)
2890{
2891 struct listnode *node;
2892 struct stream_in *last_active_in = NULL;
2893
2894 /* Get last added active input.
2895 * TODO: We may use a priority mechanism to pick highest priority active source */
2896 list_for_each(node, &adev->usecase_list)
2897 {
2898 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2899 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL)
2900 last_active_in = usecase->stream.in;
2901 }
2902
2903 return last_active_in;
2904}
2905
2906struct stream_in *get_voice_communication_input(const struct audio_device *adev)
2907{
2908 struct listnode *node;
2909
2910 /* First check active inputs with voice communication source and then
2911 * any input if audio mode is in communication */
2912 list_for_each(node, &adev->usecase_list)
2913 {
2914 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2915 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
2916 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
2917 return usecase->stream.in;
2918 }
2919 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION)
2920 return adev_get_active_input(adev);
2921
2922 return NULL;
2923}
2924
Carter Hsu2e429db2019-05-14 18:50:52 +08002925/*
2926 * Aligned with policy.h
2927 */
2928static inline int source_priority(int inputSource)
2929{
2930 switch (inputSource) {
2931 case AUDIO_SOURCE_VOICE_COMMUNICATION:
2932 return 9;
2933 case AUDIO_SOURCE_CAMCORDER:
2934 return 8;
2935 case AUDIO_SOURCE_VOICE_PERFORMANCE:
2936 return 7;
2937 case AUDIO_SOURCE_UNPROCESSED:
2938 return 6;
2939 case AUDIO_SOURCE_MIC:
2940 return 5;
2941 case AUDIO_SOURCE_ECHO_REFERENCE:
2942 return 4;
2943 case AUDIO_SOURCE_FM_TUNER:
2944 return 3;
2945 case AUDIO_SOURCE_VOICE_RECOGNITION:
2946 return 2;
2947 case AUDIO_SOURCE_HOTWORD:
2948 return 1;
2949 default:
2950 break;
2951 }
2952 return 0;
2953}
2954
2955static struct stream_in *get_priority_input(struct audio_device *adev)
2956{
2957 struct listnode *node;
2958 struct audio_usecase *usecase;
2959 int last_priority = 0, priority;
2960 struct stream_in *priority_in = NULL;
2961 struct stream_in *in;
2962
2963 list_for_each(node, &adev->usecase_list) {
2964 usecase = node_to_item(node, struct audio_usecase, list);
2965 if (usecase->type == PCM_CAPTURE) {
2966 in = usecase->stream.in;
2967 if (!in)
2968 continue;
Krishna Kishor Jha0b7175d2022-07-28 22:33:46 +05302969
2970 if (USECASE_AUDIO_RECORD_FM_VIRTUAL == usecase->id)
2971 continue;
Krishna Kishor Jhaaf83fd82022-11-15 17:54:07 +05302972#ifdef SKIP_INPUT_SOURCE_PRIORITY
2973 // temporary fix to resolve issue when accessing Google Assistant while FM is active.
2974 if (USECASE_AUDIO_RECORD_ECHO_REF_EXT == usecase->id) {
2975 continue;
2976 }
2977#endif
Carter Hsu2e429db2019-05-14 18:50:52 +08002978 priority = source_priority(in->source);
2979
2980 if (priority > last_priority) {
2981 last_priority = priority;
2982 priority_in = in;
2983 }
2984 }
2985 }
2986 return priority_in;
2987}
2988
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002989int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002990{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002991 snd_device_t out_snd_device = SND_DEVICE_NONE;
2992 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002993 struct audio_usecase *usecase = NULL;
2994 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002995 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002996 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302997 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002998 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002999 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003000
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05303001 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
3002
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003003 usecase = get_usecase_from_list(adev, uc_id);
3004 if (usecase == NULL) {
3005 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
3006 return -EINVAL;
3007 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003008
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003009 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08003010 (usecase->type == VOIP_CALL) ||
Derek Chena30a5f42019-12-03 11:17:09 -05003011 (usecase->type == PCM_HFP_CALL)||
Fei Tongaffdf732020-02-20 20:39:05 +08003012 (usecase->type == ICC_CALL) ||
3013 (usecase->type == SYNTH_LOOPBACK)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05303014 if(usecase->stream.out == NULL) {
3015 ALOGE("%s: stream.out is NULL", __func__);
3016 return -EINVAL;
3017 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003018 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS)) {
Guodong Hu267bdf82019-08-12 19:22:32 +08003019 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev,
3020 uc_id);
3021 in_snd_device = audio_extn_auto_hal_get_input_snd_device(adev,
3022 uc_id);
3023 } else {
3024 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05303025 usecase->stream.out, usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08003026 in_snd_device = platform_get_input_snd_device(adev->platform,
3027 NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05303028 &usecase->stream.out->device_list,
3029 usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08003030 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003031 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05303032 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05303033 if (usecase->stream.inout == NULL) {
3034 ALOGE("%s: stream.inout is NULL", __func__);
3035 return -EINVAL;
3036 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003037 assign_devices(&stream_out.device_list, &usecase->stream.inout->out_config.device_list);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05303038 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
3039 stream_out.format = usecase->stream.inout->out_config.format;
3040 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
Jaideep Sharma477917f2020-03-13 18:13:33 +05303041 out_snd_device = platform_get_output_snd_device(adev->platform, &stream_out, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003042 assign_devices(&usecase->device_list,
3043 &usecase->stream.inout->out_config.device_list);
Zhenlin Lian4f947842022-05-14 15:50:52 +05303044 clear_devices(&stream_out.device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05303045 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
3046 if (usecase->stream.inout == NULL) {
3047 ALOGE("%s: stream.inout is NULL", __func__);
3048 return -EINVAL;
3049 }
Manisha Agarwal03297972020-04-17 15:36:55 +05303050 struct listnode out_devices;
3051 list_init(&out_devices);
3052 in_snd_device = platform_get_input_snd_device(adev->platform, NULL,
3053 &out_devices, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003054 assign_devices(&usecase->device_list,
3055 &usecase->stream.inout->in_config.device_list);
Zhenlin Lian4f947842022-05-14 15:50:52 +05303056 clear_devices(&out_devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003057 } else {
3058 /*
3059 * If the voice call is active, use the sound devices of voice call usecase
3060 * so that it would not result any device switch. All the usecases will
3061 * be switched to new device when select_devices() is called for voice call
3062 * usecase. This is to avoid switching devices for voice call when
3063 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07003064 * choose voice call device only if the use case device is
3065 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003066 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08003067 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003068 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08003069 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003070 if ((vc_usecase) && ((is_codec_backend_out_device_type(&vc_usecase->device_list) &&
3071 is_codec_backend_out_device_type(&usecase->device_list)) ||
3072 (is_codec_backend_out_device_type(&vc_usecase->device_list) &&
3073 is_codec_backend_in_device_type(&usecase->device_list)) ||
3074 is_single_device_type_equal(&vc_usecase->device_list,
3075 AUDIO_DEVICE_OUT_HEARING_AID) ||
3076 is_single_device_type_equal(&usecase->device_list,
Robert Lee8a6aaf32019-09-20 16:40:19 +08003077 AUDIO_DEVICE_IN_VOICE_CALL) ||
3078 (is_single_device_type_equal(&usecase->device_list,
Gautam Manam8fa06162021-09-24 10:41:29 +05303079 AUDIO_DEVICE_IN_BUILTIN_MIC) &&
3080 is_single_device_type_equal(&vc_usecase->device_list,
3081 AUDIO_DEVICE_OUT_USB_HEADSET)) ||
3082 (is_single_device_type_equal(&usecase->device_list,
Robert Lee8a6aaf32019-09-20 16:40:19 +08003083 AUDIO_DEVICE_IN_USB_HEADSET) &&
3084 is_single_device_type_equal(&vc_usecase->device_list,
Kamalakar Yalasiri5edba852021-01-28 14:52:38 +05303085 AUDIO_DEVICE_OUT_USB_HEADSET))||
Gautam Manamf4002142021-09-13 22:05:56 +05303086 (is_single_device_type_equal(&usecase->device_list,
3087 AUDIO_DEVICE_IN_USB_HEADSET) &&
3088 is_codec_backend_out_device_type(&vc_usecase->device_list)) ||
Kamalakar Yalasiri5edba852021-01-28 14:52:38 +05303089 (is_single_device_type_equal(&usecase->device_list,
3090 AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) &&
3091 is_codec_backend_out_device_type(&vc_usecase->device_list)))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003092 in_snd_device = vc_usecase->in_snd_device;
3093 out_snd_device = vc_usecase->out_snd_device;
3094 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003095 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08003096 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08003097 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08003098 if ((voip_usecase != NULL) &&
3099 (usecase->type == PCM_PLAYBACK) &&
3100 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08003101 out_snd_device_backend_match = platform_check_backends_match(
3102 voip_usecase->out_snd_device,
3103 platform_get_output_snd_device(
3104 adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05303105 usecase->stream.out, usecase->type));
yidongh02ef86f2017-04-21 15:36:04 +08003106 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003107 if ((voip_usecase) && (is_codec_backend_out_device_type(&voip_usecase->device_list) &&
3108 (is_codec_backend_out_device_type(&usecase->device_list) ||
3109 is_codec_backend_in_device_type(&usecase->device_list)) &&
yidongh02ef86f2017-04-21 15:36:04 +08003110 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07003111 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003112 in_snd_device = voip_usecase->in_snd_device;
3113 out_snd_device = voip_usecase->out_snd_device;
3114 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08003115 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08003116 hfp_ucid = audio_extn_hfp_get_usecase();
3117 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003118 if ((hfp_usecase) && is_codec_backend_out_device_type(&hfp_usecase->device_list)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08003119 in_snd_device = hfp_usecase->in_snd_device;
3120 out_snd_device = hfp_usecase->out_snd_device;
3121 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003122 }
3123 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05303124 if (usecase->stream.out == NULL) {
3125 ALOGE("%s: stream.out is NULL", __func__);
3126 return -EINVAL;
3127 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003128 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003129 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003130 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003131 struct stream_out *voip_out = adev->primary_output;
3132 struct stream_in *voip_in = get_voice_communication_input(adev);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003133 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS))
Guodong Hu267bdf82019-08-12 19:22:32 +08003134 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev, uc_id);
3135 else
3136 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05303137 usecase->stream.out,
3138 usecase->type);
kunleizdcf967a2018-08-07 17:09:11 +08003139 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizdcf967a2018-08-07 17:09:11 +08003140
Eric Laurent637e2d42018-11-15 12:24:31 -08003141 if (voip_usecase)
3142 voip_out = voip_usecase->stream.out;
3143
3144 if (usecase->stream.out == voip_out && voip_in != NULL)
3145 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003146 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003147 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05303148 if (usecase->stream.in == NULL) {
3149 ALOGE("%s: stream.in is NULL", __func__);
3150 return -EINVAL;
3151 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003152 assign_devices(&usecase->device_list, &usecase->stream.in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003153 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003154 if (in_snd_device == SND_DEVICE_NONE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003155 struct listnode out_devices;
Eric Laurent637e2d42018-11-15 12:24:31 -08003156 struct stream_in *voip_in = get_voice_communication_input(adev);
Carter Hsu2e429db2019-05-14 18:50:52 +08003157 struct stream_in *priority_in = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08003158
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003159 list_init(&out_devices);
Eric Laurent637e2d42018-11-15 12:24:31 -08003160 if (voip_in != NULL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003161 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
3162 USECASE_AUDIO_PLAYBACK_VOIP);
3163
Carter Hsu2e429db2019-05-14 18:50:52 +08003164 usecase->stream.in->enable_ec_port = false;
3165
Zhou Song503196b2021-07-23 17:31:05 +08003166 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY ||
3167 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY2) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003168 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_TELEPHONY_TX, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08003169 } else if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003170 assign_devices(&out_devices, &voip_usecase->stream.out->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08003171 } else if (adev->primary_output &&
3172 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003173 assign_devices(&out_devices, &adev->primary_output->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08003174 } else {
3175 /* forcing speaker o/p device to get matching i/p pair
3176 in case o/p is not routed from same primary HAL */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003177 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08003178 }
Carter Hsu2e429db2019-05-14 18:50:52 +08003179 priority_in = voip_in;
3180 } else {
Krishna Kishor Jhaaf83fd82022-11-15 17:54:07 +05303181#ifdef SKIP_INPUT_SOURCE_PRIORITY
Kogara Naveen Kumar912313f2022-11-23 09:38:28 +05303182 ALOGD("%s: Skipping get_priority_input for use-case-id:%d(%s).", __func__, uc_id, use_case_table[uc_id]);
Krishna Kishor Jhaaf83fd82022-11-15 17:54:07 +05303183#else
Carter Hsu2e429db2019-05-14 18:50:52 +08003184 priority_in = get_priority_input(adev);
Krishna Kishor Jhaaf83fd82022-11-15 17:54:07 +05303185#endif
Carter Hsu2e429db2019-05-14 18:50:52 +08003186
Susan Wang727dd6b2021-03-26 11:28:59 -04003187 if (!priority_in ||
3188 audio_extn_auto_hal_overwrite_priority_for_auto(usecase->stream.in))
Carter Hsu2e429db2019-05-14 18:50:52 +08003189 priority_in = usecase->stream.in;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003190 }
Huicheng Liu1404ba12020-09-11 01:03:25 -04003191 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_IN_BUS)){
3192 in_snd_device = audio_extn_auto_hal_get_snd_device_for_car_audio_stream(priority_in->car_audio_stream);
3193 }
3194 else
3195 in_snd_device = platform_get_input_snd_device(adev->platform,
3196 priority_in,
3197 &out_devices,
3198 usecase->type);
Zhenlin Lian4f947842022-05-14 15:50:52 +05303199 clear_devices(&out_devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003200 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003201 }
3202 }
3203
3204 if (out_snd_device == usecase->out_snd_device &&
3205 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05303206
3207 if (!force_device_switch(usecase))
3208 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003209 }
3210
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003211 if (!compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS) &&
Guodong Hu267bdf82019-08-12 19:22:32 +08003212 ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003213 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready()))) {
Guodong Hu267bdf82019-08-12 19:22:32 +08003214 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
3215 return 0;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303216 }
3217
Aalique Grahame22e49102018-12-18 14:23:57 -08003218 if (out_snd_device != SND_DEVICE_NONE &&
3219 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
3220 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
3221 __func__,
3222 use_case_table[uc_id],
3223 adev->last_logged_snd_device[uc_id][0],
3224 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
3225 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
3226 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
3227 -1,
3228 out_snd_device,
3229 platform_get_snd_device_name(out_snd_device),
3230 platform_get_snd_device_acdb_id(out_snd_device));
3231 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
3232 }
3233 if (in_snd_device != SND_DEVICE_NONE &&
3234 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
3235 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
3236 __func__,
3237 use_case_table[uc_id],
3238 adev->last_logged_snd_device[uc_id][1],
3239 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
3240 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
3241 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
3242 -1,
3243 in_snd_device,
3244 platform_get_snd_device_name(in_snd_device),
3245 platform_get_snd_device_acdb_id(in_snd_device));
3246 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
3247 }
3248
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003249
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003250 /*
3251 * Limitation: While in call, to do a device switch we need to disable
3252 * and enable both RX and TX devices though one of them is same as current
3253 * device.
3254 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07003255 if ((usecase->type == VOICE_CALL) &&
3256 (usecase->in_snd_device != SND_DEVICE_NONE) &&
3257 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07003258 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07003259 }
3260
3261 if (((usecase->type == VOICE_CALL) ||
3262 (usecase->type == VOIP_CALL)) &&
3263 (usecase->out_snd_device != SND_DEVICE_NONE)) {
3264 /* Disable sidetone only if voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303265 if (voice_is_call_state_active_in_call(adev) ||
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07003266 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07003267 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003268
3269 /* Disable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303270 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003271 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08003272 }
3273
Aalique Grahame22e49102018-12-18 14:23:57 -08003274 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
3275 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003276 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303277 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08003278 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
3279 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
3280 else
3281 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303282 }
3283
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003284 /* Disable current sound devices */
3285 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003286 disable_audio_route(adev, usecase);
3287 disable_snd_device(adev, usecase->out_snd_device);
Gautam Manam274f4752021-09-24 10:58:49 +05303288 if (usecase->id == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
3289 disable_snd_device(adev, SND_DEVICE_OUT_HAPTICS);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003290 }
3291
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003292 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003293 disable_audio_route(adev, usecase);
3294 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003295 }
3296
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08003297 /* Applicable only on the targets that has external modem.
3298 * New device information should be sent to modem before enabling
3299 * the devices to reduce in-call device switch time.
3300 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07003301 if ((usecase->type == VOICE_CALL) &&
3302 (usecase->in_snd_device != SND_DEVICE_NONE) &&
3303 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08003304 status = platform_switch_voice_call_enable_device_config(adev->platform,
3305 out_snd_device,
3306 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07003307 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08003308
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003309 /* Enable new sound devices */
3310 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08003311 check_usecases_codec_backend(adev, usecase, out_snd_device);
Saurav Kumarc1411662020-10-14 10:50:45 +05303312 check_and_configure_headphone(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05303313 if (platform_check_codec_asrc_support(adev->platform))
3314 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003315 enable_snd_device(adev, out_snd_device);
Zhou Songd9bd9302020-08-04 16:34:45 +08003316 /* Enable haptics device for haptic usecase */
3317 if (usecase->id == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
3318 enable_snd_device(adev, SND_DEVICE_OUT_HAPTICS);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003319 }
3320
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07003321 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303322 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003323 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07003324 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003325
Lakshman Chaluvarajuab7e5572020-10-28 19:29:23 +05303326 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL)
Eric Laurentb23d5282013-05-14 15:27:20 -07003327 status = platform_switch_voice_call_device_post(adev->platform,
3328 out_snd_device,
3329 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08003330
sangwoo170731f2013-06-08 15:36:36 +09003331 usecase->in_snd_device = in_snd_device;
3332 usecase->out_snd_device = out_snd_device;
3333
Dhananjay Kumard6d32152016-10-13 16:11:03 +05303334 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
3335 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05303336 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003337 if ((24 == usecase->stream.out->bit_width) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003338 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_SPEAKER)) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003339 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3340 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
3341 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
3342 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
3343 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
3344 /*
3345 * To best utlize DSP, check if the stream sample rate is supported/multiple of
3346 * configured device sample rate, if not update the COPP rate to be equal to the
3347 * device sample rate, else open COPP at stream sample rate
3348 */
3349 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
3350 usecase->stream.out->sample_rate,
3351 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05303352 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
Preetam Singh Ranawat590d0432019-09-30 14:39:47 +05303353 out_snd_device != SND_DEVICE_OUT_HEADPHONES &&
3354 out_snd_device != SND_DEVICE_OUT_HEADPHONES_HIFI_FILTER &&
Ashish Jain4826f6c2017-02-06 13:33:20 +05303355 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003356 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
3357 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +05303358#ifdef PLATFORM_AUTO
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +05303359 if (!(compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS) && ((usecase->stream.out->flags &
3360 (audio_output_flags_t)AUDIO_OUTPUT_FLAG_SYS_NOTIFICATION) || (usecase->stream.out->flags &
Kogara Naveen Kumare88ee942022-12-22 17:01:12 +05303361 (audio_output_flags_t)AUDIO_OUTPUT_FLAG_PHONE) || (usecase->stream.out->flags &
3362 (audio_output_flags_t)AUDIO_OUTPUT_FLAG_NAV_GUIDANCE) || (usecase->stream.out->flags &
3363 (audio_output_flags_t)AUDIO_OUTPUT_FLAG_ALERTS)))) {
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +05303364 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3365 }
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +05303366#else
3367 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3368#endif
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003369 }
Weiyin Jiangcdece202019-07-08 16:13:16 +08003370 }
3371 enable_audio_route(adev, usecase);
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003372
Shalini Manjunatha5e610912020-12-29 13:02:25 +05303373 if (uc_id == USECASE_AUDIO_PLAYBACK_VOIP) {
3374 struct stream_in *voip_in = get_voice_communication_input(adev);
3375 struct audio_usecase *voip_in_usecase = NULL;
3376 voip_in_usecase = get_usecase_from_list(adev, USECASE_AUDIO_RECORD_VOIP);
3377 if (voip_in != NULL &&
3378 voip_in_usecase != NULL &&
3379 !(out_snd_device == AUDIO_DEVICE_OUT_SPEAKER ||
3380 out_snd_device == AUDIO_DEVICE_OUT_SPEAKER_SAFE) &&
3381 (voip_in_usecase->in_snd_device ==
3382 platform_get_input_snd_device(adev->platform, voip_in,
3383 &usecase->stream.out->device_list,usecase->type))) {
3384 /*
3385 * if VOIP TX is enabled before VOIP RX, needs to re-route the TX path
3386 * for enabling echo-reference-voip with correct port
3387 */
3388 ALOGD("%s: VOIP TX is enabled before VOIP RX,needs to re-route the TX path",__func__);
3389 disable_audio_route(adev, voip_in_usecase);
3390 disable_snd_device(adev, voip_in_usecase->in_snd_device);
3391 enable_snd_device(adev, voip_in_usecase->in_snd_device);
3392 enable_audio_route(adev, voip_in_usecase);
3393 }
3394 }
Ramjee Singhcdf67af2021-09-29 14:20:27 +05303395 if (voice_extn_compress_voip_is_active(adev)) {
3396 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
3397 USECASE_COMPRESS_VOIP_CALL);
3398 /*
3399 * If only compress voip input is opened voip out will be primary out.
3400 * Need to consider re-routing to select correct i/p pair
3401 */
3402 if ((voip_usecase != NULL) &&
3403 (usecase->type == PCM_PLAYBACK) &&
3404 (usecase->stream.out == voip_usecase->stream.out)) {
3405 in_snd_device = platform_get_input_snd_device(adev->platform,
3406 NULL,
3407 &usecase->stream.out->device_list,
3408 usecase->type);
3409 if (voip_usecase->in_snd_device != in_snd_device ) {
3410 ALOGD("%s:Re routing compress voip tx snd device matching voip rx pair",
3411 __func__);
3412 disable_audio_route(adev, voip_usecase);
3413 disable_snd_device(adev, voip_usecase->in_snd_device);
3414 voip_usecase->in_snd_device = in_snd_device;
3415 voip_usecase->out_snd_device = usecase->out_snd_device;
3416 /* Route all TX usecase to Compress voip BE */
3417 check_usecases_capture_codec_backend(adev, voip_usecase, in_snd_device);
3418 enable_snd_device(adev, in_snd_device);
3419 /* Send Voice related calibration for RX /TX pair */
3420 status = platform_switch_voice_call_device_post(adev->platform,
3421 out_snd_device,
3422 in_snd_device);
3423 enable_audio_route(adev, voip_usecase);
3424 }
3425 }
3426 }
Shalini Manjunatha5e610912020-12-29 13:02:25 +05303427
3428
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08003429 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08003430
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003431 /* If input stream is already running then effect needs to be
3432 applied on the new input device that's being enabled here. */
Eric Laurent637e2d42018-11-15 12:24:31 -08003433 if (in_snd_device != SND_DEVICE_NONE)
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003434 check_and_enable_effect(adev);
3435
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003436 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003437 /* Enable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303438 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003439 voice_check_and_update_aanc_path(adev, out_snd_device, true);
3440
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003441 /* Enable sidetone only if other voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303442 if (voice_is_call_state_active_in_call(adev) ||
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003443 voice_extn_compress_voip_is_started(adev))
3444 voice_set_sidetone(adev, out_snd_device, true);
3445 }
3446
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003447 /* Applicable only on the targets that has external modem.
3448 * Enable device command should be sent to modem only after
3449 * enabling voice call mixer controls
3450 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07003451 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003452 status = platform_switch_voice_call_usecase_route_post(adev->platform,
3453 out_snd_device,
3454 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303455
3456 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003457 struct stream_in *in = adev_get_active_input(adev);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303458 if (usecase->type == VOIP_CALL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003459 if (in != NULL && !in->standby) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303460 if (is_bt_soc_on(adev) == false){
3461 ALOGD("BT SCO MIC disconnected while in connection");
Eric Laurent637e2d42018-11-15 12:24:31 -08003462 if (in->pcm != NULL)
3463 pcm_stop(in->pcm);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303464 }
3465 }
3466 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
3467 && usecase->stream.out->started) {
3468 if (is_bt_soc_on(adev) == false) {
3469 ALOGD("BT SCO/A2DP disconnected while in connection");
3470 out_standby_l(&usecase->stream.out->stream.common);
3471 }
3472 }
3473 } else if ((usecase->stream.out != NULL) &&
3474 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05303475 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
3476 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Weiyin Jiang0d373242019-07-25 13:18:17 +08003477 (usecase->type != PCM_CAPTURE) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303478 usecase->stream.out->started) {
3479 if (is_bt_soc_on(adev) == false) {
3480 ALOGD("BT SCO/A2dp disconnected while in connection");
3481 out_standby_l(&usecase->stream.out->stream.common);
3482 }
3483 }
3484 }
3485
Yung Ti Su70cb8242018-06-22 17:38:47 +08003486 if (usecase->type != PCM_CAPTURE && usecase == voip_usecase) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003487 struct stream_out *voip_out = voip_usecase->stream.out;
3488 audio_extn_utils_send_app_type_gain(adev,
3489 voip_out->app_type_cfg.app_type,
3490 &voip_out->app_type_cfg.gain[0]);
3491 }
3492
Ajender Reddyb940b832021-07-07 11:51:42 +05303493 ALOGD("%s: done",__func__);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303494
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003495 return status;
3496}
3497
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003498static int stop_input_stream(struct stream_in *in)
3499{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303500 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003501 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05303502
3503 if (in == NULL) {
3504 ALOGE("%s: stream_in ptr is NULL", __func__);
3505 return -EINVAL;
3506 }
3507
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003508 struct audio_device *adev = in->dev;
Carter Hsu2e429db2019-05-14 18:50:52 +08003509 struct stream_in *priority_in = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003510
Eric Laurent994a6932013-07-17 11:51:42 -07003511 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003512 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003513 uc_info = get_usecase_from_list(adev, in->usecase);
3514 if (uc_info == NULL) {
3515 ALOGE("%s: Could not find the usecase (%d) in the list",
3516 __func__, in->usecase);
3517 return -EINVAL;
3518 }
Krishna Kishor Jhaaf83fd82022-11-15 17:54:07 +05303519#ifdef SKIP_INPUT_SOURCE_PRIORITY
3520 // Skip (1)fm-virtual-record and (2)echo-reference-external from get-priority-input logic.
3521 // See comment in function select_devices() before call to get_priority_input()
3522 if ((in->usecase == USECASE_AUDIO_RECORD_FM_VIRTUAL || in->usecase == USECASE_AUDIO_RECORD_ECHO_REF_EXT)){
3523 ALOGD("%s: Skipping get_priority_input for use-case-id:%d/%s.", __func__, in->usecase, use_case_table[in->usecase]);
3524 } else {
3525 priority_in = get_priority_input(adev);
3526 }
3527#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003528
Carter Hsu2e429db2019-05-14 18:50:52 +08003529 priority_in = get_priority_input(adev);
3530
Krishna Kishor Jhaaf83fd82022-11-15 17:54:07 +05303531#endif
3532
Derek Chenea197282019-01-07 17:35:01 -08003533 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3534 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003535
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003536 /* Close in-call recording streams */
3537 voice_check_and_stop_incall_rec_usecase(adev, in);
3538
Eric Laurent150dbfe2013-02-27 14:31:02 -08003539 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003540 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003541
3542 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003543 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003544
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003545 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303546 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_PRIMARY);
3547
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003548 list_remove(&uc_info->list);
Zhenlin Lian4f947842022-05-14 15:50:52 +05303549 clear_devices(&uc_info->device_list);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003550 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003551
Carter Hsu2e429db2019-05-14 18:50:52 +08003552 if (priority_in == in) {
3553 priority_in = get_priority_input(adev);
Sujin Panicker110f7942021-08-26 17:01:22 +05303554 if (priority_in) {
3555 if (is_usb_in_device_type(&priority_in->device_list)) {
3556 if (audio_extn_usb_connected(NULL))
3557 select_devices(adev, priority_in->usecase);
3558 } else {
3559 select_devices(adev, priority_in->usecase);
3560 }
3561 }
Carter Hsu2e429db2019-05-14 18:50:52 +08003562 }
3563
Vatsal Buchac09ae062018-11-14 13:25:08 +05303564 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07003565 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003566 return ret;
3567}
3568
3569int start_input_stream(struct stream_in *in)
3570{
3571 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08003572 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003573 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05303574
3575 if (in == NULL) {
3576 ALOGE("%s: stream_in ptr is NULL", __func__);
3577 return -EINVAL;
3578 }
3579
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003580 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07003581 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07003582 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003583
Mingming Yin2664a5b2015-09-03 10:53:11 -07003584 if (get_usecase_from_list(adev, usecase) == NULL)
3585 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303586 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
3587 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003588
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303589 if (CARD_STATUS_OFFLINE == in->card_status||
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05003590 CARD_STATUS_OFFLINE == adev->card_status ||
3591 POWER_POLICY_STATUS_OFFLINE == adev->in_power_policy) {
3592 ALOGW("in->card_status or adev->card_status or adev->input_power offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303593 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303594 goto error_config;
3595 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303596
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003597 if (is_sco_in_device_type(&in->device_list)) {
Lakshman Chaluvaraju87f53aa2021-02-02 15:50:11 +05303598 if (!adev->bt_sco_on || audio_extn_a2dp_source_is_ready()) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303599 ALOGE("%s: SCO profile is not ready, return error", __func__);
3600 ret = -EIO;
3601 goto error_config;
3602 }
3603 }
3604
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003605 /* Check if source matches incall recording usecase criteria */
3606 ret = voice_check_and_set_incall_rec_usecase(adev, in);
3607 if (ret)
3608 goto error_config;
3609 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07003610 ALOGV("%s: usecase(%d)", __func__, in->usecase);
3611
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303612 if (audio_extn_cin_attached_usecase(in))
3613 audio_extn_cin_acquire_usecase(in);
3614
Mingming Yin2664a5b2015-09-03 10:53:11 -07003615 if (get_usecase_from_list(adev, in->usecase) != NULL) {
3616 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
3617 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Weiyin Jiang38c0e612020-09-10 16:10:51 +08003618 ret = -EINVAL;
3619 goto error_config;
Mingming Yin2664a5b2015-09-03 10:53:11 -07003620 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003621
Eric Laurentb23d5282013-05-14 15:27:20 -07003622 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003623 if (in->pcm_device_id < 0) {
3624 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
3625 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08003626 ret = -EINVAL;
3627 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003628 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003629
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003630 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003631
3632 if (!uc_info) {
3633 ret = -ENOMEM;
3634 goto error_config;
3635 }
3636
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003637 uc_info->id = in->usecase;
3638 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003639 uc_info->stream.in = in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003640 list_init(&uc_info->device_list);
3641 assign_devices(&uc_info->device_list, &in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003642 uc_info->in_snd_device = SND_DEVICE_NONE;
3643 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003644
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003645 list_add_tail(&adev->usecase_list, &uc_info->list);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003646 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303647 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3648 adev->perf_lock_opts,
3649 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003650 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003651
Derek Chenea197282019-01-07 17:35:01 -08003652 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3653 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003654
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05303655 android_atomic_acquire_cas(true, false, &(in->capture_stopped));
3656
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303657 if (audio_extn_cin_attached_usecase(in)) {
Manish Dewangan46e07982018-12-13 18:18:59 +05303658 ret = audio_extn_cin_open_input_stream(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303659 if (ret)
3660 goto error_open;
3661 else
3662 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003663 }
3664
Haynes Mathew George16081042017-05-31 17:16:49 -07003665 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003666 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003667 ALOGE("%s: pcm stream not ready", __func__);
3668 goto error_open;
3669 }
3670 ret = pcm_start(in->pcm);
3671 if (ret < 0) {
3672 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3673 goto error_open;
3674 }
3675 } else {
3676 unsigned int flags = PCM_IN | PCM_MONOTONIC;
3677 unsigned int pcm_open_retry_count = 0;
3678
Zhou Song62ea0282020-03-22 19:53:01 +08003679 if ((in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) ||
3680 (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003681 flags |= PCM_MMAP | PCM_NOIRQ;
3682 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
3683 } else if (in->realtime) {
3684 flags |= PCM_MMAP | PCM_NOIRQ;
3685 }
3686
Garmond Leunge2433c32017-09-28 21:51:22 -07003687 if (audio_extn_ffv_get_stream() == in) {
3688 ALOGD("%s: ffv stream, update pcm config", __func__);
3689 audio_extn_ffv_update_pcm_config(&config);
3690 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003691 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3692 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3693
3694 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003695 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07003696 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07003697 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003698 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303699 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303700 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3701 adev->card_status = CARD_STATUS_OFFLINE;
3702 in->card_status = CARD_STATUS_OFFLINE;
3703 ret = -EIO;
3704 goto error_open;
3705 }
3706
Haynes Mathew George16081042017-05-31 17:16:49 -07003707 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3708 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3709 if (in->pcm != NULL) {
3710 pcm_close(in->pcm);
3711 in->pcm = NULL;
3712 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003713 if (pcm_open_retry_count == 0) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003714 ret = -EIO;
3715 goto error_open;
3716 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003717 pcm_open_retry_count--;
Haynes Mathew George16081042017-05-31 17:16:49 -07003718 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3719 continue;
3720 }
3721 break;
3722 }
3723
3724 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003725 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07003726 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003727 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003728 if (ret < 0) {
3729 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3730 pcm_close(in->pcm);
3731 in->pcm = NULL;
3732 goto error_open;
3733 }
Vaibhav Raut5f3bf222023-02-06 17:45:22 +05303734 if (in->flags & (AUDIO_INPUT_FLAG_FAST | AUDIO_INPUT_FLAG_RAW))
Narsinga Rao Chellaa6e1f702021-10-22 13:57:32 +05303735 register_in_stream(in);
Haynes Mathew George16081042017-05-31 17:16:49 -07003736 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003737 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07003738 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003739 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003740 if (ret < 0) {
3741 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003742 pcm_close(in->pcm);
3743 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003744 goto error_open;
3745 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003746 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003747 }
3748
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003749 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07003750 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
3751 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003752
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003753 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303754 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
3755
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303756done_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003757 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303758 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Manisha Agarwal4c2402e2020-10-21 12:02:57 +05303759 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303760 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003761 return ret;
3762
3763error_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003764 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303765 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003766 stop_input_stream(in);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003767
Eric Laurentc8400632013-02-14 19:04:54 -08003768error_config:
Weiyin Jiang38c0e612020-09-10 16:10:51 +08003769 if (audio_extn_cin_attached_usecase(in))
3770 audio_extn_cin_close_input_stream(in);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303771 /*
3772 * sleep 50ms to allow sufficient time for kernel
3773 * drivers to recover incases like SSR.
3774 */
3775 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003776 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303777 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003778 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003779}
3780
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003781void lock_input_stream(struct stream_in *in)
3782{
3783 pthread_mutex_lock(&in->pre_lock);
3784 pthread_mutex_lock(&in->lock);
3785 pthread_mutex_unlock(&in->pre_lock);
3786}
3787
3788void lock_output_stream(struct stream_out *out)
3789{
3790 pthread_mutex_lock(&out->pre_lock);
3791 pthread_mutex_lock(&out->lock);
3792 pthread_mutex_unlock(&out->pre_lock);
3793}
3794
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003795/* must be called with out->lock locked */
3796static int send_offload_cmd_l(struct stream_out* out, int command)
3797{
3798 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
3799
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003800 if (!cmd) {
3801 ALOGE("failed to allocate mem for command 0x%x", command);
3802 return -ENOMEM;
3803 }
3804
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003805 ALOGVV("%s %d", __func__, command);
3806
3807 cmd->cmd = command;
3808 list_add_tail(&out->offload_cmd_list, &cmd->node);
3809 pthread_cond_signal(&out->offload_cond);
3810 return 0;
3811}
3812
Gautam Manam14c198b2020-12-24 14:08:04 +05303813/* must be called with out->lock */
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003814static void stop_compressed_output_l(struct stream_out *out)
3815{
Gautam Manam14c198b2020-12-24 14:08:04 +05303816 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003817 out->offload_state = OFFLOAD_STATE_IDLE;
Gautam Manam14c198b2020-12-24 14:08:04 +05303818 pthread_mutex_unlock(&out->latch_lock);
Weiyin Jiang906db3c2021-03-02 13:17:04 +08003819
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003820 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003821 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003822 if (out->compr != NULL) {
3823 compress_stop(out->compr);
3824 while (out->offload_thread_blocked) {
3825 pthread_cond_wait(&out->cond, &out->lock);
3826 }
3827 }
3828}
3829
Varun Balaraje49253e2017-07-06 19:48:56 +05303830bool is_interactive_usecase(audio_usecase_t uc_id)
3831{
3832 unsigned int i;
3833 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
3834 if (uc_id == interactive_usecases[i])
3835 return true;
3836 }
3837 return false;
3838}
3839
3840static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
3841{
3842 audio_usecase_t ret_uc = USECASE_INVALID;
3843 unsigned int intract_uc_index;
3844 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3845
3846 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
3847 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
3848 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
3849 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
3850 ret_uc = interactive_usecases[intract_uc_index];
3851 break;
3852 }
3853 }
3854
3855 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
3856 return ret_uc;
3857}
3858
3859static void free_interactive_usecase(struct audio_device *adev,
3860 audio_usecase_t uc_id)
3861{
3862 unsigned int interact_uc_index;
3863 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3864
3865 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
3866 if (interactive_usecases[interact_uc_index] == uc_id) {
3867 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
3868 break;
3869 }
3870 }
3871 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
3872}
3873
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003874bool is_offload_usecase(audio_usecase_t uc_id)
3875{
3876 unsigned int i;
3877 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
3878 if (uc_id == offload_usecases[i])
3879 return true;
3880 }
3881 return false;
3882}
3883
Dhananjay Kumarac341582017-02-23 23:42:25 +05303884static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003885{
vivek mehta446c3962015-09-14 10:57:35 -07003886 audio_usecase_t ret_uc = USECASE_INVALID;
3887 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003888 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003889 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05303890 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07003891 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
3892 else
3893 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003894
vivek mehta446c3962015-09-14 10:57:35 -07003895 pthread_mutex_lock(&adev->lock);
3896 if (get_usecase_from_list(adev, ret_uc) != NULL)
3897 ret_uc = USECASE_INVALID;
3898 pthread_mutex_unlock(&adev->lock);
3899
3900 return ret_uc;
3901 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003902
3903 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003904 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3905 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3906 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3907 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003908 break;
3909 }
3910 }
vivek mehta446c3962015-09-14 10:57:35 -07003911
3912 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3913 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003914}
3915
3916static void free_offload_usecase(struct audio_device *adev,
3917 audio_usecase_t uc_id)
3918{
vivek mehta446c3962015-09-14 10:57:35 -07003919 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003920 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003921
3922 if (!adev->multi_offload_enable)
3923 return;
3924
3925 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3926 if (offload_usecases[offload_uc_index] == uc_id) {
3927 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003928 break;
3929 }
3930 }
3931 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3932}
3933
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003934static void *offload_thread_loop(void *context)
3935{
3936 struct stream_out *out = (struct stream_out *) context;
3937 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003938 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003939
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003940 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08003941 set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003942 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3943
3944 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003945 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003946 out->offload_state = OFFLOAD_STATE_IDLE;
3947 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003948 for (;;) {
3949 struct offload_cmd *cmd = NULL;
3950 stream_callback_event_t event;
3951 bool send_callback = false;
3952
3953 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3954 __func__, list_empty(&out->offload_cmd_list),
3955 out->offload_state);
3956 if (list_empty(&out->offload_cmd_list)) {
3957 ALOGV("%s SLEEPING", __func__);
3958 pthread_cond_wait(&out->offload_cond, &out->lock);
3959 ALOGV("%s RUNNING", __func__);
3960 continue;
3961 }
3962
3963 item = list_head(&out->offload_cmd_list);
3964 cmd = node_to_item(item, struct offload_cmd, node);
3965 list_remove(item);
3966
3967 ALOGVV("%s STATE %d CMD %d out->compr %p",
3968 __func__, out->offload_state, cmd->cmd, out->compr);
3969
3970 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3971 free(cmd);
3972 break;
3973 }
3974
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003975 // allow OFFLOAD_CMD_ERROR reporting during standby
3976 // this is needed to handle failures during compress_open
3977 // Note however that on a pause timeout, the stream is closed
3978 // and no offload usecase will be active. Therefore this
3979 // special case is needed for compress_open failures alone
3980 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3981 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003982 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003983 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003984 pthread_cond_signal(&out->cond);
3985 continue;
3986 }
3987 out->offload_thread_blocked = true;
3988 pthread_mutex_unlock(&out->lock);
3989 send_callback = false;
3990 switch(cmd->cmd) {
3991 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003992 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003993 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003994 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003995 send_callback = true;
3996 event = STREAM_CBK_EVENT_WRITE_READY;
3997 break;
3998 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003999 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05304000 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004001 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05304002 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004003 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05304004 if (ret < 0)
4005 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05304006 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05304007 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08004008 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08004009 else
4010 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08004011 if (-ENETRESET != ret && !(-EINTR == ret &&
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05004012 (CARD_STATUS_OFFLINE == out->card_status ||
4013 POWER_POLICY_STATUS_OFFLINE == adev->out_power_policy))) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05304014 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304015 pthread_mutex_lock(&out->lock);
4016 out->send_new_metadata = 1;
4017 out->send_next_track_params = true;
4018 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05304019 event = STREAM_CBK_EVENT_DRAIN_READY;
4020 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
4021 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304022 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004023 break;
4024 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004025 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08004026 ret = compress_drain(out->compr);
4027 ALOGD("copl(%p):out of compress_drain", out);
4028 // EINTR check avoids drain interruption due to SSR
4029 if (-ENETRESET != ret && !(-EINTR == ret &&
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05004030 (CARD_STATUS_OFFLINE == out->card_status ||
4031 POWER_POLICY_STATUS_OFFLINE == adev->out_power_policy))) {
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08004032 send_callback = true;
4033 event = STREAM_CBK_EVENT_DRAIN_READY;
4034 } else
4035 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004036 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304037 case OFFLOAD_CMD_ERROR:
4038 ALOGD("copl(%p): sending error callback to AF", out);
4039 send_callback = true;
4040 event = STREAM_CBK_EVENT_ERROR;
4041 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004042 default:
4043 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
4044 break;
4045 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004046 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004047 out->offload_thread_blocked = false;
4048 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004049 if (send_callback && out->client_callback) {
4050 ALOGVV("%s: sending client_callback event %d", __func__, event);
4051 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07004052 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004053 free(cmd);
4054 }
4055
4056 pthread_cond_signal(&out->cond);
4057 while (!list_empty(&out->offload_cmd_list)) {
4058 item = list_head(&out->offload_cmd_list);
4059 list_remove(item);
4060 free(node_to_item(item, struct offload_cmd, node));
4061 }
4062 pthread_mutex_unlock(&out->lock);
4063
4064 return NULL;
4065}
4066
4067static int create_offload_callback_thread(struct stream_out *out)
4068{
4069 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
4070 list_init(&out->offload_cmd_list);
4071 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
4072 offload_thread_loop, out);
4073 return 0;
4074}
4075
4076static int destroy_offload_callback_thread(struct stream_out *out)
4077{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004078 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004079 stop_compressed_output_l(out);
4080 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
4081
4082 pthread_mutex_unlock(&out->lock);
4083 pthread_join(out->offload_thread, (void **) NULL);
4084 pthread_cond_destroy(&out->offload_cond);
4085
4086 return 0;
4087}
4088
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004089static int stop_output_stream(struct stream_out *out)
4090{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304091 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004092 struct audio_usecase *uc_info;
4093 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08004094 bool has_voip_usecase =
4095 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004096
Eric Laurent994a6932013-07-17 11:51:42 -07004097 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004098 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004099 uc_info = get_usecase_from_list(adev, out->usecase);
4100 if (uc_info == NULL) {
4101 ALOGE("%s: Could not find the usecase (%d) in the list",
4102 __func__, out->usecase);
4103 return -EINVAL;
4104 }
4105
Zhou Songbaddf9f2020-11-20 13:57:39 +08004106 out->a2dp_muted = false;
4107
Derek Chenea197282019-01-07 17:35:01 -08004108 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
4109 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08004110
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004111 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304112 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004113 if (adev->visualizer_stop_output != NULL)
4114 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004115
4116 audio_extn_dts_remove_state_notifier_node(out->usecase);
4117
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004118 if (adev->offload_effects_stop_output != NULL)
4119 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07004120 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
4121 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4122 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004123 }
Eric Laurentc4aef752013-09-12 17:45:53 -07004124
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004125 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
4126 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07004127 voice_set_device_mute_flag(adev, false);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004128 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07004129
Eric Laurent150dbfe2013-02-27 14:31:02 -08004130 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07004131 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004132
4133 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07004134 disable_snd_device(adev, uc_info->out_snd_device);
Zhou Songd9bd9302020-08-04 16:34:45 +08004135 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
4136 disable_snd_device(adev, SND_DEVICE_OUT_HAPTICS);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004137
Aalique Grahame22e49102018-12-18 14:23:57 -08004138 audio_extn_extspk_update(adev->extspk);
4139
Xiaojun Sang785b5da2017-08-03 15:52:29 +08004140 if (is_offload_usecase(out->usecase)) {
4141 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
4142 adev->dsp_bit_width_enforce_mode,
4143 false);
4144 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004145 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07004146 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
4147 false);
4148
4149 if (ret != 0)
4150 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
4151 /* default service interval was successfully updated,
4152 reopen USB backend with new service interval */
4153 ret = 0;
4154 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08004155
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004156 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304157 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004158 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304159 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004160 ALOGV("Disable passthrough , reset mixer to pcm");
4161 /* NO_PASSTHROUGH */
Meng Wang4c32fb42020-01-16 17:57:11 +08004162#ifdef AUDIO_GKI_ENABLED
4163 /* out->compr_config.codec->reserved[0] is for compr_passthr */
4164 out->compr_config.codec->reserved[0] = 0;
4165#else
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004166 out->compr_config.codec->compr_passthr = 0;
Meng Wang4c32fb42020-01-16 17:57:11 +08004167#endif
Mingming Yin21854652016-04-13 11:54:02 -07004168 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004169 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
4170 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07004171
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304172 /* Must be called after removing the usecase from list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004173 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL))
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05304174 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304175
Manish Dewangan21a850a2017-08-14 12:03:55 +05304176 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07004177 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
4178 if (ret < 0)
4179 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
4180 }
4181
Zhou Song642ec432020-12-23 16:11:10 +08004182 /* trigger voip input to reroute when voip output changes to hearing aid */
Aalique Grahame22e49102018-12-18 14:23:57 -08004183 if (has_voip_usecase ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004184 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08004185 struct listnode *node;
4186 struct audio_usecase *usecase;
4187 list_for_each(node, &adev->usecase_list) {
4188 usecase = node_to_item(node, struct audio_usecase, list);
Zhou Song642ec432020-12-23 16:11:10 +08004189 if (usecase->type == PCM_PLAYBACK || usecase == uc_info ||
4190 (usecase->type == PCM_CAPTURE &&
Revathi Uddarajud9f23d92020-07-27 10:55:06 +05304191 usecase->id != USECASE_AUDIO_RECORD_VOIP &&
Zhou Song642ec432020-12-23 16:11:10 +08004192 usecase->id != USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY))
Aalique Grahame22e49102018-12-18 14:23:57 -08004193 continue;
4194
4195 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
4196 __func__, usecase->id, use_case_table[usecase->id],
4197 out->usecase, use_case_table[out->usecase]);
4198 select_devices(adev, usecase->id);
4199 }
4200 }
4201
Zhenlin Lian4f947842022-05-14 15:50:52 +05304202 clear_devices(&uc_info->device_list);
Garmond Leung5fd0b552018-04-17 11:56:12 -07004203 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07004204 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004205 return ret;
4206}
4207
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004208struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
4209 unsigned int flags, unsigned int pcm_open_retry_count,
4210 struct pcm_config *config)
4211{
4212 struct pcm* pcm = NULL;
4213
4214 while (1) {
4215 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
4216 if (pcm == NULL || !pcm_is_ready(pcm)) {
4217 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
4218 if (pcm != NULL) {
4219 pcm_close(pcm);
4220 pcm = NULL;
4221 }
Weiyin Jiang72197252019-10-09 11:49:32 +08004222 if (pcm_open_retry_count == 0)
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004223 return NULL;
4224
Weiyin Jiang72197252019-10-09 11:49:32 +08004225 pcm_open_retry_count--;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004226 usleep(PROXY_OPEN_WAIT_TIME * 1000);
4227 continue;
4228 }
4229 break;
4230 }
4231
4232 if (pcm_is_ready(pcm)) {
4233 int ret = pcm_prepare(pcm);
4234 if (ret < 0) {
4235 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
4236 pcm_close(pcm);
4237 pcm = NULL;
4238 }
4239 }
4240
4241 return pcm;
4242}
4243
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004244int start_output_stream(struct stream_out *out)
4245{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004246 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004247 struct audio_usecase *uc_info;
4248 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004249 char mixer_ctl_name[128];
4250 struct mixer_ctl *ctl = NULL;
4251 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304252 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004253 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004254
Haynes Mathew George380745d2017-10-04 15:27:45 -07004255 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004256 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
4257 ret = -EINVAL;
4258 goto error_config;
4259 }
4260
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004261 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304262 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004263 get_device_types(&out->device_list), is_haptic_usecase);
4264
4265 bool is_speaker_active = compare_device_type(&out->device_list,
4266 AUDIO_DEVICE_OUT_SPEAKER);
4267 bool is_speaker_safe_active = compare_device_type(&out->device_list,
4268 AUDIO_DEVICE_OUT_SPEAKER_SAFE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304269
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304270 if (CARD_STATUS_OFFLINE == out->card_status ||
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05004271 CARD_STATUS_OFFLINE == adev->card_status ||
4272 POWER_POLICY_STATUS_OFFLINE == adev->out_power_policy) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304273 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05304274 ret = -EIO;
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004275 goto error_fatal;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304276 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05304277
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004278 //Update incall music usecase to reflect correct voice session
4279 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
4280 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
4281 if (ret != 0) {
4282 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
4283 __func__, ret);
4284 goto error_config;
4285 }
4286 }
4287
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004288 if (is_a2dp_out_device_type(&out->device_list)) {
Florian Pfister1a84f312018-07-19 14:38:18 +02004289 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004290 if (is_speaker_active || is_speaker_safe_active) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304291 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304292 } else {
Zhou Songd01e7a22020-09-23 22:49:01 +08004293 if (!is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304294 ALOGE("%s: A2DP profile is not ready, return error", __func__);
4295 ret = -EAGAIN;
4296 goto error_config;
4297 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304298 }
4299 }
4300 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004301 if (is_sco_out_device_type(&out->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304302 if (!adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004303 if (is_speaker_active) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304304 //combo usecase just by pass a2dp
4305 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004306 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304307 } else {
4308 ALOGE("%s: SCO profile is not ready, return error", __func__);
4309 ret = -EAGAIN;
4310 goto error_config;
4311 }
4312 }
4313 }
4314
Eric Laurentb23d5282013-05-14 15:27:20 -07004315 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004316 if (out->pcm_device_id < 0) {
4317 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
4318 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004319 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004320 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004321 }
4322
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004323 if (is_haptic_usecase) {
Meng Wang51d8c2a2020-04-27 15:23:21 +08004324 adev->haptic_pcm_device_id = platform_get_pcm_device_id(
4325 USECASE_AUDIO_PLAYBACK_HAPTICS, PCM_PLAYBACK);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004326 if (adev->haptic_pcm_device_id < 0) {
4327 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
4328 __func__, adev->haptic_pcm_device_id, out->usecase);
4329 ret = -EINVAL;
4330 goto error_config;
4331 }
4332 }
4333
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004334 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004335
4336 if (!uc_info) {
4337 ret = -ENOMEM;
4338 goto error_config;
4339 }
4340
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004341 uc_info->id = out->usecase;
4342 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004343 uc_info->stream.out = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004344 list_init(&uc_info->device_list);
4345 assign_devices(&uc_info->device_list, &out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004346 uc_info->in_snd_device = SND_DEVICE_NONE;
4347 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07004348
4349 /* This must be called before adding this usecase to the list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004350 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07004351 audio_extn_usb_check_and_set_svc_int(uc_info, true);
4352 /* USB backend is not reopened immediately.
4353 This is eventually done as part of select_devices */
4354 }
4355
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004356 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004357
Wei Wangf7ca6c92017-11-21 14:51:20 -08004358 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304359 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4360 adev->perf_lock_opts,
4361 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304362
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004363 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05304364 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304365 if (audio_extn_passthru_is_enabled() &&
4366 audio_extn_passthru_is_passthrough_stream(out)) {
4367 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304368 }
4369 }
4370
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004371 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02004372 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304373 if (!a2dp_combo) {
4374 check_a2dp_restore_l(adev, out, false);
4375 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004376 struct listnode dev;
4377 list_init(&dev);
4378 assign_devices(&dev, &out->device_list);
4379 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4380 reassign_device_list(&out->device_list,
4381 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aalique Grahame22e49102018-12-18 14:23:57 -08004382 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004383 reassign_device_list(&out->device_list,
4384 AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304385 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004386 assign_devices(&out->device_list, &dev);
Zhenlin Lian4f947842022-05-14 15:50:52 +05304387 clear_devices(&dev);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304388 }
4389 } else {
Revathi Uddarajub26e3932020-06-10 14:51:02 +05304390 select_devices(adev, out->usecase);
4391 if (is_a2dp_out_device_type(&out->device_list) &&
4392 !adev->a2dp_started) {
4393 if (is_speaker_active || is_speaker_safe_active) {
4394 struct listnode dev;
4395 list_init(&dev);
4396 assign_devices(&dev, &out->device_list);
4397 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4398 reassign_device_list(&out->device_list,
4399 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
4400 else
4401 reassign_device_list(&out->device_list,
4402 AUDIO_DEVICE_OUT_SPEAKER, "");
4403 select_devices(adev, out->usecase);
4404 assign_devices(&out->device_list, &dev);
Zhenlin Lian4f947842022-05-14 15:50:52 +05304405 clear_devices(&dev);
Revathi Uddarajub26e3932020-06-10 14:51:02 +05304406 } else {
4407 ret = -EINVAL;
4408 goto error_open;
4409 }
4410 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304411 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004412
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004413 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
4414 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07004415 voice_set_device_mute_flag(adev, true);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004416 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07004417
Derek Chenea197282019-01-07 17:35:01 -08004418 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
4419 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08004420
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004421 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
4422 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07004423
4424 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07004425 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07004426 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4427 ALOGE("%s: pcm stream not ready", __func__);
4428 goto error_open;
4429 }
4430 ret = pcm_start(out->pcm);
4431 if (ret < 0) {
4432 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
4433 goto error_open;
4434 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07004435 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07004436 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004437 unsigned int flags = PCM_OUT;
4438 unsigned int pcm_open_retry_count = 0;
4439 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
4440 flags |= PCM_MMAP | PCM_NOIRQ;
4441 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004442 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08004443 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004444 } else
4445 flags |= PCM_MONOTONIC;
4446
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004447 if ((adev->vr_audio_mode_enabled) &&
4448 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
4449 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4450 "PCM_Dev %d Topology", out->pcm_device_id);
4451 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4452 if (!ctl) {
4453 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
4454 __func__, mixer_ctl_name);
4455 } else {
4456 //if success use ULLPP
4457 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
4458 __func__, mixer_ctl_name, out->pcm_device_id);
4459 //There is a still a possibility that some sessions
4460 // that request for FAST|RAW when 3D audio is active
4461 //can go through ULLPP. Ideally we expects apps to
4462 //listen to audio focus and stop concurrent playback
4463 //Also, we will look for mode flag (voice_in_communication)
4464 //before enabling the realtime flag.
4465 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
4466 }
4467 }
4468
Vatsal Bucha3f39f222021-06-29 16:16:55 +05304469 platform_set_stream_channel_map(adev->platform, out->channel_mask,
4470 out->pcm_device_id, -1, &out->channel_map_param.channel_map[0]);
Surendar Karka91fa3682018-07-02 18:12:12 +05304471
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004472 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
4473 flags, pcm_open_retry_count,
4474 &(out->config));
4475 if (out->pcm == NULL) {
4476 ret = -EIO;
4477 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004478 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004479
4480 if (is_haptic_usecase) {
4481 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
4482 adev->haptic_pcm_device_id,
4483 flags, pcm_open_retry_count,
4484 &(adev->haptics_config));
4485 // failure to open haptics pcm shouldnt stop audio,
4486 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07004487
4488 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
4489 ALOGD("%s: enable haptic audio synchronization", __func__);
4490 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
4491 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004492 }
4493
Zhou Song2b8f28f2017-09-11 10:51:38 +08004494 // apply volume for voip playback after path is set up
4495 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
4496 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05304497 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
4498 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304499 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
4500 out->apply_volume = false;
Derek Chenf13dd492018-11-13 14:53:51 -08004501 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
4502 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Krishna Kishor Jha10ad39f2022-02-21 17:02:47 +05304503#ifdef SOFT_VOLUME
4504 out_set_soft_volume_params(&out->stream);
4505#endif
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304506 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004507 } else {
Zhou Song79929fe2020-01-20 17:57:43 +08004508 /*
4509 * set custom channel map if:
4510 * 1. neither mono nor stereo clips i.e. channels > 2 OR
4511 * 2. custom channel map has been set by client
4512 * else default channel map of FC/FR/FL can always be set to DSP
4513 */
4514 if (popcount(out->channel_mask) > 2 || out->channel_map_param.channel_map[0])
4515 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Weiyin Jiang810a80d2021-01-18 16:04:31 +08004516 out->pcm_device_id, -1, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08004517 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
4518 adev->dsp_bit_width_enforce_mode,
4519 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004520 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07004521 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004522 out->compr = compress_open(adev->snd_card,
4523 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004524 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004525 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05304526 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05304527 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
4528 adev->card_status = CARD_STATUS_OFFLINE;
4529 out->card_status = CARD_STATUS_OFFLINE;
4530 ret = -EIO;
4531 goto error_open;
4532 }
4533
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004534 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004535 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004536 compress_close(out->compr);
4537 out->compr = NULL;
4538 ret = -EIO;
4539 goto error_open;
4540 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304541 /* compress_open sends params of the track, so reset the flag here */
4542 out->is_compr_metadata_avail = false;
4543
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004544 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004545 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07004546
Fred Oh3f43e742015-03-04 18:42:34 -08004547 /* Since small bufs uses blocking writes, a write will be blocked
4548 for the default max poll time (20s) in the event of an SSR.
4549 Reduce the poll time to observe and deal with SSR faster.
4550 */
Ashish Jain5106d362016-05-11 19:23:33 +05304551 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08004552 compress_set_max_poll_wait(out->compr, 1000);
4553 }
4554
Manish Dewangan69426c82017-01-30 17:35:36 +05304555 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05304556 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05304557
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004558 audio_extn_dts_create_state_notifier_node(out->usecase);
4559 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4560 popcount(out->channel_mask),
4561 out->playback_started);
4562
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004563#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304564 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004565 audio_extn_dolby_send_ddp_endp_params(adev);
4566#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05304567 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
4568 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004569 if (adev->visualizer_start_output != NULL)
4570 adev->visualizer_start_output(out->handle, out->pcm_device_id);
4571 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05304572 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004573 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004574 }
Derek Chenf13dd492018-11-13 14:53:51 -08004575
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004576 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf13dd492018-11-13 14:53:51 -08004577 /* Update cached volume from media to offload/direct stream */
4578 struct listnode *node = NULL;
4579 list_for_each(node, &adev->active_outputs_list) {
4580 streams_output_ctxt_t *out_ctxt = node_to_item(node,
4581 streams_output_ctxt_t,
4582 list);
4583 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
4584 out->volume_l = out_ctxt->output->volume_l;
4585 out->volume_r = out_ctxt->output->volume_r;
4586 }
4587 }
4588 out_set_compr_volume(&out->stream,
4589 out->volume_l, out->volume_r);
4590 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004591 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004592
4593 if (ret == 0) {
Vaibhav Raut5f3bf222023-02-06 17:45:22 +05304594 if (out->flags & (AUDIO_OUTPUT_FLAG_FAST | AUDIO_OUTPUT_FLAG_RAW))
Narsinga Rao Chellaa6e1f702021-10-22 13:57:32 +05304595 register_out_stream(out);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004596 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07004597 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4598 ALOGE("%s: pcm stream not ready", __func__);
4599 goto error_open;
4600 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004601 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004602 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004603 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004604 if (ret < 0)
4605 goto error_open;
4606 }
4607 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004608 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304609 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Jaideep Sharma0fa53812020-09-17 09:00:11 +05304610 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004611
vivek mehtad15d2bf2019-05-17 13:35:10 -07004612 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
4613 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4614 audio_low_latency_hint_start();
4615 }
4616
Manish Dewangan21a850a2017-08-14 12:03:55 +05304617 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07004618 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07004619 if (ret < 0)
4620 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
4621 }
4622
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004623 // consider a scenario where on pause lower layers are tear down.
4624 // so on resume, swap mixer control need to be sent only when
4625 // backend is active, hence rather than sending from enable device
4626 // sending it from start of streamtream
4627
4628 platform_set_swap_channels(adev, true);
4629
Haynes Mathew George380745d2017-10-04 15:27:45 -07004630 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304631 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004632 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004633error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004634 if (adev->haptic_pcm) {
4635 pcm_close(adev->haptic_pcm);
4636 adev->haptic_pcm = NULL;
4637 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004638 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304639 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004640 stop_output_stream(out);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004641error_fatal:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05304642 /*
4643 * sleep 50ms to allow sufficient time for kernel
4644 * drivers to recover incases like SSR.
4645 */
4646 usleep(50000);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004647error_config:
Haynes Mathew George380745d2017-10-04 15:27:45 -07004648 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304649 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004650 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004651}
4652
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004653static int check_input_parameters(uint32_t sample_rate,
4654 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08004655 int channel_count,
4656 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004657{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004658 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004659
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304660 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
4661 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
4662 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07004663 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02004664 !audio_extn_compr_cap_format_supported(format) &&
4665 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004666 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004667
Aalique Grahame22e49102018-12-18 14:23:57 -08004668 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
4669 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
4670 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
4671 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
4672 return -EINVAL;
4673 }
4674
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004675 switch (channel_count) {
4676 case 1:
4677 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304678 case 3:
4679 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004680 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07004681 case 8:
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05304682 case 10:
4683 case 12:
4684 case 14:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004685 break;
4686 default:
4687 ret = -EINVAL;
4688 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004689
4690 switch (sample_rate) {
4691 case 8000:
4692 case 11025:
4693 case 12000:
4694 case 16000:
4695 case 22050:
4696 case 24000:
4697 case 32000:
4698 case 44100:
4699 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004700 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304701 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004702 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304703 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004704 break;
4705 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004706 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004707 }
4708
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004709 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004710}
4711
Naresh Tanniru04f71882018-06-26 17:46:22 +05304712
4713/** Add a value in a list if not already present.
4714 * @return true if value was successfully inserted or already present,
4715 * false if the list is full and does not contain the value.
4716 */
4717static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
4718 for (size_t i = 0; i < list_length; i++) {
4719 if (list[i] == value) return true; // value is already present
4720 if (list[i] == 0) { // no values in this slot
4721 list[i] = value;
4722 return true; // value inserted
4723 }
4724 }
4725 return false; // could not insert value
4726}
4727
4728/** Add channel_mask in supported_channel_masks if not already present.
4729 * @return true if channel_mask was successfully inserted or already present,
4730 * false if supported_channel_masks is full and does not contain channel_mask.
4731 */
4732static void register_channel_mask(audio_channel_mask_t channel_mask,
4733 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
4734 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
4735 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
4736}
4737
4738/** Add format in supported_formats if not already present.
4739 * @return true if format was successfully inserted or already present,
4740 * false if supported_formats is full and does not contain format.
4741 */
4742static void register_format(audio_format_t format,
4743 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
4744 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
4745 "%s: stream can not declare supporting its format %x", __func__, format);
4746}
4747/** Add sample_rate in supported_sample_rates if not already present.
4748 * @return true if sample_rate was successfully inserted or already present,
4749 * false if supported_sample_rates is full and does not contain sample_rate.
4750 */
4751static void register_sample_rate(uint32_t sample_rate,
4752 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
4753 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
4754 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
4755}
4756
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004757static inline uint32_t lcm(uint32_t num1, uint32_t num2)
4758{
4759 uint32_t high = num1, low = num2, temp = 0;
4760
4761 if (!num1 || !num2)
4762 return 0;
4763
4764 if (num1 < num2) {
4765 high = num2;
4766 low = num1;
4767 }
4768
4769 while (low != 0) {
4770 temp = low;
4771 low = high % low;
4772 high = temp;
4773 }
4774 return (num1 * num2)/high;
4775}
4776
4777static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
4778{
4779 uint32_t remainder = 0;
4780
4781 if (!multiplier)
4782 return num;
4783
4784 remainder = num % multiplier;
4785 if (remainder)
4786 num += (multiplier - remainder);
4787
4788 return num;
4789}
4790
Aalique Grahame22e49102018-12-18 14:23:57 -08004791static size_t get_stream_buffer_size(size_t duration_ms,
4792 uint32_t sample_rate,
4793 audio_format_t format,
4794 int channel_count,
4795 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004796{
4797 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004798 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004799
Aalique Grahame22e49102018-12-18 14:23:57 -08004800 size = (sample_rate * duration_ms) / 1000;
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +05304801 if (is_low_latency){
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +05304802#ifndef PLATFORM_AUTO
4803 size = configured_low_latency_capture_period_size;
4804#else
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +05304805 switch(sample_rate) {
4806 case 48000:
4807 size = 240;
4808 break;
4809 case 32000:
4810 size = 160;
4811 break;
4812 case 24000:
4813 size = 120;
4814 break;
4815 case 16000:
4816 size = 80;
4817 break;
4818 case 8000:
4819 size = 40;
4820 break;
4821 default:
4822 size = 240;
4823 }
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +05304824#endif
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +05304825 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304826
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004827 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08004828 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004829
Ralf Herzbd08d632018-09-28 15:50:49 +02004830 /* make sure the size is multiple of 32 bytes and additionally multiple of
4831 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004832 * At 48 kHz mono 16-bit PCM:
4833 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
4834 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004835 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004836 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004837 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07004838
4839 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004840}
4841
Aalique Grahame22e49102018-12-18 14:23:57 -08004842static size_t get_input_buffer_size(uint32_t sample_rate,
4843 audio_format_t format,
4844 int channel_count,
4845 bool is_low_latency)
4846{
Avinash Chandrad7296d42021-08-04 15:07:47 +05304847 bool is_usb_hifi = IS_USB_HIFI;
Aalique Grahame22e49102018-12-18 14:23:57 -08004848 /* Don't know if USB HIFI in this context so use true to be conservative */
4849 if (check_input_parameters(sample_rate, format, channel_count,
Avinash Chandrad7296d42021-08-04 15:07:47 +05304850 is_usb_hifi) != 0)
Aalique Grahame22e49102018-12-18 14:23:57 -08004851 return 0;
4852
4853 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4854 sample_rate,
4855 format,
4856 channel_count,
4857 is_low_latency);
4858}
4859
Derek Chenf6318be2017-06-12 17:16:24 -04004860size_t get_output_period_size(uint32_t sample_rate,
4861 audio_format_t format,
4862 int channel_count,
4863 int duration /*in millisecs*/)
Ashish Jain058165c2016-09-28 23:18:48 +05304864{
4865 size_t size = 0;
4866 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
4867
4868 if ((duration == 0) || (sample_rate == 0) ||
4869 (bytes_per_sample == 0) || (channel_count == 0)) {
4870 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
4871 bytes_per_sample, channel_count);
4872 return -EINVAL;
4873 }
4874
4875 size = (sample_rate *
4876 duration *
4877 bytes_per_sample *
4878 channel_count) / 1000;
4879 /*
4880 * To have same PCM samples for all channels, the buffer size requires to
4881 * be multiple of (number of channels * bytes per sample)
4882 * For writes to succeed, the buffer must be written at address which is multiple of 32
4883 */
4884 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
4885
4886 return (size/(channel_count * bytes_per_sample));
4887}
4888
Zhou Song48453a02018-01-10 17:50:59 +08004889static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05304890{
4891 uint64_t actual_frames_rendered = 0;
Weiyin Jiang4813da12020-05-28 00:37:28 +08004892 uint64_t written_frames = 0;
4893 uint64_t kernel_frames = 0;
4894 uint64_t dsp_frames = 0;
4895 uint64_t signed_frames = 0;
4896 size_t kernel_buffer_size = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304897
4898 /* This adjustment accounts for buffering after app processor.
4899 * It is based on estimated DSP latency per use case, rather than exact.
4900 */
George Gao9ba8a142020-07-23 14:30:03 -07004901 dsp_frames = platform_render_latency(out) *
Weiyin Jiang4813da12020-05-28 00:37:28 +08004902 out->sample_rate / 1000000LL;
Ashish Jain5106d362016-05-11 19:23:33 +05304903
Zhou Song48453a02018-01-10 17:50:59 +08004904 pthread_mutex_lock(&out->position_query_lock);
Weiyin Jiang4813da12020-05-28 00:37:28 +08004905 written_frames = out->written /
4906 (audio_bytes_per_sample(out->hal_ip_format) * popcount(out->channel_mask));
4907
Ashish Jain5106d362016-05-11 19:23:33 +05304908 /* not querying actual state of buffering in kernel as it would involve an ioctl call
4909 * which then needs protection, this causes delay in TS query for pcm_offload usecase
4910 * hence only estimate.
4911 */
Weiyin Jiang4813da12020-05-28 00:37:28 +08004912 kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
4913 kernel_frames = kernel_buffer_size /
4914 (audio_bytes_per_sample(out->hal_op_format) * popcount(out->channel_mask));
Ashish Jain5106d362016-05-11 19:23:33 +05304915
Weiyin Jiang4813da12020-05-28 00:37:28 +08004916 if (written_frames >= (kernel_frames + dsp_frames))
4917 signed_frames = written_frames - kernel_frames - dsp_frames;
Ashish Jain5106d362016-05-11 19:23:33 +05304918
Zhou Song48453a02018-01-10 17:50:59 +08004919 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05304920 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08004921 if (timestamp != NULL )
4922 *timestamp = out->writeAt;
4923 } else if (timestamp != NULL) {
4924 clock_gettime(CLOCK_MONOTONIC, timestamp);
4925 }
4926 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304927
Weiyin Jiang4813da12020-05-28 00:37:28 +08004928 ALOGVV("%s signed frames %lld written frames %lld kernel frames %lld dsp frames %lld",
4929 __func__, signed_frames, written_frames, kernel_frames, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05304930
4931 return actual_frames_rendered;
4932}
4933
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004934static uint32_t out_get_sample_rate(const struct audio_stream *stream)
4935{
4936 struct stream_out *out = (struct stream_out *)stream;
4937
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004938 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004939}
4940
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004941static int out_set_sample_rate(struct audio_stream *stream __unused,
4942 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004943{
4944 return -ENOSYS;
4945}
4946
4947static size_t out_get_buffer_size(const struct audio_stream *stream)
4948{
4949 struct stream_out *out = (struct stream_out *)stream;
4950
Varun Balaraje49253e2017-07-06 19:48:56 +05304951 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05304952 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05304953 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304954 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4955 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
4956 else
4957 return out->compr_config.fragment_size;
4958 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004959 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304960 else if (is_offload_usecase(out->usecase) &&
4961 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304962 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004963
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004964 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004965 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004966}
4967
4968static uint32_t out_get_channels(const struct audio_stream *stream)
4969{
4970 struct stream_out *out = (struct stream_out *)stream;
4971
4972 return out->channel_mask;
4973}
4974
4975static audio_format_t out_get_format(const struct audio_stream *stream)
4976{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004977 struct stream_out *out = (struct stream_out *)stream;
4978
4979 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004980}
4981
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004982static int out_set_format(struct audio_stream *stream __unused,
4983 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004984{
4985 return -ENOSYS;
4986}
4987
4988static int out_standby(struct audio_stream *stream)
4989{
4990 struct stream_out *out = (struct stream_out *)stream;
4991 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07004992 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004993
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304994 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4995 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004996
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004997 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004998 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004999 if (adev->adm_deregister_stream)
5000 adev->adm_deregister_stream(adev->adm_data, out->handle);
5001
Weiyin Jiang280ea742020-09-08 20:28:22 +08005002 if (is_offload_usecase(out->usecase)) {
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07005003 stop_compressed_output_l(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08005004 }
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07005005
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08005006 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005007 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08005008 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
5009 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305010 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08005011 pthread_mutex_unlock(&adev->lock);
5012 pthread_mutex_unlock(&out->lock);
5013 ALOGD("VOIP output entered standby");
5014 return 0;
5015 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005016 if (out->pcm) {
5017 pcm_close(out->pcm);
5018 out->pcm = NULL;
5019 }
Meng Wanga09da002020-04-20 12:56:04 +08005020 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
5021 if (adev->haptic_pcm) {
5022 pcm_close(adev->haptic_pcm);
5023 adev->haptic_pcm = NULL;
5024 }
5025
5026 if (adev->haptic_buffer != NULL) {
5027 free(adev->haptic_buffer);
5028 adev->haptic_buffer = NULL;
5029 adev->haptic_buffer_size = 0;
5030 }
5031 adev->haptic_pcm_device_id = 0;
5032 }
5033
Haynes Mathew George16081042017-05-31 17:16:49 -07005034 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5035 do_stop = out->playback_started;
5036 out->playback_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07005037
5038 if (out->mmap_shared_memory_fd >= 0) {
5039 ALOGV("%s: closing mmap_shared_memory_fd = %d",
5040 __func__, out->mmap_shared_memory_fd);
5041 close(out->mmap_shared_memory_fd);
5042 out->mmap_shared_memory_fd = -1;
5043 }
Haynes Mathew George16081042017-05-31 17:16:49 -07005044 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005045 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005046 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305047 out->send_next_track_params = false;
5048 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005049 out->gapless_mdata.encoder_delay = 0;
5050 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005051 if (out->compr != NULL) {
5052 compress_close(out->compr);
5053 out->compr = NULL;
5054 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08005055 }
Haynes Mathew George16081042017-05-31 17:16:49 -07005056 if (do_stop) {
5057 stop_output_stream(out);
5058 }
Lakshman Chaluvaraju06677b42019-06-24 10:04:52 +05305059 // if fm is active route on selected device in UI
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005060 audio_extn_fm_route_on_selected_device(adev, &out->device_list);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005061 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005062 }
5063 pthread_mutex_unlock(&out->lock);
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07005064 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005065 return 0;
5066}
5067
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305068static int out_on_error(struct audio_stream *stream)
5069{
5070 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07005071 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305072
5073 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08005074 // always send CMD_ERROR for offload streams, this
5075 // is needed e.g. when SSR happens within compress_open
5076 // since the stream is active, offload_callback_thread is also active.
5077 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
5078 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07005079 }
5080 pthread_mutex_unlock(&out->lock);
5081
5082 status = out_standby(&out->stream.common);
5083
5084 lock_output_stream(out);
5085 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08005086 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305087 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05305088
5089 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
5090 ALOGD("Setting previous card status if offline");
5091 out->prev_card_status_offline = true;
5092 }
5093
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305094 pthread_mutex_unlock(&out->lock);
5095
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07005096 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305097}
5098
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305099/*
Weiyin Jiang280ea742020-09-08 20:28:22 +08005100 * standby implementation without locks, assumes that the callee already
5101 * has taken adev and out lock.
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305102 */
5103int out_standby_l(struct audio_stream *stream)
5104{
5105 struct stream_out *out = (struct stream_out *)stream;
5106 struct audio_device *adev = out->dev;
5107
5108 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
5109 stream, out->usecase, use_case_table[out->usecase]);
5110
5111 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07005112 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305113 if (adev->adm_deregister_stream)
5114 adev->adm_deregister_stream(adev->adm_data, out->handle);
5115
Weiyin Jiang280ea742020-09-08 20:28:22 +08005116 if (is_offload_usecase(out->usecase)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305117 stop_compressed_output_l(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08005118 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305119
5120 out->standby = true;
5121 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
5122 voice_extn_compress_voip_close_output_stream(stream);
5123 out->started = 0;
5124 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07005125 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305126 return 0;
5127 } else if (!is_offload_usecase(out->usecase)) {
5128 if (out->pcm) {
5129 pcm_close(out->pcm);
5130 out->pcm = NULL;
5131 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005132 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
5133 if (adev->haptic_pcm) {
5134 pcm_close(adev->haptic_pcm);
5135 adev->haptic_pcm = NULL;
5136 }
5137
5138 if (adev->haptic_buffer != NULL) {
5139 free(adev->haptic_buffer);
5140 adev->haptic_buffer = NULL;
5141 adev->haptic_buffer_size = 0;
5142 }
5143 adev->haptic_pcm_device_id = 0;
5144 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305145 } else {
5146 ALOGD("copl(%p):standby", out);
5147 out->send_next_track_params = false;
5148 out->is_compr_metadata_avail = false;
5149 out->gapless_mdata.encoder_delay = 0;
5150 out->gapless_mdata.encoder_padding = 0;
5151 if (out->compr != NULL) {
5152 compress_close(out->compr);
5153 out->compr = NULL;
5154 }
5155 }
5156 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005157 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305158 }
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07005159 ALOGV("%s: exit", __func__);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305160 return 0;
5161}
5162
Aalique Grahame22e49102018-12-18 14:23:57 -08005163static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005164{
Aalique Grahame22e49102018-12-18 14:23:57 -08005165 struct stream_out *out = (struct stream_out *)stream;
5166
5167 // We try to get the lock for consistency,
5168 // but it isn't necessary for these variables.
5169 // If we're not in standby, we may be blocked on a write.
5170 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
5171 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
5172 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
Dechen Chai22768452021-07-30 09:29:16 +05305173#ifndef LINUX_ENABLED
Andy Hunga1f48fa2019-07-01 18:14:53 -07005174 char buffer[256]; // for statistics formatting
5175 if (!is_offload_usecase(out->usecase)) {
5176 simple_stats_to_string(&out->fifo_underruns, buffer, sizeof(buffer));
5177 dprintf(fd, " Fifo frame underruns: %s\n", buffer);
5178 }
5179
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005180 if (out->start_latency_ms.n > 0) {
5181 simple_stats_to_string(&out->start_latency_ms, buffer, sizeof(buffer));
5182 dprintf(fd, " Start latency ms: %s\n", buffer);
5183 }
Dechen Chai22768452021-07-30 09:29:16 +05305184#endif
Aalique Grahame22e49102018-12-18 14:23:57 -08005185 if (locked) {
5186 pthread_mutex_unlock(&out->lock);
5187 }
5188
Dechen Chai22768452021-07-30 09:29:16 +05305189#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -08005190 // dump error info
5191 (void)error_log_dump(
5192 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Dechen Chai22768452021-07-30 09:29:16 +05305193#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005194 return 0;
5195}
5196
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005197static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
5198{
5199 int ret = 0;
5200 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08005201
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005202 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08005203 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005204 return -EINVAL;
5205 }
5206
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05305207 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08005208
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005209 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
5210 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05305211 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005212 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005213 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
5214 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05305215 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005216 }
5217
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005218 ALOGV("%s new encoder delay %u and padding %u", __func__,
5219 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
5220
5221 return 0;
5222}
5223
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005224static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
5225{
5226 return out == adev->primary_output || out == adev->voice_tx_output;
5227}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005228
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305229// note: this call is safe only if the stream_cb is
5230// removed first in close_output_stream (as is done now).
5231static void out_snd_mon_cb(void * stream, struct str_parms * parms)
5232{
5233 if (!stream || !parms)
5234 return;
5235
5236 struct stream_out *out = (struct stream_out *)stream;
5237 struct audio_device *adev = out->dev;
5238
5239 card_status_t status;
5240 int card;
5241 if (parse_snd_card_status(parms, &card, &status) < 0)
5242 return;
5243
5244 pthread_mutex_lock(&adev->lock);
5245 bool valid_cb = (card == adev->snd_card);
5246 pthread_mutex_unlock(&adev->lock);
5247
5248 if (!valid_cb)
5249 return;
5250
5251 lock_output_stream(out);
5252 if (out->card_status != status)
5253 out->card_status = status;
5254 pthread_mutex_unlock(&out->lock);
5255
5256 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
5257 use_case_table[out->usecase],
5258 status == CARD_STATUS_OFFLINE ? "offline" : "online");
5259
Aditya Bavanari59ebed42019-02-05 17:44:57 +05305260 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305261 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05305262 if (voice_is_call_state_active(adev) &&
5263 out == adev->primary_output) {
5264 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
5265 pthread_mutex_lock(&adev->lock);
5266 voice_stop_call(adev);
5267 adev->mode = AUDIO_MODE_NORMAL;
5268 pthread_mutex_unlock(&adev->lock);
5269 }
5270 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305271 return;
5272}
5273
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005274int route_output_stream(struct stream_out *out,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005275 struct listnode *devices)
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005276{
5277 struct audio_device *adev = out->dev;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005278 int ret = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005279 struct listnode new_devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005280 bool bypass_a2dp = false;
5281 bool reconfig = false;
5282 unsigned long service_interval = 0;
5283
5284 ALOGD("%s: enter: usecase(%d: %s) devices %x",
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005285 __func__, out->usecase, use_case_table[out->usecase], get_device_types(devices));
5286
5287 list_init(&new_devices);
5288 assign_devices(&new_devices, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005289
5290 lock_output_stream(out);
5291 pthread_mutex_lock(&adev->lock);
5292
5293 /*
5294 * When HDMI cable is unplugged the music playback is paused and
5295 * the policy manager sends routing=0. But the audioflinger continues
5296 * to write data until standby time (3sec). As the HDMI core is
5297 * turned off, the write gets blocked.
5298 * Avoid this by routing audio to speaker until standby.
5299 */
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08005300 if (is_single_device_type_equal(&out->device_list,
5301 AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005302 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005303 !audio_extn_passthru_is_passthrough_stream(out) &&
5304 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005305 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005306 }
5307 /*
5308 * When A2DP is disconnected the
5309 * music playback is paused and the policy manager sends routing=0
5310 * But the audioflinger continues to write data until standby time
5311 * (3sec). As BT is turned off, the write gets blocked.
5312 * Avoid this by routing audio to speaker until standby.
5313 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005314 if (is_a2dp_out_device_type(&out->device_list) &&
5315 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005316 !audio_extn_a2dp_source_is_ready() &&
5317 !adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005318 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005319 }
5320 /*
Weiyin Jiangabedea32020-12-09 12:49:19 +08005321 * When USB headset is disconnected the music playback paused
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005322 * and the policy manager send routing=0. But if the USB is connected
5323 * back before the standby time, AFE is not closed and opened
5324 * when USB is connected back. So routing to speker will guarantee
5325 * AFE reconfiguration and AFE will be opend once USB is connected again
5326 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005327 if (is_usb_out_device_type(&out->device_list) &&
5328 list_empty(&new_devices) &&
5329 !audio_extn_usb_connected(NULL)) {
Sujin Panicker84d953a2020-11-16 17:39:54 +05305330 if (adev->mode == AUDIO_MODE_IN_CALL || adev->mode == AUDIO_MODE_IN_COMMUNICATION)
5331 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_EARPIECE, "");
5332 else
5333 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005334 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005335 /* To avoid a2dp to sco overlapping / BT device improper state
5336 * check with BT lib about a2dp streaming support before routing
5337 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005338 if (is_a2dp_out_device_type(&new_devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005339 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005340 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER) ||
5341 compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005342 //combo usecase just by pass a2dp
5343 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
5344 bypass_a2dp = true;
5345 } else {
5346 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
5347 /* update device to a2dp and don't route as BT returned error
5348 * However it is still possible a2dp routing called because
5349 * of current active device disconnection (like wired headset)
5350 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005351 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005352 pthread_mutex_unlock(&adev->lock);
5353 pthread_mutex_unlock(&out->lock);
5354 goto error;
5355 }
5356 }
5357 }
5358
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005359 // Workaround: If routing to an non existing usb device, fail gracefully
5360 // The routing request will otherwise block during 10 second
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005361 if (is_usb_out_device_type(&new_devices)) {
5362 struct str_parms *parms =
5363 str_parms_create_str(get_usb_device_address(&new_devices));
5364 if (!parms)
5365 goto error;
Weiyin Jiangabedea32020-12-09 12:49:19 +08005366 if (!audio_extn_usb_connected(NULL)) {
5367 ALOGW("%s: ignoring rerouting to non existing USB card", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005368 pthread_mutex_unlock(&adev->lock);
5369 pthread_mutex_unlock(&out->lock);
5370 str_parms_destroy(parms);
5371 ret = -ENOSYS;
5372 goto error;
5373 }
5374 str_parms_destroy(parms);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005375 }
5376
Weiyin Jiang80c8f9a2020-01-10 20:42:08 +08005377 // Workaround: If routing to an non existing hdmi device, fail gracefully
5378 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
5379 (platform_get_edid_info_v2(adev->platform,
5380 out->extconn.cs.controller,
5381 out->extconn.cs.stream) != 0)) {
5382 ALOGW("out_set_parameters() ignoring rerouting to non existing HDMI/DP");
5383 pthread_mutex_unlock(&adev->lock);
5384 pthread_mutex_unlock(&out->lock);
5385 ret = -ENOSYS;
5386 goto error;
5387 }
5388
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005389 /*
5390 * select_devices() call below switches all the usecases on the same
5391 * backend to the new device. Refer to check_usecases_codec_backend() in
5392 * the select_devices(). But how do we undo this?
5393 *
5394 * For example, music playback is active on headset (deep-buffer usecase)
5395 * and if we go to ringtones and select a ringtone, low-latency usecase
5396 * will be started on headset+speaker. As we can't enable headset+speaker
5397 * and headset devices at the same time, select_devices() switches the music
5398 * playback to headset+speaker while starting low-lateny usecase for ringtone.
5399 * So when the ringtone playback is completed, how do we undo the same?
5400 *
5401 * We are relying on the out_set_parameters() call on deep-buffer output,
5402 * once the ringtone playback is ended.
5403 * NOTE: We should not check if the current devices are same as new devices.
5404 * Because select_devices() must be called to switch back the music
5405 * playback to headset.
5406 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005407 if (!list_empty(&new_devices)) {
5408 bool same_dev = compare_devices(&out->device_list, &new_devices);
5409 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005410
5411 if (output_drives_call(adev, out)) {
5412 if (!voice_is_call_state_active(adev)) {
5413 if (adev->mode == AUDIO_MODE_IN_CALL) {
5414 adev->current_call_output = out;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005415 ret = voice_start_call(adev);
5416 }
5417 } else {
Kunlei Zhang253ad102020-10-14 16:21:28 +08005418 platform_is_volume_boost_supported_device(adev->platform, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005419 adev->current_call_output = out;
5420 voice_update_devices_for_all_voice_usecases(adev);
5421 }
5422 }
5423
Mingshu Pang971ff702020-09-09 15:28:22 +08005424 if (is_usb_out_device_type(&out->device_list)) {
5425 service_interval = audio_extn_usb_find_service_interval(false, true /*playback*/);
5426 audio_extn_usb_set_service_interval(true /*playback*/,
5427 service_interval,
5428 &reconfig);
5429 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
5430 }
5431
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005432 if (!out->standby) {
5433 if (!same_dev) {
5434 ALOGV("update routing change");
5435 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
5436 adev->perf_lock_opts,
5437 adev->perf_lock_opts_size);
5438 if (adev->adm_on_routing_change)
5439 adev->adm_on_routing_change(adev->adm_data,
5440 out->handle);
5441 }
5442 if (!bypass_a2dp) {
5443 select_devices(adev, out->usecase);
5444 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005445 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
5446 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005447 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005448 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005449 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005450 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005451 }
5452
5453 if (!same_dev) {
5454 // on device switch force swap, lower functions will make sure
5455 // to check if swap is allowed or not.
5456 platform_set_swap_channels(adev, true);
5457 audio_extn_perf_lock_release(&adev->perf_lock_handle);
5458 }
Zhou Songbaddf9f2020-11-20 13:57:39 +08005459 pthread_mutex_lock(&out->latch_lock);
5460 if (!is_a2dp_out_device_type(&out->device_list) || audio_extn_a2dp_source_is_ready()) {
5461 if (out->a2dp_muted) {
5462 out->a2dp_muted = false;
5463 if (is_offload_usecase(out->usecase))
5464 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5465 else if (out->usecase != USECASE_AUDIO_PLAYBACK_VOIP)
5466 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Weiyin Jiang280ea742020-09-08 20:28:22 +08005467 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005468 }
Zhou Songbaddf9f2020-11-20 13:57:39 +08005469 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP && !out->a2dp_muted)
5470 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
5471 pthread_mutex_unlock(&out->latch_lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005472 }
5473 }
5474
5475 pthread_mutex_unlock(&adev->lock);
5476 pthread_mutex_unlock(&out->lock);
5477
5478 /*handles device and call state changes*/
5479 audio_extn_extspk_update(adev->extspk);
5480
Revathi Uddaraju4255a632021-12-02 05:11:13 -08005481 clear_devices(&new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005482error:
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005483 ALOGV("%s: exit: code(%d)", __func__, ret);
5484 return ret;
5485}
5486
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005487static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
5488{
5489 struct stream_out *out = (struct stream_out *)stream;
5490 struct audio_device *adev = out->dev;
5491 struct str_parms *parms;
5492 char value[32];
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005493 int ret = 0, err;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005494 int ext_controller = -1;
5495 int ext_stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005496
sangwoobc677242013-08-08 16:53:43 +09005497 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005498 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005499 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305500 if (!parms)
5501 goto error;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005502
5503 err = platform_get_controller_stream_from_params(parms, &ext_controller,
5504 &ext_stream);
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08005505 if (err == 0) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005506 out->extconn.cs.controller = ext_controller;
5507 out->extconn.cs.stream = ext_stream;
5508 ALOGD("%s: usecase(%s) new controller/stream (%d/%d)", __func__,
5509 use_case_table[out->usecase], out->extconn.cs.controller,
5510 out->extconn.cs.stream);
5511 }
5512
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005513 if (out == adev->primary_output) {
5514 pthread_mutex_lock(&adev->lock);
5515 audio_extn_set_parameters(adev, parms);
5516 pthread_mutex_unlock(&adev->lock);
5517 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005518 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005519 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005520 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005521
5522 audio_extn_dts_create_state_notifier_node(out->usecase);
5523 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5524 popcount(out->channel_mask),
5525 out->playback_started);
5526
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08005527 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005528 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005529
Surendar Karkaf51b5842018-04-26 11:28:38 +05305530 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
5531 sizeof(value));
5532 if (err >= 0) {
5533 if (!strncmp("true", value, sizeof("true")) || atoi(value))
5534 audio_extn_send_dual_mono_mixing_coefficients(out);
5535 }
5536
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305537 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5538 if (err >= 0) {
5539 strlcpy(out->profile, value, sizeof(out->profile));
5540 ALOGV("updating stream profile with value '%s'", out->profile);
5541 lock_output_stream(out);
5542 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
5543 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005544 &out->device_list, out->flags,
5545 out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305546 out->sample_rate, out->bit_width,
5547 out->channel_mask, out->profile,
5548 &out->app_type_cfg);
5549 pthread_mutex_unlock(&out->lock);
5550 }
5551
Alexy Joseph98988832017-01-13 14:56:59 -08005552 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005553 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
5554 // and vendor.audio.hal.output.suspend.supported is set to true
5555 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08005556 //check suspend parameter only for low latency and if the property
5557 //is enabled
5558 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
5559 ALOGI("%s: got suspend_playback %s", __func__, value);
5560 lock_output_stream(out);
5561 if (!strncmp(value, "false", 5)) {
5562 //suspend_playback=false is supposed to set QOS value back to 75%
5563 //the mixer control sent with value Enable will achieve that
5564 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5565 } else if (!strncmp (value, "true", 4)) {
5566 //suspend_playback=true is supposed to remove QOS value
5567 //resetting the mixer control will set the default value
5568 //for the mixer control which is Disable and this removes the QOS vote
5569 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5570 } else {
5571 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
5572 " got %s", __func__, value);
5573 ret = -1;
5574 }
5575
5576 if (ret != 0) {
5577 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
5578 __func__, out->pm_qos_mixer_path, ret);
5579 }
5580
5581 pthread_mutex_unlock(&out->lock);
5582 }
5583 }
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005584
Alexy Joseph98988832017-01-13 14:56:59 -08005585 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005586 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305587error:
Eric Laurent994a6932013-07-17 11:51:42 -07005588 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005589 return ret;
5590}
5591
Paul McLeana50b7332018-12-17 08:24:21 -07005592static int in_set_microphone_direction(const struct audio_stream_in *stream,
5593 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07005594 struct stream_in *in = (struct stream_in *)stream;
5595
5596 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
5597
5598 in->direction = dir;
5599
5600 if (in->standby)
5601 return 0;
5602
5603 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07005604}
5605
5606static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07005607 struct stream_in *in = (struct stream_in *)stream;
5608
5609 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
5610
5611 if (zoom > 1.0 || zoom < -1.0)
5612 return -EINVAL;
5613
5614 in->zoom = zoom;
5615
5616 if (in->standby)
5617 return 0;
5618
5619 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07005620}
5621
5622
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005623static bool stream_get_parameter_channels(struct str_parms *query,
5624 struct str_parms *reply,
5625 audio_channel_mask_t *supported_channel_masks) {
5626 int ret = -1;
5627 char value[512];
5628 bool first = true;
5629 size_t i, j;
5630
5631 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
5632 ret = 0;
5633 value[0] = '\0';
5634 i = 0;
5635 while (supported_channel_masks[i] != 0) {
5636 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5637 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
5638 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305639 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005640
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305641 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005642 first = false;
5643 break;
5644 }
5645 }
5646 i++;
5647 }
5648 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5649 }
5650 return ret == 0;
5651}
5652
5653static bool stream_get_parameter_formats(struct str_parms *query,
5654 struct str_parms *reply,
5655 audio_format_t *supported_formats) {
5656 int ret = -1;
5657 char value[256];
5658 size_t i, j;
5659 bool first = true;
5660
5661 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
5662 ret = 0;
5663 value[0] = '\0';
5664 i = 0;
5665 while (supported_formats[i] != 0) {
5666 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5667 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
5668 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305669 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005670 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305671 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005672 first = false;
5673 break;
5674 }
5675 }
5676 i++;
5677 }
5678 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
5679 }
5680 return ret == 0;
5681}
5682
5683static bool stream_get_parameter_rates(struct str_parms *query,
5684 struct str_parms *reply,
5685 uint32_t *supported_sample_rates) {
5686
5687 int i;
5688 char value[256];
5689 int ret = -1;
5690 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
5691 ret = 0;
5692 value[0] = '\0';
5693 i=0;
5694 int cursor = 0;
5695 while (supported_sample_rates[i]) {
5696 int avail = sizeof(value) - cursor;
5697 ret = snprintf(value + cursor, avail, "%s%d",
5698 cursor > 0 ? "|" : "",
5699 supported_sample_rates[i]);
5700 if (ret < 0 || ret >= avail) {
5701 // if cursor is at the last element of the array
5702 // overwrite with \0 is duplicate work as
5703 // snprintf already put a \0 in place.
5704 // else
5705 // we had space to write the '|' at value[cursor]
5706 // (which will be overwritten) or no space to fill
5707 // the first element (=> cursor == 0)
5708 value[cursor] = '\0';
5709 break;
5710 }
5711 cursor += ret;
5712 ++i;
5713 }
5714 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
5715 value);
5716 }
5717 return ret >= 0;
5718}
5719
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005720static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
5721{
5722 struct stream_out *out = (struct stream_out *)stream;
5723 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005724 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005725 char value[256];
5726 struct str_parms *reply = str_parms_create();
5727 size_t i, j;
5728 int ret;
5729 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005730
5731 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005732 if (reply) {
5733 str_parms_destroy(reply);
5734 }
5735 if (query) {
5736 str_parms_destroy(query);
5737 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005738 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
5739 return NULL;
5740 }
5741
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005742 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005743 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
5744 if (ret >= 0) {
5745 value[0] = '\0';
5746 i = 0;
5747 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005748 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5749 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005750 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005751 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005752 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005753 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005754 first = false;
5755 break;
5756 }
5757 }
5758 i++;
5759 }
5760 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5761 str = str_parms_to_str(reply);
5762 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005763 voice_extn_out_get_parameters(out, query, reply);
5764 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005765 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005766
Alexy Joseph62142aa2015-11-16 15:10:34 -08005767
5768 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
5769 if (ret >= 0) {
5770 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05305771 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
5772 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08005773 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305774 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005775 } else {
5776 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05305777 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005778 }
5779 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005780 if (str)
5781 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08005782 str = str_parms_to_str(reply);
5783 }
5784
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005785 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
5786 if (ret >= 0) {
5787 value[0] = '\0';
5788 i = 0;
5789 first = true;
5790 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005791 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5792 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005793 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005794 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005795 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005796 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005797 first = false;
5798 break;
5799 }
5800 }
5801 i++;
5802 }
5803 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005804 if (str)
5805 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005806 str = str_parms_to_str(reply);
5807 }
Mingming Yin3a941d42016-02-17 18:08:05 -08005808
5809 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
5810 if (ret >= 0) {
5811 value[0] = '\0';
5812 i = 0;
5813 first = true;
5814 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005815 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
5816 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005817 if (!first) {
5818 strlcat(value, "|", sizeof(value));
5819 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005820 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08005821 first = false;
5822 break;
5823 }
5824 }
5825 i++;
5826 }
5827 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
5828 if (str)
5829 free(str);
5830 str = str_parms_to_str(reply);
5831 }
5832
Alexy Joseph98988832017-01-13 14:56:59 -08005833 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
5834 //only low latency track supports suspend_resume
5835 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005836 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08005837 if (str)
5838 free(str);
5839 str = str_parms_to_str(reply);
5840 }
5841
5842
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005843 str_parms_destroy(query);
5844 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07005845 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005846 return str;
5847}
5848
5849static uint32_t out_get_latency(const struct audio_stream_out *stream)
5850{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005851 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005852 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08005853 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005854
Alexy Josephaa54c872014-12-03 02:46:47 -08005855 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05305856 lock_output_stream(out);
5857 latency = audio_extn_utils_compress_get_dsp_latency(out);
5858 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005859 } else if ((out->realtime) ||
5860 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005861 // since the buffer won't be filled up faster than realtime,
5862 // return a smaller number
5863 if (out->config.rate)
5864 period_ms = (out->af_period_multiplier * out->config.period_size *
5865 1000) / (out->config.rate);
5866 else
5867 period_ms = 0;
George Gao9ba8a142020-07-23 14:30:03 -07005868 latency = period_ms + platform_render_latency(out) / 1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005869 } else {
5870 latency = (out->config.period_count * out->config.period_size * 1000) /
Mingshu Pangf69a88d2021-04-30 16:14:39 +08005871 (out->config.rate);
pavanisra2d95d82022-02-09 18:55:58 +05305872 if (out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5873 out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY)
Mingshu Pangf69a88d2021-04-30 16:14:39 +08005874 latency += platform_render_latency(out)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005875 }
5876
Zhou Songd2537a02020-06-11 22:04:46 +08005877 if (!out->standby && is_a2dp_out_device_type(&out->device_list))
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08005878 latency += audio_extn_a2dp_get_encoder_latency();
5879
Anish Kumar50ebcbf2014-12-09 04:01:39 +05305880 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08005881 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005882}
5883
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305884static float AmpToDb(float amplification)
5885{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305886 float db = DSD_VOLUME_MIN_DB;
5887 if (amplification > 0) {
5888 db = 20 * log10(amplification);
5889 if(db < DSD_VOLUME_MIN_DB)
5890 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305891 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305892 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305893}
5894
Krishna Kishor Jha10ad39f2022-02-21 17:02:47 +05305895#ifdef SOFT_VOLUME
5896static int out_set_soft_volume_params(struct audio_stream_out *stream)
5897{
5898 struct stream_out *out = (struct stream_out *)stream;
5899 int ret = 0;
5900 char mixer_ctl_name[128];
5901 struct audio_device *adev = out->dev;
5902 struct mixer_ctl *ctl = NULL;
5903 struct soft_step_volume_params *volume_params = NULL;
5904
5905 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5906 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Soft Vol Params", pcm_device_id);
5907 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5908 if (!ctl) {
5909 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5910 return -EINVAL;
5911 }
5912
5913 volume_params =(struct soft_step_volume_params * ) malloc(sizeof(struct soft_step_volume_params));
5914 if (volume_params == NULL){
5915 ALOGE("%s : malloc is failed for volume params", __func__);
5916 return -EINVAL;
5917 } else {
5918 ret = platform_get_soft_step_volume_params(volume_params,out->usecase);
5919 if (ret < 0) {
5920 ALOGE("%s : platform_get_soft_step_volume_params is fialed", __func__);
Karan Naidu28b335a2022-05-18 23:00:08 +05305921 ret = -EINVAL;
5922 goto ERR_EXIT;
Krishna Kishor Jha10ad39f2022-02-21 17:02:47 +05305923 }
5924
5925 }
5926 ret = mixer_ctl_set_array(ctl, volume_params, sizeof(struct soft_step_volume_params)/sizeof(int));
5927 if (ret < 0) {
5928 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
Karan Naidu28b335a2022-05-18 23:00:08 +05305929 ret = -EINVAL;
5930 goto ERR_EXIT;
5931 }
5932
5933 if (volume_params) {
5934 free(volume_params);
Krishna Kishor Jha10ad39f2022-02-21 17:02:47 +05305935 }
5936 return 0;
Karan Naidu28b335a2022-05-18 23:00:08 +05305937
5938ERR_EXIT:
5939 if (volume_params) {
5940 free(volume_params);
5941 }
5942 return ret;
Krishna Kishor Jha10ad39f2022-02-21 17:02:47 +05305943}
5944#endif
5945
Arun Mirpuri5d170872019-03-26 13:21:31 -07005946static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
5947 float right)
5948{
5949 struct stream_out *out = (struct stream_out *)stream;
5950 long volume = 0;
5951 char mixer_ctl_name[128] = "";
5952 struct audio_device *adev = out->dev;
5953 struct mixer_ctl *ctl = NULL;
5954 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5955 PCM_PLAYBACK);
5956
5957 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5958 "Playback %d Volume", pcm_device_id);
5959 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5960 if (!ctl) {
5961 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5962 __func__, mixer_ctl_name);
5963 return -EINVAL;
5964 }
5965 if (left != right)
5966 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
5967 __func__, left, right);
5968 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
5969 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
5970 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
5971 __func__, mixer_ctl_name, volume);
5972 return -EINVAL;
5973 }
5974 return 0;
5975}
5976
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305977static int out_set_compr_volume(struct audio_stream_out *stream, float left,
5978 float right)
5979{
5980 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305981 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305982 char mixer_ctl_name[128];
5983 struct audio_device *adev = out->dev;
5984 struct mixer_ctl *ctl;
5985 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5986 PCM_PLAYBACK);
5987
5988 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5989 "Compress Playback %d Volume", pcm_device_id);
5990 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5991 if (!ctl) {
5992 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5993 __func__, mixer_ctl_name);
5994 return -EINVAL;
5995 }
5996 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
5997 __func__, mixer_ctl_name, left, right);
5998 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
5999 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
6000 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
6001
6002 return 0;
6003}
6004
Zhou Song2b8f28f2017-09-11 10:51:38 +08006005static int out_set_voip_volume(struct audio_stream_out *stream, float left,
6006 float right)
6007{
6008 struct stream_out *out = (struct stream_out *)stream;
6009 char mixer_ctl_name[] = "App Type Gain";
6010 struct audio_device *adev = out->dev;
6011 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05306012 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08006013
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07006014 if (!is_valid_volume(left, right)) {
6015 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
6016 __func__, left, right);
6017 return -EINVAL;
6018 }
6019
Zhou Song2b8f28f2017-09-11 10:51:38 +08006020 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
6021 if (!ctl) {
6022 ALOGE("%s: Could not get ctl for mixer cmd - %s",
6023 __func__, mixer_ctl_name);
6024 return -EINVAL;
6025 }
6026
6027 set_values[0] = 0; //0: Rx Session 1:Tx Session
6028 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05306029 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
6030 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08006031
6032 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
6033 return 0;
6034}
6035
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05306036static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
6037 float right)
6038{
6039 struct stream_out *out = (struct stream_out *)stream;
6040 /* Volume control for pcm playback */
6041 if (left != right) {
6042 return -EINVAL;
6043 } else {
6044 char mixer_ctl_name[128];
6045 struct audio_device *adev = out->dev;
6046 struct mixer_ctl *ctl;
6047 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
6048 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
6049 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
6050 if (!ctl) {
6051 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
6052 return -EINVAL;
6053 }
6054
6055 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
6056 int ret = mixer_ctl_set_value(ctl, 0, volume);
6057 if (ret < 0) {
6058 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
6059 return -EINVAL;
6060 }
6061
6062 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
6063
6064 return 0;
6065 }
6066}
6067
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006068static int out_set_volume(struct audio_stream_out *stream, float left,
6069 float right)
6070{
Eric Laurenta9024de2013-04-04 09:19:12 -07006071 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006072 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306073 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006074
Arun Mirpuri5d170872019-03-26 13:21:31 -07006075 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07006076 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
6077 /* only take left channel into account: the API is for stereo anyway */
6078 out->muted = (left == 0.0f);
6079 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006080 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306081 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006082 /*
6083 * Set mute or umute on HDMI passthrough stream.
6084 * Only take left channel into account.
6085 * Mute is 0 and unmute 1
6086 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306087 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306088 } else if (out->format == AUDIO_FORMAT_DSD){
6089 char mixer_ctl_name[128] = "DSD Volume";
6090 struct audio_device *adev = out->dev;
6091 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
6092
6093 if (!ctl) {
6094 ALOGE("%s: Could not get ctl for mixer cmd - %s",
6095 __func__, mixer_ctl_name);
6096 return -EINVAL;
6097 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05306098 volume[0] = (long)(AmpToDb(left));
6099 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306100 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
6101 return 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006102 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS) &&
Derek Chendf05eea2019-08-01 13:57:49 -07006103 (out->car_audio_stream == CAR_AUDIO_STREAM_MEDIA)) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07006104 ALOGD("%s: Overriding offload set volume for media bus stream", __func__);
6105 struct listnode *node = NULL;
6106 list_for_each(node, &adev->active_outputs_list) {
6107 streams_output_ctxt_t *out_ctxt = node_to_item(node,
6108 streams_output_ctxt_t,
6109 list);
6110 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
6111 out->volume_l = out_ctxt->output->volume_l;
6112 out->volume_r = out_ctxt->output->volume_r;
6113 }
6114 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08006115 pthread_mutex_lock(&out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +08006116 if (!out->a2dp_muted) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07006117 ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
6118 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08006119 pthread_mutex_unlock(&out->latch_lock);
Philippe Gravel1c9ac352019-05-28 16:08:37 -07006120 return ret;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006121 } else {
Weiyin Jiang280ea742020-09-08 20:28:22 +08006122 pthread_mutex_lock(&out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +08006123 ALOGV("%s: compress mute %d", __func__, out->a2dp_muted);
6124 if (!out->a2dp_muted)
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306125 ret = out_set_compr_volume(stream, left, right);
6126 out->volume_l = left;
6127 out->volume_r = right;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006128 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306129 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006130 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07006131 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08006132 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
6133 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Songbaddf9f2020-11-20 13:57:39 +08006134 pthread_mutex_lock(&out->latch_lock);
Aalique Grahame22e49102018-12-18 14:23:57 -08006135 if (!out->standby) {
6136 audio_extn_utils_send_app_type_gain(out->dev,
6137 out->app_type_cfg.app_type,
6138 &out->app_type_cfg.gain[0]);
Zhou Songbaddf9f2020-11-20 13:57:39 +08006139 if (!out->a2dp_muted)
6140 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08006141 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08006142 out->volume_l = left;
6143 out->volume_r = right;
Zhou Songbaddf9f2020-11-20 13:57:39 +08006144 pthread_mutex_unlock(&out->latch_lock);
Zhou Song2b8f28f2017-09-11 10:51:38 +08006145 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006146 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
6147 ALOGV("%s: MMAP set volume called", __func__);
6148 if (!out->standby)
6149 ret = out_set_mmap_volume(stream, left, right);
6150 out->volume_l = left;
6151 out->volume_r = right;
6152 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05306153 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05306154 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
6155 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Zhou Songbaddf9f2020-11-20 13:57:39 +08006156 pthread_mutex_lock(&out->latch_lock);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05306157 /* Volume control for pcm playback */
Zhou Songbaddf9f2020-11-20 13:57:39 +08006158 if (!out->standby && !out->a2dp_muted)
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05306159 ret = out_set_pcm_volume(stream, left, right);
6160 else
6161 out->apply_volume = true;
6162
6163 out->volume_l = left;
6164 out->volume_r = right;
Zhou Songbaddf9f2020-11-20 13:57:39 +08006165 pthread_mutex_unlock(&out->latch_lock);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05306166 return ret;
Derek Chenf13dd492018-11-13 14:53:51 -08006167 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
6168 ALOGV("%s: bus device set volume called", __func__);
Zhou Songbaddf9f2020-11-20 13:57:39 +08006169 pthread_mutex_lock(&out->latch_lock);
6170 if (!out->standby && !out->a2dp_muted)
Derek Chenf13dd492018-11-13 14:53:51 -08006171 ret = out_set_pcm_volume(stream, left, right);
6172 out->volume_l = left;
6173 out->volume_r = right;
Zhou Songbaddf9f2020-11-20 13:57:39 +08006174 pthread_mutex_unlock(&out->latch_lock);
Derek Chenf13dd492018-11-13 14:53:51 -08006175 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07006176 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006177
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006178 return -ENOSYS;
6179}
6180
Zhou Songc9672822017-08-16 16:01:39 +08006181static void update_frames_written(struct stream_out *out, size_t bytes)
6182{
6183 size_t bpf = 0;
6184
6185 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
6186 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
6187 bpf = 1;
6188 else if (!is_offload_usecase(out->usecase))
6189 bpf = audio_bytes_per_sample(out->format) *
6190 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08006191
6192 pthread_mutex_lock(&out->position_query_lock);
6193 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08006194 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08006195 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
6196 }
6197 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08006198}
6199
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006200int split_and_write_audio_haptic_data(struct stream_out *out,
6201 const void *buffer, size_t bytes_to_write)
6202{
6203 struct audio_device *adev = out->dev;
6204
6205 int ret = 0;
6206 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
6207 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
6208 size_t frame_size = channel_count * bytes_per_sample;
6209 size_t frame_count = bytes_to_write / frame_size;
6210
6211 bool force_haptic_path =
6212 property_get_bool("vendor.audio.test_haptic", false);
6213
6214 // extract Haptics data from Audio buffer
6215 bool alloc_haptic_buffer = false;
6216 int haptic_channel_count = adev->haptics_config.channels;
6217 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
6218 size_t audio_frame_size = frame_size - haptic_frame_size;
6219 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
6220
6221 if (adev->haptic_buffer == NULL) {
6222 alloc_haptic_buffer = true;
6223 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
6224 free(adev->haptic_buffer);
6225 adev->haptic_buffer_size = 0;
6226 alloc_haptic_buffer = true;
6227 }
6228
6229 if (alloc_haptic_buffer) {
6230 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08006231 if(adev->haptic_buffer == NULL) {
6232 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
6233 return -ENOMEM;
6234 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006235 adev->haptic_buffer_size = total_haptic_buffer_size;
6236 }
6237
6238 size_t src_index = 0, aud_index = 0, hap_index = 0;
6239 uint8_t *audio_buffer = (uint8_t *)buffer;
6240 uint8_t *haptic_buffer = adev->haptic_buffer;
6241
6242 // This is required for testing only. This works for stereo data only.
6243 // One channel is fed to audio stream and other to haptic stream for testing.
6244 if (force_haptic_path)
6245 audio_frame_size = haptic_frame_size = bytes_per_sample;
6246
6247 for (size_t i = 0; i < frame_count; i++) {
6248 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
6249 audio_frame_size);
6250 aud_index += audio_frame_size;
6251 src_index += audio_frame_size;
6252
6253 if (adev->haptic_pcm)
6254 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
6255 haptic_frame_size);
6256 hap_index += haptic_frame_size;
6257 src_index += haptic_frame_size;
6258
6259 // This is required for testing only.
6260 // Discard haptic channel data.
6261 if (force_haptic_path)
6262 src_index += haptic_frame_size;
6263 }
6264
6265 // write to audio pipeline
6266 ret = pcm_write(out->pcm, (void *)audio_buffer,
6267 frame_count * audio_frame_size);
6268
6269 // write to haptics pipeline
6270 if (adev->haptic_pcm)
6271 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
6272 frame_count * haptic_frame_size);
6273
6274 return ret;
6275}
6276
Aalique Grahame22e49102018-12-18 14:23:57 -08006277#ifdef NO_AUDIO_OUT
6278static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
6279 const void *buffer __unused, size_t bytes)
6280{
6281 struct stream_out *out = (struct stream_out *)stream;
6282
6283 /* No Output device supported other than BT for playback.
6284 * Sleep for the amount of buffer duration
6285 */
6286 lock_output_stream(out);
6287 usleep(bytes * 1000000 / audio_stream_out_frame_size(
6288 (const struct audio_stream_out *)&out->stream) /
6289 out_get_sample_rate(&out->stream.common));
6290 pthread_mutex_unlock(&out->lock);
6291 return bytes;
6292}
6293#endif
6294
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006295static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
6296 size_t bytes)
6297{
6298 struct stream_out *out = (struct stream_out *)stream;
6299 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07006300 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05306301 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006302 const size_t frame_size = audio_stream_out_frame_size(stream);
6303 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05306304 struct audio_usecase *usecase = NULL;
Meng Wang4c32fb42020-01-16 17:57:11 +08006305 uint32_t compr_passthr = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006306
Haynes Mathew George380745d2017-10-04 15:27:45 -07006307 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006308 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306309
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05006310 if (CARD_STATUS_OFFLINE == out->card_status ||
6311 POWER_POLICY_STATUS_OFFLINE == adev->out_power_policy) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08006312
Dhananjay Kumarac341582017-02-23 23:42:25 +05306313 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306314 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05306315 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
6316 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006317 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05306318 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05306319 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05306320 ALOGD(" %s: sound card is not active/SSR state", __func__);
6321 ret= -EIO;
6322 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306323 }
6324 }
6325
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306326 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05306327 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05306328 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306329 goto exit;
6330 }
6331
Haynes Mathew George16081042017-05-31 17:16:49 -07006332 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
6333 ret = -EINVAL;
6334 goto exit;
6335 }
6336
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006337 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306338 !out->is_iec61937_info_available) {
6339
6340 if (!audio_extn_passthru_is_passthrough_stream(out)) {
6341 out->is_iec61937_info_available = true;
6342 } else if (audio_extn_passthru_is_enabled()) {
6343 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05306344 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05306345
6346 if((out->format == AUDIO_FORMAT_DTS) ||
6347 (out->format == AUDIO_FORMAT_DTS_HD)) {
6348 ret = audio_extn_passthru_update_dts_stream_configuration(out,
6349 buffer, bytes);
6350 if (ret) {
6351 if (ret != -ENOSYS) {
6352 out->is_iec61937_info_available = false;
6353 ALOGD("iec61937 transmission info not yet updated retry");
6354 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306355 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05306356 /* if stream has started and after that there is
6357 * stream config change (iec transmission config)
6358 * then trigger select_device to update backend configuration.
6359 */
6360 out->stream_config_changed = true;
6361 pthread_mutex_lock(&adev->lock);
6362 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306363 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08006364 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306365 ret = -EINVAL;
6366 goto exit;
6367 }
Manish Dewangan671a4202017-08-18 17:30:46 +05306368 pthread_mutex_unlock(&adev->lock);
6369 out->stream_config_changed = false;
6370 out->is_iec61937_info_available = true;
6371 }
6372 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05306373
Meng Wang4c32fb42020-01-16 17:57:11 +08006374#ifdef AUDIO_GKI_ENABLED
6375 /* out->compr_config.codec->reserved[0] is for compr_passthr */
6376 compr_passthr = out->compr_config.codec->reserved[0];
6377#else
6378 compr_passthr = out->compr_config.codec->compr_passthr;
6379#endif
6380
Garmond Leung317cbf12017-09-13 16:20:50 -07006381 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Meng Wang4c32fb42020-01-16 17:57:11 +08006382 (compr_passthr == PASSTHROUGH) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05306383 (out->is_iec61937_info_available == true)) {
6384 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
6385 ret = -EINVAL;
6386 goto exit;
6387 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05306388 }
6389 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306390
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006391 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02006392 (audio_extn_a2dp_source_is_suspended())) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006393 if (!(compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER) ||
6394 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Zhou Songd01e7a22020-09-23 22:49:01 +08006395 if (!is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306396 ret = -EIO;
6397 goto exit;
6398 }
6399 }
6400 }
6401
Weiyin Jiangabedea32020-12-09 12:49:19 +08006402 if (is_usb_out_device_type(&out->device_list) &&
6403 !audio_extn_usb_connected(NULL)) {
6404 ret = -EIO;
6405 goto exit;
6406 }
6407
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006408 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07006409 out->standby = false;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006410 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
6411
Eric Laurent150dbfe2013-02-27 14:31:02 -08006412 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006413 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
6414 ret = voice_extn_compress_voip_start_output_stream(out);
6415 else
6416 ret = start_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006417 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006418 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07006419 out->standby = true;
Weiyin Jiangac2bae82020-07-29 17:23:53 +08006420 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006421 goto exit;
6422 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306423 out->started = 1;
Andy Hunga1f48fa2019-07-01 18:14:53 -07006424 out->last_fifo_valid = false; // we're coming out of standby, last_fifo isn't valid.
Weiyin Jiangac2bae82020-07-29 17:23:53 +08006425
6426 if ((last_known_cal_step != -1) && (adev->platform != NULL)) {
vivek mehtab72d08d2016-04-29 03:16:47 -07006427 ALOGD("%s: retry previous failed cal level set", __func__);
Weiyin Jiangac2bae82020-07-29 17:23:53 +08006428 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05306429 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07006430 }
Weiyin Jiangac2bae82020-07-29 17:23:53 +08006431 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306432
6433 if ((out->is_iec61937_info_available == true) &&
6434 (audio_extn_passthru_is_passthrough_stream(out))&&
6435 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
6436 ret = -EINVAL;
6437 goto exit;
6438 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05306439 if (out->set_dual_mono)
6440 audio_extn_send_dual_mono_mixing_coefficients(out);
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006441
Dechen Chai22768452021-07-30 09:29:16 +05306442#ifndef LINUX_ENABLED
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006443 // log startup time in ms.
6444 simple_stats_log(
6445 &out->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Dechen Chai22768452021-07-30 09:29:16 +05306446#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006447 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006448
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006449 if (adev->is_channel_status_set == false &&
6450 compare_device_type(&out->device_list,
6451 AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Alexy Josephb1379942016-01-29 15:49:38 -08006452 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05306453 adev->is_channel_status_set = true;
6454 }
6455
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05306456 if ((adev->use_old_pspd_mix_ctrl == true) &&
6457 (out->pspd_coeff_sent == false)) {
6458 /*
6459 * Need to resend pspd coefficients after stream started for
6460 * older kernel version as it does not save the coefficients
6461 * and also stream has to be started for coeff to apply.
6462 */
6463 usecase = get_usecase_from_list(adev, out->usecase);
6464 if (usecase != NULL) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05306465 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05306466 out->pspd_coeff_sent = true;
6467 }
6468 }
6469
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006470 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08006471 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006472 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006473 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006474 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
6475 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05306476 if (out->send_next_track_params && out->is_compr_metadata_avail) {
6477 ALOGD("copl(%p):send next track params in gapless", out);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08006478 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05306479 out->send_next_track_params = false;
6480 out->is_compr_metadata_avail = false;
6481 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006482 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05306483 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306484 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006485
Ashish Jain83a6cc22016-06-28 14:34:17 +05306486 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05306487 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05306488 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05306489 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006490 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05306491 return -EINVAL;
6492 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05306493 audio_format_t dst_format = out->hal_op_format;
6494 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306495
Dieter Luecking5d57def2018-09-07 14:23:37 +02006496 /* prevent division-by-zero */
6497 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
6498 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
6499 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
6500 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05306501 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006502 ATRACE_END();
6503 return -EINVAL;
6504 }
6505
Ashish Jainf1eaa582016-05-23 20:54:24 +05306506 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
6507 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
6508
Ashish Jain83a6cc22016-06-28 14:34:17 +05306509 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05306510 dst_format,
6511 buffer,
6512 src_format,
6513 frames);
6514
Ashish Jain83a6cc22016-06-28 14:34:17 +05306515 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05306516 bytes_to_write);
6517
6518 /*Convert written bytes in audio flinger format*/
6519 if (ret > 0)
6520 ret = ((ret * format_to_bitwidth_table[out->format]) /
6521 format_to_bitwidth_table[dst_format]);
6522 }
6523 } else
6524 ret = compress_write(out->compr, buffer, bytes);
6525
Zhou Songc9672822017-08-16 16:01:39 +08006526 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
6527 update_frames_written(out, bytes);
6528
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306529 if (ret < 0)
6530 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08006531 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05306532 /*msg to cb thread only if non blocking write is enabled*/
6533 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05306534 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006535 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05306536 } else if (-ENETRESET == ret) {
6537 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306538 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05306539 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05306540 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006541 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05306542 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006543 }
Ashish Jain5106d362016-05-11 19:23:33 +05306544
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05306545 /* Call compr start only when non-zero bytes of data is there to be rendered */
6546 if (!out->playback_started && ret > 0) {
6547 int status = compress_start(out->compr);
6548 if (status < 0) {
6549 ret = status;
6550 ALOGE("%s: compr start failed with err %d", __func__, errno);
6551 goto exit;
6552 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07006553 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006554 out->playback_started = 1;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006555 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006556 out->offload_state = OFFLOAD_STATE_PLAYING;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006557 pthread_mutex_unlock(&out->latch_lock);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006558
6559 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6560 popcount(out->channel_mask),
6561 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006562 }
6563 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006564 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006565 return ret;
6566 } else {
6567 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006568 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006569 if (out->muted)
6570 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006571 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
6572 __func__, frames, frame_size, bytes_to_write);
6573
Aalique Grahame22e49102018-12-18 14:23:57 -08006574 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07006575 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
6576 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
6577 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006578 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
6579 int16_t *src = (int16_t *)buffer;
6580 int16_t *dst = (int16_t *)buffer;
6581
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006582 LOG_ALWAYS_FATAL_IF(channel_count > 2 ||
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006583 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08006584 "out_write called for %s use case with wrong properties",
6585 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006586
6587 /*
6588 * FIXME: this can be removed once audio flinger mixer supports
6589 * mono output
6590 */
6591
6592 /*
6593 * Code below goes over each frame in the buffer and adds both
6594 * L and R samples and then divides by 2 to convert to mono
6595 */
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006596 if (channel_count == 2) {
6597 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
6598 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
6599 }
6600 bytes_to_write /= 2;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006601 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006602 }
Andy Hunga1f48fa2019-07-01 18:14:53 -07006603
6604 // Note: since out_get_presentation_position() is called alternating with out_write()
6605 // by AudioFlinger, we can check underruns using the prior timestamp read.
6606 // (Alternately we could check if the buffer is empty using pcm_get_htimestamp().
6607 if (out->last_fifo_valid) {
6608 // compute drain to see if there is an underrun.
6609 const int64_t current_ns = systemTime(SYSTEM_TIME_MONOTONIC); // sys call
Dhananjay Kumara4429632020-07-11 02:53:37 +05306610 int64_t time_diff_ns = current_ns - out->last_fifo_time_ns;
6611 int64_t frames_by_time =
6612 ((time_diff_ns > 0) && (time_diff_ns < (INT64_MAX / out->config.rate))) ?
6613 (time_diff_ns * out->config.rate / NANOS_PER_SECOND) : 0;
Andy Hunga1f48fa2019-07-01 18:14:53 -07006614 const int64_t underrun = frames_by_time - out->last_fifo_frames_remaining;
6615
6616 if (underrun > 0) {
Dechen Chai22768452021-07-30 09:29:16 +05306617#ifndef LINUX_ENABLED
Andy Hunga1f48fa2019-07-01 18:14:53 -07006618 simple_stats_log(&out->fifo_underruns, underrun);
Dechen Chai22768452021-07-30 09:29:16 +05306619#endif
Andy Hunga1f48fa2019-07-01 18:14:53 -07006620
6621 ALOGW("%s: underrun(%lld) "
6622 "frames_by_time(%lld) > out->last_fifo_frames_remaining(%lld)",
6623 __func__,
6624 (long long)out->fifo_underruns.n,
6625 (long long)frames_by_time,
6626 (long long)out->last_fifo_frames_remaining);
6627 }
6628 out->last_fifo_valid = false; // we're writing below, mark fifo info as stale.
6629 }
6630
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306631 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006632
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006633 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006634
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006635 if (out->config.rate)
6636 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
6637 out->config.rate;
6638
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006639 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006640 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
6641
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006642 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006643 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006644 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306645 out->convert_buffer != NULL) {
6646
6647 memcpy_by_audio_format(out->convert_buffer,
6648 out->hal_op_format,
6649 buffer,
6650 out->hal_ip_format,
6651 out->config.period_size * out->config.channels);
6652
6653 ret = pcm_write(out->pcm, out->convert_buffer,
6654 (out->config.period_size *
6655 out->config.channels *
6656 format_to_bitwidth_table[out->hal_op_format]));
6657 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05306658 /*
6659 * To avoid underrun in DSP when the application is not pumping
6660 * data at required rate, check for the no. of bytes and ignore
6661 * pcm_write if it is less than actual buffer size.
6662 * It is a work around to a change in compress VOIP driver.
6663 */
6664 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
6665 bytes < (out->config.period_size * out->config.channels *
6666 audio_bytes_per_sample(out->format))) {
6667 size_t voip_buf_size =
6668 out->config.period_size * out->config.channels *
6669 audio_bytes_per_sample(out->format);
6670 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
6671 __func__, bytes, voip_buf_size);
6672 usleep(((uint64_t)voip_buf_size - bytes) *
6673 1000000 / audio_stream_out_frame_size(stream) /
6674 out_get_sample_rate(&out->stream.common));
6675 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006676 } else {
6677 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
6678 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
6679 else
6680 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
6681 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306682 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006683
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006684 release_out_focus(out);
6685
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306686 if (ret < 0)
6687 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08006688 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05306689 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006690 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006691 }
6692
6693exit:
Zhou Songc9672822017-08-16 16:01:39 +08006694 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306695 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306696 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306697 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006698 pthread_mutex_unlock(&out->lock);
6699
6700 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006701 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08006702 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306703 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306704 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306705 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306706 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306707 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306708 out->standby = true;
6709 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306710 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006711 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
6712 /* prevent division-by-zero */
6713 uint32_t stream_size = audio_stream_out_frame_size(stream);
6714 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006715
Dieter Luecking5d57def2018-09-07 14:23:37 +02006716 if ((stream_size == 0) || (srate == 0)) {
6717 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
6718 ATRACE_END();
6719 return -EINVAL;
6720 }
6721 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
6722 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006723 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05306724 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006725 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006726 return ret;
6727 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006728 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07006729 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006730 return bytes;
6731}
6732
6733static int out_get_render_position(const struct audio_stream_out *stream,
6734 uint32_t *dsp_frames)
6735{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006736 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08006737
6738 if (dsp_frames == NULL)
6739 return -EINVAL;
6740
6741 *dsp_frames = 0;
6742 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08006743 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05306744
6745 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
6746 * this operation and adev_close_output_stream(where out gets reset).
6747 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05306748 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006749 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05306750 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006751 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05306752 return 0;
6753 }
6754
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006755 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05306756 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306757 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006758 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306759 if (ret < 0)
6760 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006761 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05306762 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006763 }
Naresh Tanniru80659832014-06-04 18:17:56 +05306764 if (-ENETRESET == ret) {
6765 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306766 out->card_status = CARD_STATUS_OFFLINE;
6767 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306768 } else if(ret < 0) {
6769 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306770 ret = -EINVAL;
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05006771 } else if (out->card_status == CARD_STATUS_OFFLINE ||
6772 adev->out_power_policy == POWER_POLICY_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05306773 /*
6774 * Handle corner case where compress session is closed during SSR
6775 * and timestamp is queried
6776 */
6777 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306778 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306779 } else if (out->prev_card_status_offline) {
6780 ALOGE("ERROR: previously sound card was offline,return error");
6781 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306782 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306783 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006784 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05306785 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306786 pthread_mutex_unlock(&out->lock);
6787 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08006788 } else if (audio_is_linear_pcm(out->format)) {
6789 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006790 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08006791 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006792 } else
6793 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006794}
6795
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006796static int out_add_audio_effect(const struct audio_stream *stream __unused,
6797 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006798{
6799 return 0;
6800}
6801
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006802static int out_remove_audio_effect(const struct audio_stream *stream __unused,
6803 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006804{
6805 return 0;
6806}
6807
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006808static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
6809 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006810{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05306811 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006812}
6813
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006814static int out_get_presentation_position(const struct audio_stream_out *stream,
6815 uint64_t *frames, struct timespec *timestamp)
6816{
6817 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05306818 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07006819 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006820
Ashish Jain5106d362016-05-11 19:23:33 +05306821 /* below piece of code is not guarded against any lock because audioFliner serializes
6822 * this operation and adev_close_output_stream( where out gets reset).
6823 */
6824 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05306825 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006826 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05306827 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
6828 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
6829 return 0;
6830 }
6831
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006832 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006833
Ashish Jain5106d362016-05-11 19:23:33 +05306834 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
6835 ret = compress_get_tstamp(out->compr, &dsp_frames,
6836 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08006837 // Adjustment accounts for A2dp encoder latency with offload usecases
6838 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006839 if (is_a2dp_out_device_type(&out->device_list)) {
yidongh0515e042017-07-06 15:00:34 +08006840 unsigned long offset =
6841 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
6842 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
6843 }
Ashish Jain5106d362016-05-11 19:23:33 +05306844 ALOGVV("%s rendered frames %ld sample_rate %d",
6845 __func__, dsp_frames, out->sample_rate);
6846 *frames = dsp_frames;
6847 if (ret < 0)
6848 ret = -errno;
6849 if (-ENETRESET == ret) {
6850 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306851 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05306852 ret = -EINVAL;
6853 } else
6854 ret = 0;
6855 /* this is the best we can do */
6856 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07006857 } else {
6858 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08006859 unsigned int avail;
6860 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
George Gao62ebc722019-07-29 16:29:44 -07006861 uint64_t signed_frames = 0;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006862 uint64_t frames_temp = 0;
George Gao62ebc722019-07-29 16:29:44 -07006863
Andy Hunga1f48fa2019-07-01 18:14:53 -07006864 if (out->kernel_buffer_size > avail) {
6865 frames_temp = out->last_fifo_frames_remaining = out->kernel_buffer_size - avail;
6866 } else {
6867 ALOGW("%s: avail:%u > kernel_buffer_size:%zu clamping!",
6868 __func__, avail, out->kernel_buffer_size);
6869 avail = out->kernel_buffer_size;
6870 frames_temp = out->last_fifo_frames_remaining = 0;
6871 }
6872 out->last_fifo_valid = true;
6873 out->last_fifo_time_ns = audio_utils_ns_from_timespec(timestamp);
6874
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006875 if (out->written >= frames_temp)
6876 signed_frames = out->written - frames_temp;
George Gao62ebc722019-07-29 16:29:44 -07006877
Andy Hunga1f48fa2019-07-01 18:14:53 -07006878 ALOGVV("%s: frames:%lld avail:%u kernel_buffer_size:%zu",
6879 __func__, (long long)signed_frames, avail, out->kernel_buffer_size);
6880
Weiyin Jiangd4633762018-03-16 12:05:03 +08006881 // This adjustment accounts for buffering after app processor.
6882 // It is based on estimated DSP latency per use case, rather than exact.
George Gao9ba8a142020-07-23 14:30:03 -07006883 frames_temp = platform_render_latency(out) *
Robert Lee58215542019-07-15 20:55:12 +08006884 out->sample_rate / 1000000LL;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006885 if (signed_frames >= frames_temp)
6886 signed_frames -= frames_temp;
Aniket Kumar Lataff613152017-07-18 18:19:21 -07006887
Weiyin Jiangd4633762018-03-16 12:05:03 +08006888 // Adjustment accounts for A2dp encoder latency with non offload usecases
6889 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006890 if (is_a2dp_out_device_type(&out->device_list)) {
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006891 frames_temp = audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000;
6892 if (signed_frames >= frames_temp)
6893 signed_frames -= frames_temp;
Weiyin Jiangd4633762018-03-16 12:05:03 +08006894 }
6895
6896 // It would be unusual for this value to be negative, but check just in case ...
George Gao62ebc722019-07-29 16:29:44 -07006897 *frames = signed_frames;
6898 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006899 }
Eric Laurenta7a33042019-07-10 16:20:22 -07006900 } else if (out->card_status == CARD_STATUS_OFFLINE ||
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05006901 adev->out_power_policy == POWER_POLICY_STATUS_OFFLINE ||
Eric Laurenta7a33042019-07-10 16:20:22 -07006902 // audioflinger still needs position updates when A2DP is suspended
Jasmine Cha5c2517f2019-09-09 11:07:28 +08006903 (is_a2dp_out_device_type(&out->device_list) && audio_extn_a2dp_source_is_suspended())) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306904 *frames = out->written;
6905 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306906 if (is_offload_usecase(out->usecase))
6907 ret = -EINVAL;
6908 else
6909 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006910 }
6911 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006912 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006913 return ret;
6914}
6915
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006916static int out_set_callback(struct audio_stream_out *stream,
6917 stream_callback_t callback, void *cookie)
6918{
6919 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006920 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006921
6922 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006923 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006924 out->client_callback = callback;
6925 out->client_cookie = cookie;
6926 if (out->adsp_hdlr_stream_handle) {
6927 ret = audio_extn_adsp_hdlr_stream_set_callback(
6928 out->adsp_hdlr_stream_handle,
6929 callback,
6930 cookie);
6931 if (ret)
6932 ALOGW("%s:adsp hdlr callback registration failed %d",
6933 __func__, ret);
6934 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006935 pthread_mutex_unlock(&out->lock);
6936 return 0;
6937}
6938
6939static int out_pause(struct audio_stream_out* stream)
6940{
6941 struct stream_out *out = (struct stream_out *)stream;
6942 int status = -ENOSYS;
6943 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006944 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006945 ALOGD("copl(%p):pause compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306946 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006947 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006948 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006949 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306950 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05306951 status = compress_pause(out->compr);
6952
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006953 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006954
Mingming Yin21854652016-04-13 11:54:02 -07006955 if (audio_extn_passthru_is_active()) {
6956 ALOGV("offload use case, pause passthru");
6957 audio_extn_passthru_on_pause(out);
6958 }
6959
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306960 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006961 audio_extn_dts_notify_playback_state(out->usecase, 0,
6962 out->sample_rate, popcount(out->channel_mask),
6963 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006964 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08006965 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006966 pthread_mutex_unlock(&out->lock);
6967 }
6968 return status;
6969}
6970
6971static int out_resume(struct audio_stream_out* stream)
6972{
6973 struct stream_out *out = (struct stream_out *)stream;
6974 int status = -ENOSYS;
6975 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006976 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006977 ALOGD("copl(%p):resume compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306978 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006979 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006980 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006981 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306982 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306983 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07006984 }
6985 if (!status) {
6986 out->offload_state = OFFLOAD_STATE_PLAYING;
6987 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306988 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006989 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6990 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006991 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08006992 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006993 pthread_mutex_unlock(&out->lock);
6994 }
6995 return status;
6996}
6997
6998static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
6999{
7000 struct stream_out *out = (struct stream_out *)stream;
7001 int status = -ENOSYS;
7002 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07007003 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007004 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007005 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
7006 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
7007 else
7008 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
7009 pthread_mutex_unlock(&out->lock);
7010 }
7011 return status;
7012}
7013
7014static int out_flush(struct audio_stream_out* stream)
7015{
7016 struct stream_out *out = (struct stream_out *)stream;
7017 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07007018 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07007019 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007020 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08007021 pthread_mutex_lock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07007022 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
Gautam Manam14c198b2020-12-24 14:08:04 +05307023 pthread_mutex_unlock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07007024 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07007025 } else {
7026 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
Gautam Manam14c198b2020-12-24 14:08:04 +05307027 pthread_mutex_unlock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07007028 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08007029 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007030 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07007031 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007032 return 0;
7033 }
7034 return -ENOSYS;
7035}
7036
Haynes Mathew George16081042017-05-31 17:16:49 -07007037static int out_stop(const struct audio_stream_out* stream)
7038{
7039 struct stream_out *out = (struct stream_out *)stream;
7040 struct audio_device *adev = out->dev;
7041 int ret = -ENOSYS;
7042
7043 ALOGV("%s", __func__);
7044 pthread_mutex_lock(&adev->lock);
7045 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
7046 out->playback_started && out->pcm != NULL) {
7047 pcm_stop(out->pcm);
7048 ret = stop_output_stream(out);
7049 out->playback_started = false;
7050 }
7051 pthread_mutex_unlock(&adev->lock);
7052 return ret;
7053}
7054
7055static int out_start(const struct audio_stream_out* stream)
7056{
7057 struct stream_out *out = (struct stream_out *)stream;
7058 struct audio_device *adev = out->dev;
7059 int ret = -ENOSYS;
7060
7061 ALOGV("%s", __func__);
7062 pthread_mutex_lock(&adev->lock);
7063 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
7064 !out->playback_started && out->pcm != NULL) {
7065 ret = start_output_stream(out);
7066 if (ret == 0) {
7067 out->playback_started = true;
7068 }
7069 }
7070 pthread_mutex_unlock(&adev->lock);
7071 return ret;
7072}
7073
7074/*
7075 * Modify config->period_count based on min_size_frames
7076 */
7077static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
7078{
7079 int periodCountRequested = (min_size_frames + config->period_size - 1)
7080 / config->period_size;
7081 int periodCount = MMAP_PERIOD_COUNT_MIN;
7082
7083 ALOGV("%s original config.period_size = %d config.period_count = %d",
7084 __func__, config->period_size, config->period_count);
7085
7086 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
7087 periodCount *= 2;
7088 }
7089 config->period_count = periodCount;
7090
7091 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
7092}
7093
Phil Burkfe17efd2019-03-25 10:23:35 -07007094// Read offset for the positional timestamp from a persistent vendor property.
7095// This is to workaround apparent inaccuracies in the timing information that
7096// is used by the AAudio timing model. The inaccuracies can cause glitches.
7097static int64_t get_mmap_out_time_offset() {
7098 const int32_t kDefaultOffsetMicros = 0;
7099 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08007100 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07007101 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
7102 return mmap_time_offset_micros * (int64_t)1000;
7103}
7104
Haynes Mathew George16081042017-05-31 17:16:49 -07007105static int out_create_mmap_buffer(const struct audio_stream_out *stream,
7106 int32_t min_size_frames,
7107 struct audio_mmap_buffer_info *info)
7108{
7109 struct stream_out *out = (struct stream_out *)stream;
7110 struct audio_device *adev = out->dev;
7111 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07007112 unsigned int offset1 = 0;
7113 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007114 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07007115 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007116 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07007117
Arun Mirpuri5d170872019-03-26 13:21:31 -07007118 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05307119 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07007120 pthread_mutex_lock(&adev->lock);
7121
Sharad Sanglec6f32552018-05-04 16:15:38 +05307122 if (CARD_STATUS_OFFLINE == out->card_status ||
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05007123 CARD_STATUS_OFFLINE == adev->card_status ||
7124 POWER_POLICY_STATUS_OFFLINE == adev->out_power_policy) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307125 ALOGW("out->card_status or adev->card_status offline, try again");
7126 ret = -EIO;
7127 goto exit;
7128 }
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307129 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07007130 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
7131 ret = -EINVAL;
7132 goto exit;
7133 }
7134 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
7135 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
7136 ret = -ENOSYS;
7137 goto exit;
7138 }
7139 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
7140 if (out->pcm_device_id < 0) {
7141 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
7142 __func__, out->pcm_device_id, out->usecase);
7143 ret = -EINVAL;
7144 goto exit;
7145 }
7146
7147 adjust_mmap_period_count(&out->config, min_size_frames);
7148
Arun Mirpuri5d170872019-03-26 13:21:31 -07007149 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07007150 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
7151 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
7152 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307153 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307154 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7155 out->card_status = CARD_STATUS_OFFLINE;
7156 adev->card_status = CARD_STATUS_OFFLINE;
7157 ret = -EIO;
7158 goto exit;
7159 }
7160
Haynes Mathew George16081042017-05-31 17:16:49 -07007161 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
7162 step = "open";
7163 ret = -ENODEV;
7164 goto exit;
7165 }
7166 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
7167 if (ret < 0) {
7168 step = "begin";
7169 goto exit;
7170 }
juyuchen626833d2019-06-04 16:48:02 +08007171
7172 info->flags = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007173 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07007174 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07007175 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07007176 ret = platform_get_mmap_data_fd(adev->platform,
7177 out->pcm_device_id, 0 /*playback*/,
7178 &info->shared_memory_fd,
7179 &mmap_size);
7180 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07007181 // Fall back to non exclusive mode
7182 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
7183 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07007184 out->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
7185 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, out->mmap_shared_memory_fd);
7186
Arun Mirpuri5d170872019-03-26 13:21:31 -07007187 if (mmap_size < buffer_size) {
7188 step = "mmap";
7189 goto exit;
7190 }
juyuchen626833d2019-06-04 16:48:02 +08007191 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07007192 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007193 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07007194 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07007195
7196 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
7197 if (ret < 0) {
7198 step = "commit";
7199 goto exit;
7200 }
7201
Phil Burkfe17efd2019-03-25 10:23:35 -07007202 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
7203
Haynes Mathew George16081042017-05-31 17:16:49 -07007204 out->standby = false;
7205 ret = 0;
7206
Arun Mirpuri5d170872019-03-26 13:21:31 -07007207 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07007208 __func__, info->shared_memory_address, info->buffer_size_frames);
7209
7210exit:
7211 if (ret != 0) {
7212 if (out->pcm == NULL) {
7213 ALOGE("%s: %s - %d", __func__, step, ret);
7214 } else {
7215 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
7216 pcm_close(out->pcm);
7217 out->pcm = NULL;
7218 }
7219 }
7220 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05307221 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07007222 return ret;
7223}
7224
7225static int out_get_mmap_position(const struct audio_stream_out *stream,
7226 struct audio_mmap_position *position)
7227{
7228 struct stream_out *out = (struct stream_out *)stream;
7229 ALOGVV("%s", __func__);
7230 if (position == NULL) {
7231 return -EINVAL;
7232 }
7233 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08007234 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07007235 return -ENOSYS;
7236 }
7237 if (out->pcm == NULL) {
7238 return -ENOSYS;
7239 }
7240
7241 struct timespec ts = { 0, 0 };
7242 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
7243 if (ret < 0) {
7244 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
7245 return ret;
7246 }
Phil Burkfe17efd2019-03-25 10:23:35 -07007247 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7248 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07007249 return 0;
7250}
7251
7252
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007253/** audio_stream_in implementation **/
7254static uint32_t in_get_sample_rate(const struct audio_stream *stream)
7255{
7256 struct stream_in *in = (struct stream_in *)stream;
7257
7258 return in->config.rate;
7259}
7260
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007261static int in_set_sample_rate(struct audio_stream *stream __unused,
7262 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007263{
7264 return -ENOSYS;
7265}
7266
7267static size_t in_get_buffer_size(const struct audio_stream *stream)
7268{
7269 struct stream_in *in = (struct stream_in *)stream;
7270
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007271 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
7272 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07007273 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
Raghu Bankapur37cbf382022-12-01 09:30:00 +05307274 return audio_extn_compr_cap_get_buffer_size(pcm_format_to_audio_format(in->config.format));
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307275 else if(audio_extn_cin_attached_usecase(in))
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307276 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007277
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007278 return in->config.period_size * in->af_period_multiplier *
7279 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007280}
7281
7282static uint32_t in_get_channels(const struct audio_stream *stream)
7283{
7284 struct stream_in *in = (struct stream_in *)stream;
7285
7286 return in->channel_mask;
7287}
7288
7289static audio_format_t in_get_format(const struct audio_stream *stream)
7290{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007291 struct stream_in *in = (struct stream_in *)stream;
7292
7293 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007294}
7295
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007296static int in_set_format(struct audio_stream *stream __unused,
7297 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007298{
7299 return -ENOSYS;
7300}
7301
7302static int in_standby(struct audio_stream *stream)
7303{
7304 struct stream_in *in = (struct stream_in *)stream;
7305 struct audio_device *adev = in->dev;
7306 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307307 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
7308 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07007309 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307310
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007311 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007312 if (!in->standby && in->is_st_session) {
7313 ALOGD("%s: sound trigger pcm stop lab", __func__);
7314 audio_extn_sound_trigger_stop_lab(in);
George Gao3018ede2019-10-23 13:23:00 -07007315 if (adev->num_va_sessions > 0)
7316 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007317 in->standby = 1;
7318 }
7319
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007320 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007321 if (adev->adm_deregister_stream)
7322 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
7323
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08007324 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007325 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08007326 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08007327 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08007328 voice_extn_compress_voip_close_input_stream(stream);
7329 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07007330 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
7331 do_stop = in->capture_started;
7332 in->capture_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07007333 if (in->mmap_shared_memory_fd >= 0) {
7334 ALOGV("%s: closing mmap_shared_memory_fd = %d",
7335 __func__, in->mmap_shared_memory_fd);
7336 close(in->mmap_shared_memory_fd);
7337 in->mmap_shared_memory_fd = -1;
7338 }
Zhou Songa8895042016-07-05 17:54:22 +08007339 } else {
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307340 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05307341 audio_extn_cin_close_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08007342 }
7343
Arun Mirpuri5d170872019-03-26 13:21:31 -07007344 if (in->pcm) {
7345 ATRACE_BEGIN("pcm_in_close");
7346 pcm_close(in->pcm);
7347 ATRACE_END();
7348 in->pcm = NULL;
7349 }
7350
Carter Hsu2e429db2019-05-14 18:50:52 +08007351 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08007352 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08007353
George Gao3018ede2019-10-23 13:23:00 -07007354 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
7355 if (adev->num_va_sessions > 0)
7356 adev->num_va_sessions--;
7357 }
Quinn Malef6050362019-01-30 15:55:40 -08007358
Eric Laurent150dbfe2013-02-27 14:31:02 -08007359 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007360 }
7361 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07007362 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007363 return status;
7364}
7365
Aalique Grahame22e49102018-12-18 14:23:57 -08007366static int in_dump(const struct audio_stream *stream,
7367 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007368{
Aalique Grahame22e49102018-12-18 14:23:57 -08007369 struct stream_in *in = (struct stream_in *)stream;
7370
7371 // We try to get the lock for consistency,
7372 // but it isn't necessary for these variables.
7373 // If we're not in standby, we may be blocked on a read.
7374 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
7375 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
7376 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
7377 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
Dechen Chai22768452021-07-30 09:29:16 +05307378#ifndef LINUX_ENABLED
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007379 char buffer[256]; // for statistics formatting
7380 if (in->start_latency_ms.n > 0) {
7381 simple_stats_to_string(&in->start_latency_ms, buffer, sizeof(buffer));
7382 dprintf(fd, " Start latency ms: %s\n", buffer);
7383 }
Dechen Chai22768452021-07-30 09:29:16 +05307384#endif
Aalique Grahame22e49102018-12-18 14:23:57 -08007385 if (locked) {
7386 pthread_mutex_unlock(&in->lock);
7387 }
Dechen Chai22768452021-07-30 09:29:16 +05307388#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -08007389 // dump error info
7390 (void)error_log_dump(
7391 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Dechen Chai22768452021-07-30 09:29:16 +05307392#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007393 return 0;
7394}
7395
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307396static void in_snd_mon_cb(void * stream, struct str_parms * parms)
7397{
7398 if (!stream || !parms)
7399 return;
7400
7401 struct stream_in *in = (struct stream_in *)stream;
7402 struct audio_device *adev = in->dev;
7403
7404 card_status_t status;
7405 int card;
7406 if (parse_snd_card_status(parms, &card, &status) < 0)
7407 return;
7408
7409 pthread_mutex_lock(&adev->lock);
7410 bool valid_cb = (card == adev->snd_card);
7411 pthread_mutex_unlock(&adev->lock);
7412
7413 if (!valid_cb)
7414 return;
7415
7416 lock_input_stream(in);
7417 if (in->card_status != status)
7418 in->card_status = status;
7419 pthread_mutex_unlock(&in->lock);
7420
7421 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
7422 use_case_table[in->usecase],
7423 status == CARD_STATUS_OFFLINE ? "offline" : "online");
7424
7425 // a better solution would be to report error back to AF and let
7426 // it put the stream to standby
7427 if (status == CARD_STATUS_OFFLINE)
7428 in_standby(&in->stream.common);
7429
7430 return;
7431}
7432
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007433int route_input_stream(struct stream_in *in,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007434 struct listnode *devices,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007435 audio_source_t source)
7436{
7437 struct audio_device *adev = in->dev;
7438 int ret = 0;
7439
7440 lock_input_stream(in);
7441 pthread_mutex_lock(&adev->lock);
7442
7443 /* no audio source uses val == 0 */
7444 if ((in->source != source) && (source != AUDIO_SOURCE_DEFAULT)) {
7445 in->source = source;
7446 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
7447 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
7448 (voice_extn_compress_voip_is_format_supported(in->format)) &&
7449 (in->config.rate == 8000 || in->config.rate == 16000 ||
7450 in->config.rate == 32000 || in->config.rate == 48000 ) &&
7451 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
7452 ret = voice_extn_compress_voip_open_input_stream(in);
7453 if (ret != 0) {
7454 ALOGE("%s: Compress voip input cannot be opened, error:%d",
7455 __func__, ret);
7456 }
7457 }
7458 }
7459
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007460 if (!compare_devices(&in->device_list, devices) && !list_empty(devices) &&
7461 is_audio_in_device_type(devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007462 // Workaround: If routing to an non existing usb device, fail gracefully
7463 // The routing request will otherwise block during 10 second
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007464 struct str_parms *usb_addr =
7465 str_parms_create_str(get_usb_device_address(devices));
7466 if (is_usb_in_device_type(devices) && usb_addr &&
Weiyin Jiangabedea32020-12-09 12:49:19 +08007467 !audio_extn_usb_connected(NULL)) {
7468 ALOGW("%s: ignoring rerouting to non existing USB", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007469 ret = -ENOSYS;
7470 } else {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007471 /* If recording is in progress, change the tx device to new device */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007472 assign_devices(&in->device_list, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007473 if (!in->standby && !in->is_st_session) {
7474 ALOGV("update input routing change");
7475 // inform adm before actual routing to prevent glitches.
7476 if (adev->adm_on_routing_change) {
7477 adev->adm_on_routing_change(adev->adm_data,
7478 in->capture_handle);
7479 ret = select_devices(adev, in->usecase);
7480 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7481 adev->adm_routing_changed = true;
7482 }
7483 }
7484 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007485 if (usb_addr)
7486 str_parms_destroy(usb_addr);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007487 }
7488 pthread_mutex_unlock(&adev->lock);
7489 pthread_mutex_unlock(&in->lock);
7490
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07007491 ALOGV("%s: exit: status(%d)", __func__, ret);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007492 return ret;
7493}
7494
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007495static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
7496{
7497 struct stream_in *in = (struct stream_in *)stream;
7498 struct audio_device *adev = in->dev;
7499 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007500 char value[32];
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307501 int err = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007502
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307503 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007504 parms = str_parms_create_str(kvpairs);
7505
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307506 if (!parms)
7507 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007508 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08007509 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007510
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307511 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
7512 if (err >= 0) {
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307513 strlcpy(in->profile, value, sizeof(in->profile));
7514 ALOGV("updating stream profile with value '%s'", in->profile);
7515 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
7516 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007517 &in->device_list, in->flags, in->format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307518 in->sample_rate, in->bit_width,
7519 in->profile, &in->app_type_cfg);
7520 }
7521
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007522 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08007523 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007524
7525 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307526error:
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307527 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007528}
7529
7530static char* in_get_parameters(const struct audio_stream *stream,
7531 const char *keys)
7532{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007533 struct stream_in *in = (struct stream_in *)stream;
7534 struct str_parms *query = str_parms_create_str(keys);
7535 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007536 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007537
7538 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08007539 if (reply) {
7540 str_parms_destroy(reply);
7541 }
7542 if (query) {
7543 str_parms_destroy(query);
7544 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007545 ALOGE("in_get_parameters: failed to create query or reply");
7546 return NULL;
7547 }
7548
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007549 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007550
7551 voice_extn_in_get_parameters(in, query, reply);
7552
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007553 stream_get_parameter_channels(query, reply,
7554 &in->supported_channel_masks[0]);
7555 stream_get_parameter_formats(query, reply,
7556 &in->supported_formats[0]);
7557 stream_get_parameter_rates(query, reply,
7558 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007559 str = str_parms_to_str(reply);
7560 str_parms_destroy(query);
7561 str_parms_destroy(reply);
7562
7563 ALOGV("%s: exit: returns - %s", __func__, str);
7564 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007565}
7566
Aalique Grahame22e49102018-12-18 14:23:57 -08007567static int in_set_gain(struct audio_stream_in *stream,
7568 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007569{
Aalique Grahame22e49102018-12-18 14:23:57 -08007570 struct stream_in *in = (struct stream_in *)stream;
7571 char mixer_ctl_name[128];
7572 struct mixer_ctl *ctl;
7573 int ctl_value;
7574
7575 ALOGV("%s: gain %f", __func__, gain);
7576
7577 if (stream == NULL)
7578 return -EINVAL;
7579
7580 /* in_set_gain() only used to silence MMAP capture for now */
7581 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
7582 return -ENOSYS;
7583
7584 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
7585
7586 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
7587 if (!ctl) {
7588 ALOGW("%s: Could not get ctl for mixer cmd - %s",
7589 __func__, mixer_ctl_name);
7590 return -ENOSYS;
7591 }
7592
7593 if (gain < RECORD_GAIN_MIN)
7594 gain = RECORD_GAIN_MIN;
7595 else if (gain > RECORD_GAIN_MAX)
7596 gain = RECORD_GAIN_MAX;
7597 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
7598
7599 mixer_ctl_set_value(ctl, 0, ctl_value);
7600
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007601 return 0;
7602}
7603
7604static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
7605 size_t bytes)
7606{
7607 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05307608
7609 if (in == NULL) {
7610 ALOGE("%s: stream_in ptr is NULL", __func__);
7611 return -EINVAL;
7612 }
7613
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007614 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05307615 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307616 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007617
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007618 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05307619
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007620 if (in->is_st_session) {
7621 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
7622 /* Read from sound trigger HAL */
7623 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08007624 if (in->standby) {
George Gao3018ede2019-10-23 13:23:00 -07007625 if (adev->num_va_sessions < UINT_MAX)
7626 adev->num_va_sessions++;
Quinn Malef6050362019-01-30 15:55:40 -08007627 in->standby = 0;
7628 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007629 pthread_mutex_unlock(&in->lock);
7630 return bytes;
7631 }
7632
Haynes Mathew George16081042017-05-31 17:16:49 -07007633 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
7634 ret = -ENOSYS;
7635 goto exit;
7636 }
7637
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007638 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
7639 !in->standby && adev->adm_routing_changed) {
7640 ret = -ENOSYS;
7641 goto exit;
7642 }
7643
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007644 if (in->standby) {
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007645 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
7646
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007647 pthread_mutex_lock(&adev->lock);
7648 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
7649 ret = voice_extn_compress_voip_start_input_stream(in);
7650 else
7651 ret = start_input_stream(in);
George Gao3018ede2019-10-23 13:23:00 -07007652 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
7653 if (adev->num_va_sessions < UINT_MAX)
7654 adev->num_va_sessions++;
7655 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007656 pthread_mutex_unlock(&adev->lock);
7657 if (ret != 0) {
7658 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007659 }
7660 in->standby = 0;
Dechen Chai22768452021-07-30 09:29:16 +05307661#ifndef LINUX_ENABLED
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007662 // log startup time in ms.
7663 simple_stats_log(
7664 &in->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Dechen Chai22768452021-07-30 09:29:16 +05307665#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007666 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007667
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05307668 /* Avoid read if capture_stopped is set */
7669 if (android_atomic_acquire_load(&(in->capture_stopped)) > 0) {
7670 ALOGD("%s: force stopped catpure session, ignoring read request", __func__);
7671 ret = -EINVAL;
7672 goto exit;
7673 }
7674
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007675 // what's the duration requested by the client?
7676 long ns = 0;
7677
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307678 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007679 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
7680 in->config.rate;
7681
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007682 ret = request_in_focus(in, ns);
7683 if (ret != 0)
7684 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007685 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007686
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307687 if (audio_extn_cin_attached_usecase(in)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307688 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
7689 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307690 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007691 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307692 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07007693 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007694 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007695 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07007696 } else if (audio_extn_ffv_get_stream() == in) {
7697 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307698 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007699 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307700 /* data from DSP comes in 24_8 format, convert it to 8_24 */
7701 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
7702 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
7703 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307704 ret = -EINVAL;
7705 goto exit;
7706 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307707 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307708 ret = -errno;
7709 }
7710 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307711 /* bytes read is always set to bytes for non compress usecases */
7712 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007713 }
7714
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007715 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007716
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007717 /*
Quinn Malef6050362019-01-30 15:55:40 -08007718 * Instead of writing zeroes here, we could trust the hardware to always
7719 * provide zeroes when muted. This is also muted with voice recognition
7720 * usecases so that other clients do not have access to voice recognition
7721 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007722 */
Quinn Malef6050362019-01-30 15:55:40 -08007723 if ((ret == 0 && voice_get_mic_mute(adev) &&
7724 !voice_is_in_call_rec_stream(in) &&
Zhou Song62ea0282020-03-22 19:53:01 +08007725 (in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY &&
Manoj Kumar N D54cab152023-01-27 16:41:55 +05307726 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY2 &&
7727 in->source != AUDIO_SOURCE_FM_TUNER &&
7728 !is_single_device_type_equal(&in->device_list, AUDIO_DEVICE_IN_FM_TUNER))) ||
Quinn Malef6050362019-01-30 15:55:40 -08007729 (adev->num_va_sessions &&
7730 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
7731 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
7732 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007733 memset(buffer, 0, bytes);
7734
7735exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307736 frame_size = audio_stream_in_frame_size(stream);
7737 if (frame_size > 0)
7738 in->frames_read += bytes_read/frame_size;
7739
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007740 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307741 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007742 pthread_mutex_unlock(&in->lock);
7743
7744 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307745 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307746 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307747 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307748 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307749 in->standby = true;
7750 }
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307751 if (!audio_extn_cin_attached_usecase(in)) {
Sharad Sangled17c9122017-03-20 15:58:52 +05307752 bytes_read = bytes;
7753 memset(buffer, 0, bytes);
7754 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007755 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007756 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7757 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007758 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05307759 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05307760 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007761 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307762 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007763}
7764
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007765static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007766{
7767 return 0;
7768}
7769
Aalique Grahame22e49102018-12-18 14:23:57 -08007770static int in_get_capture_position(const struct audio_stream_in *stream,
7771 int64_t *frames, int64_t *time)
7772{
7773 if (stream == NULL || frames == NULL || time == NULL) {
7774 return -EINVAL;
7775 }
7776 struct stream_in *in = (struct stream_in *)stream;
7777 int ret = -ENOSYS;
7778
7779 lock_input_stream(in);
7780 // note: ST sessions do not close the alsa pcm driver synchronously
7781 // on standby. Therefore, we may return an error even though the
7782 // pcm stream is still opened.
7783 if (in->standby) {
7784 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
7785 "%s stream in standby but pcm not NULL for non ST session", __func__);
7786 goto exit;
7787 }
7788 if (in->pcm) {
7789 struct timespec timestamp;
7790 unsigned int avail;
7791 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
7792 *frames = in->frames_read + avail;
Robert Lee58215542019-07-15 20:55:12 +08007793 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec
George Gao9ba8a142020-07-23 14:30:03 -07007794 - platform_capture_latency(in) * 1000LL;
Kakanaboina Ramanjaneyulu8cedb092021-03-15 15:55:29 +05307795 //Adjustment accounts for A2dp decoder latency for recording usecase
7796 // Note: decoder latency is returned in ms, while platform_capture_latency in ns.
7797 if (is_a2dp_in_device_type(&in->device_list))
7798 *time -= audio_extn_a2dp_get_decoder_latency() * 1000000LL;
Aalique Grahame22e49102018-12-18 14:23:57 -08007799 ret = 0;
7800 }
7801 }
7802exit:
7803 pthread_mutex_unlock(&in->lock);
7804 return ret;
7805}
7806
Carter Hsu2e429db2019-05-14 18:50:52 +08007807static int in_update_effect_list(bool add, effect_handle_t effect,
7808 struct listnode *head)
7809{
7810 struct listnode *node;
7811 struct in_effect_list *elist = NULL;
7812 struct in_effect_list *target = NULL;
7813 int ret = 0;
7814
7815 if (!head)
7816 return ret;
7817
7818 list_for_each(node, head) {
7819 elist = node_to_item(node, struct in_effect_list, list);
7820 if (elist->handle == effect) {
7821 target = elist;
7822 break;
7823 }
7824 }
7825
7826 if (add) {
7827 if (target) {
7828 ALOGD("effect %p already exist", effect);
7829 return ret;
7830 }
7831
7832 target = (struct in_effect_list *)
7833 calloc(1, sizeof(struct in_effect_list));
7834
7835 if (!target) {
7836 ALOGE("%s:fail to allocate memory", __func__);
7837 return -ENOMEM;
7838 }
7839
7840 target->handle = effect;
7841 list_add_tail(head, &target->list);
7842 } else {
7843 if (target) {
7844 list_remove(&target->list);
7845 free(target);
7846 }
7847 }
7848
7849 return ret;
7850}
7851
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007852static int add_remove_audio_effect(const struct audio_stream *stream,
7853 effect_handle_t effect,
7854 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007855{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007856 struct stream_in *in = (struct stream_in *)stream;
7857 int status = 0;
7858 effect_descriptor_t desc;
7859
7860 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007861 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
7862
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007863 if (status != 0)
7864 return status;
7865
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007866 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007867 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08007868 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08007869 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
7870 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007871 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08007872
7873 in_update_effect_list(enable, effect, &in->aec_list);
7874 enable = !list_empty(&in->aec_list);
7875 if (enable == in->enable_aec)
7876 goto exit;
7877
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007878 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007879 ALOGD("AEC enable %d", enable);
7880
Aalique Grahame22e49102018-12-18 14:23:57 -08007881 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7882 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
7883 in->dev->enable_voicerx = enable;
7884 struct audio_usecase *usecase;
7885 struct listnode *node;
7886 list_for_each(node, &in->dev->usecase_list) {
7887 usecase = node_to_item(node, struct audio_usecase, list);
7888 if (usecase->type == PCM_PLAYBACK)
7889 select_devices(in->dev, usecase->id);
7890 }
7891 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007892 if (!in->standby) {
7893 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
7894 select_devices(in->dev, in->usecase);
7895 }
7896
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007897 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007898 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
7899
7900 in_update_effect_list(enable, effect, &in->ns_list);
7901 enable = !list_empty(&in->ns_list);
7902 if (enable == in->enable_ns)
7903 goto exit;
7904
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007905 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007906 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007907 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08007908 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Ramu Gottipatifa5be522021-12-28 19:18:21 +05307909 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
kunleizd96526c2018-04-09 11:12:32 +08007910 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007911 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
7912 select_devices(in->dev, in->usecase);
7913 } else
7914 select_devices(in->dev, in->usecase);
7915 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007916 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007917exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007918 pthread_mutex_unlock(&in->dev->lock);
7919 pthread_mutex_unlock(&in->lock);
7920
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007921 return 0;
7922}
7923
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007924static int in_add_audio_effect(const struct audio_stream *stream,
7925 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007926{
Eric Laurent994a6932013-07-17 11:51:42 -07007927 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007928 return add_remove_audio_effect(stream, effect, true);
7929}
7930
7931static int in_remove_audio_effect(const struct audio_stream *stream,
7932 effect_handle_t effect)
7933{
Eric Laurent994a6932013-07-17 11:51:42 -07007934 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007935 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007936}
7937
Haynes Mathew George16081042017-05-31 17:16:49 -07007938static int in_stop(const struct audio_stream_in* stream)
7939{
7940 struct stream_in *in = (struct stream_in *)stream;
7941 struct audio_device *adev = in->dev;
7942
7943 int ret = -ENOSYS;
7944 ALOGV("%s", __func__);
7945 pthread_mutex_lock(&adev->lock);
7946 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7947 in->capture_started && in->pcm != NULL) {
7948 pcm_stop(in->pcm);
7949 ret = stop_input_stream(in);
7950 in->capture_started = false;
7951 }
7952 pthread_mutex_unlock(&adev->lock);
7953 return ret;
7954}
7955
7956static int in_start(const struct audio_stream_in* stream)
7957{
7958 struct stream_in *in = (struct stream_in *)stream;
7959 struct audio_device *adev = in->dev;
7960 int ret = -ENOSYS;
7961
7962 ALOGV("%s in %p", __func__, in);
7963 pthread_mutex_lock(&adev->lock);
7964 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7965 !in->capture_started && in->pcm != NULL) {
7966 if (!in->capture_started) {
7967 ret = start_input_stream(in);
7968 if (ret == 0) {
7969 in->capture_started = true;
7970 }
7971 }
7972 }
7973 pthread_mutex_unlock(&adev->lock);
7974 return ret;
7975}
7976
Phil Burke0a86d12019-02-16 22:28:11 -08007977// Read offset for the positional timestamp from a persistent vendor property.
7978// This is to workaround apparent inaccuracies in the timing information that
7979// is used by the AAudio timing model. The inaccuracies can cause glitches.
7980static int64_t in_get_mmap_time_offset() {
7981 const int32_t kDefaultOffsetMicros = 0;
7982 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08007983 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08007984 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
7985 return mmap_time_offset_micros * (int64_t)1000;
7986}
7987
Haynes Mathew George16081042017-05-31 17:16:49 -07007988static int in_create_mmap_buffer(const struct audio_stream_in *stream,
7989 int32_t min_size_frames,
7990 struct audio_mmap_buffer_info *info)
7991{
7992 struct stream_in *in = (struct stream_in *)stream;
7993 struct audio_device *adev = in->dev;
7994 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07007995 unsigned int offset1 = 0;
7996 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007997 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07007998 uint32_t mmap_size = 0;
7999 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07008000
8001 pthread_mutex_lock(&adev->lock);
8002 ALOGV("%s in %p", __func__, in);
8003
Sharad Sanglec6f32552018-05-04 16:15:38 +05308004 if (CARD_STATUS_OFFLINE == in->card_status||
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05008005 CARD_STATUS_OFFLINE == adev->card_status ||
8006 POWER_POLICY_STATUS_OFFLINE == adev->in_power_policy) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05308007 ALOGW("in->card_status or adev->card_status offline, try again");
8008 ret = -EIO;
8009 goto exit;
8010 }
8011
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05308012 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07008013 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
8014 ret = -EINVAL;
8015 goto exit;
8016 }
8017 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
8018 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
8019 ALOGV("%s in %p", __func__, in);
8020 ret = -ENOSYS;
8021 goto exit;
8022 }
8023 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
8024 if (in->pcm_device_id < 0) {
8025 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
8026 __func__, in->pcm_device_id, in->usecase);
8027 ret = -EINVAL;
8028 goto exit;
8029 }
8030
8031 adjust_mmap_period_count(&in->config, min_size_frames);
8032
8033 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
8034 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
8035 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
8036 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05308037 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05308038 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
8039 in->card_status = CARD_STATUS_OFFLINE;
8040 adev->card_status = CARD_STATUS_OFFLINE;
8041 ret = -EIO;
8042 goto exit;
8043 }
8044
Haynes Mathew George16081042017-05-31 17:16:49 -07008045 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
8046 step = "open";
8047 ret = -ENODEV;
8048 goto exit;
8049 }
8050
8051 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
8052 if (ret < 0) {
8053 step = "begin";
8054 goto exit;
8055 }
Haynes Mathew George16081042017-05-31 17:16:49 -07008056
juyuchen626833d2019-06-04 16:48:02 +08008057 info->flags = 0;
Arun Mirpuri5d170872019-03-26 13:21:31 -07008058 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
8059 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
8060 info->burst_size_frames = in->config.period_size;
8061 ret = platform_get_mmap_data_fd(adev->platform,
8062 in->pcm_device_id, 1 /*capture*/,
8063 &info->shared_memory_fd,
8064 &mmap_size);
8065 if (ret < 0) {
8066 // Fall back to non exclusive mode
8067 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
8068 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07008069 in->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
8070 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, in->mmap_shared_memory_fd);
8071
Arun Mirpuri5d170872019-03-26 13:21:31 -07008072 if (mmap_size < buffer_size) {
8073 step = "mmap";
8074 goto exit;
8075 }
juyuchen626833d2019-06-04 16:48:02 +08008076 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Arun Mirpuri5d170872019-03-26 13:21:31 -07008077 }
8078
8079 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07008080
8081 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
8082 if (ret < 0) {
8083 step = "commit";
8084 goto exit;
8085 }
8086
Phil Burke0a86d12019-02-16 22:28:11 -08008087 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
8088
Haynes Mathew George16081042017-05-31 17:16:49 -07008089 in->standby = false;
8090 ret = 0;
8091
8092 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
8093 __func__, info->shared_memory_address, info->buffer_size_frames);
8094
8095exit:
8096 if (ret != 0) {
8097 if (in->pcm == NULL) {
8098 ALOGE("%s: %s - %d", __func__, step, ret);
8099 } else {
8100 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
8101 pcm_close(in->pcm);
8102 in->pcm = NULL;
8103 }
8104 }
8105 pthread_mutex_unlock(&adev->lock);
8106 return ret;
8107}
8108
8109static int in_get_mmap_position(const struct audio_stream_in *stream,
8110 struct audio_mmap_position *position)
8111{
8112 struct stream_in *in = (struct stream_in *)stream;
8113 ALOGVV("%s", __func__);
8114 if (position == NULL) {
8115 return -EINVAL;
8116 }
Gautam Manam34d1f542021-01-05 20:24:37 +05308117 lock_input_stream(in);
Haynes Mathew George16081042017-05-31 17:16:49 -07008118 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
Gautam Manam34d1f542021-01-05 20:24:37 +05308119 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07008120 return -ENOSYS;
8121 }
8122 if (in->pcm == NULL) {
Gautam Manam34d1f542021-01-05 20:24:37 +05308123 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07008124 return -ENOSYS;
8125 }
8126 struct timespec ts = { 0, 0 };
8127 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
8128 if (ret < 0) {
8129 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
Gautam Manam34d1f542021-01-05 20:24:37 +05308130 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07008131 return ret;
8132 }
Phil Burke0a86d12019-02-16 22:28:11 -08008133 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
8134 + in->mmap_time_offset_nanos;
Gautam Manam34d1f542021-01-05 20:24:37 +05308135 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07008136 return 0;
8137}
8138
Naresh Tannirudcb47c52018-06-25 16:23:32 +05308139static int in_get_active_microphones(const struct audio_stream_in *stream,
8140 struct audio_microphone_characteristic_t *mic_array,
8141 size_t *mic_count) {
8142 struct stream_in *in = (struct stream_in *)stream;
8143 struct audio_device *adev = in->dev;
8144 ALOGVV("%s", __func__);
8145
8146 lock_input_stream(in);
8147 pthread_mutex_lock(&adev->lock);
8148 int ret = platform_get_active_microphones(adev->platform,
8149 audio_channel_count_from_in_mask(in->channel_mask),
8150 in->usecase, mic_array, mic_count);
8151 pthread_mutex_unlock(&adev->lock);
8152 pthread_mutex_unlock(&in->lock);
8153
8154 return ret;
8155}
8156
8157static int adev_get_microphones(const struct audio_hw_device *dev,
8158 struct audio_microphone_characteristic_t *mic_array,
8159 size_t *mic_count) {
8160 struct audio_device *adev = (struct audio_device *)dev;
8161 ALOGVV("%s", __func__);
8162
8163 pthread_mutex_lock(&adev->lock);
8164 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
8165 pthread_mutex_unlock(&adev->lock);
8166
8167 return ret;
8168}
juyuchendb308c22019-01-21 11:57:17 -07008169
8170static void in_update_sink_metadata(struct audio_stream_in *stream,
8171 const struct sink_metadata *sink_metadata) {
8172
8173 if (stream == NULL
8174 || sink_metadata == NULL
8175 || sink_metadata->tracks == NULL) {
8176 return;
8177 }
8178
8179 int error = 0;
8180 struct stream_in *in = (struct stream_in *)stream;
8181 struct audio_device *adev = in->dev;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008182 struct listnode devices;
8183
8184 list_init(&devices);
juyuchendb308c22019-01-21 11:57:17 -07008185
8186 if (sink_metadata->track_count != 0)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008187 reassign_device_list(&devices, sink_metadata->tracks->dest_device, "");
juyuchendb308c22019-01-21 11:57:17 -07008188
8189 lock_input_stream(in);
8190 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008191 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, get_device_types(&devices));
juyuchendb308c22019-01-21 11:57:17 -07008192
Zhou Song503196b2021-07-23 17:31:05 +08008193 if ((in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY ||
8194 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2) &&
8195 !list_empty(&devices) &&
8196 adev->voice_tx_output != NULL) {
juyuchendb308c22019-01-21 11:57:17 -07008197 /* Use the rx device from afe-proxy record to route voice call because
8198 there is no routing if tx device is on primary hal and rx device
8199 is on other hal during voice call. */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008200 assign_devices(&adev->voice_tx_output->device_list, &devices);
juyuchendb308c22019-01-21 11:57:17 -07008201
8202 if (!voice_is_call_state_active(adev)) {
8203 if (adev->mode == AUDIO_MODE_IN_CALL) {
8204 adev->current_call_output = adev->voice_tx_output;
8205 error = voice_start_call(adev);
8206 if (error != 0)
8207 ALOGE("%s: start voice call failed %d", __func__, error);
8208 }
8209 } else {
8210 adev->current_call_output = adev->voice_tx_output;
8211 voice_update_devices_for_all_voice_usecases(adev);
8212 }
8213 }
8214
Zhenlin Lian4f947842022-05-14 15:50:52 +05308215 clear_devices(&devices);
juyuchendb308c22019-01-21 11:57:17 -07008216 pthread_mutex_unlock(&adev->lock);
8217 pthread_mutex_unlock(&in->lock);
8218}
8219
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308220int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07008221 audio_io_handle_t handle,
8222 audio_devices_t devices,
8223 audio_output_flags_t flags,
8224 struct audio_config *config,
8225 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04008226 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008227{
8228 struct audio_device *adev = (struct audio_device *)dev;
8229 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05308230 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008231 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008232 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05308233 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008234 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
8235 bool is_usb_dev = audio_is_usb_out_device(devices) &&
8236 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
8237 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008238 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07008239 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
8240 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008241 bool force_haptic_path =
8242 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07008243 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008244#ifdef AUDIO_GKI_ENABLED
8245 __s32 *generic_dec;
8246#endif
Weiyin Jiang906db3c2021-03-02 13:17:04 +08008247 pthread_mutexattr_t latch_attr;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008248
kunleizdff872d2018-08-20 14:40:33 +08008249 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08008250 is_usb_dev = false;
8251 devices = AUDIO_DEVICE_OUT_SPEAKER;
8252 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
8253 __func__, devices);
Mingshu Pangdbd20562019-11-25 18:04:39 +08008254 if (config->format == AUDIO_FORMAT_DEFAULT)
8255 config->format = AUDIO_FORMAT_PCM_16_BIT;
8256 if (config->sample_rate == 0)
8257 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8258 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8259 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
kunleizd6a9e0c2018-07-30 15:38:52 +08008260 }
8261
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008262 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05308263
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008264 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
8265
Mingming Yin3a941d42016-02-17 18:08:05 -08008266 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04008267 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
8268 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308269
8270
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008271 if (!out) {
8272 return -ENOMEM;
8273 }
8274
Haynes Mathew George204045b2015-02-25 20:32:03 -08008275 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07008276 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Weiyin Jiang906db3c2021-03-02 13:17:04 +08008277 pthread_mutexattr_init(&latch_attr);
8278 pthread_mutexattr_settype(&latch_attr, PTHREAD_MUTEX_RECURSIVE);
8279 pthread_mutex_init(&out->latch_lock, &latch_attr);
8280 pthread_mutexattr_destroy(&latch_attr);
Zhou Song48453a02018-01-10 17:50:59 +08008281 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08008282 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
8283
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008284 if (devices == AUDIO_DEVICE_NONE)
8285 devices = AUDIO_DEVICE_OUT_SPEAKER;
8286
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008287 out->flags = flags;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008288 list_init(&out->device_list);
8289 update_device_list(&out->device_list, devices, address, true /* add devices */);
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07008290 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07008291 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008292 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05308293 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05308294 if (out->channel_mask == AUDIO_CHANNEL_NONE)
8295 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
8296 else
8297 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07008298 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07008299 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08008300 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308301 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308302 out->started = 0;
Zhou Songbaddf9f2020-11-20 13:57:39 +08008303 out->a2dp_muted = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008304 out->hal_output_suspend_supported = 0;
8305 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05308306 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05308307 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05308308 out->pspd_coeff_sent = false;
Phil Burkd898ba62019-06-20 12:49:01 -07008309 out->mmap_shared_memory_fd = -1; // not open
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008310
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05308311 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05308312 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07008313 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
8314
Aalique Grahame22e49102018-12-18 14:23:57 -08008315 if (direct_dev &&
8316 (audio_is_linear_pcm(out->format) ||
8317 config->format == AUDIO_FORMAT_DEFAULT) &&
8318 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
8319 audio_format_t req_format = config->format;
8320 audio_channel_mask_t req_channel_mask = config->channel_mask;
8321 uint32_t req_sample_rate = config->sample_rate;
8322
8323 pthread_mutex_lock(&adev->lock);
8324 if (is_hdmi) {
8325 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
8326 ret = read_hdmi_sink_caps(out);
8327 if (config->sample_rate == 0)
8328 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8329 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8330 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
8331 if (config->format == AUDIO_FORMAT_DEFAULT)
8332 config->format = AUDIO_FORMAT_PCM_16_BIT;
8333 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008334 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
8335 &config->format,
8336 &out->supported_formats[0],
8337 MAX_SUPPORTED_FORMATS,
8338 &config->channel_mask,
8339 &out->supported_channel_masks[0],
8340 MAX_SUPPORTED_CHANNEL_MASKS,
8341 &config->sample_rate,
8342 &out->supported_sample_rates[0],
8343 MAX_SUPPORTED_SAMPLE_RATES);
8344 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008345 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008346
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008347 pthread_mutex_unlock(&adev->lock);
8348 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08008349 if (ret == -ENOSYS) {
8350 /* ignore and go with default */
8351 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08008352 }
8353 // For MMAP NO IRQ, allow conversions in ADSP
8354 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
8355 goto error_open;
8356 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008357 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08008358 goto error_open;
8359 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008360
8361 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
8362 config->sample_rate = req_sample_rate;
8363 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
8364 config->channel_mask = req_channel_mask;
8365 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
8366 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08008367 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008368
8369 out->sample_rate = config->sample_rate;
8370 out->channel_mask = config->channel_mask;
8371 out->format = config->format;
8372 if (is_hdmi) {
8373 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
8374 out->config = pcm_config_hdmi_multi;
8375 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8376 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8377 out->config = pcm_config_mmap_playback;
8378 out->stream.start = out_start;
8379 out->stream.stop = out_stop;
8380 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8381 out->stream.get_mmap_position = out_get_mmap_position;
8382 } else {
8383 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
8384 out->config = pcm_config_hifi;
8385 }
8386
8387 out->config.rate = out->sample_rate;
8388 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
8389 if (is_hdmi) {
8390 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
8391 audio_bytes_per_sample(out->format));
8392 }
8393 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08008394 }
8395
Derek Chenf6318be2017-06-12 17:16:24 -04008396 /* validate bus device address */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008397 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008398 /* extract car audio stream index */
8399 out->car_audio_stream =
8400 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
8401 if (out->car_audio_stream < 0) {
8402 ALOGE("%s: invalid car audio stream %x",
8403 __func__, out->car_audio_stream);
8404 ret = -EINVAL;
8405 goto error_open;
8406 }
Derek Chen5f67a942020-02-24 23:08:13 -08008407 ALOGV("%s: car_audio_stream %x", __func__, out->car_audio_stream);
Derek Chenf6318be2017-06-12 17:16:24 -04008408 }
8409
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008410 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07008411 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008412 if (!voice_extn_is_compress_voip_supported()) {
8413 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
8414 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07008415 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
Lakshman Chaluvarajue7fc9482020-05-30 14:29:29 +05308416 config->channel_mask : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008417 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
8418 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07008419 out->volume_l = INVALID_OUT_VOLUME;
8420 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07008421
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008422 out->config = default_pcm_config_voip_copp;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008423 out->config.rate = out->sample_rate;
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07008424 uint32_t channel_count =
8425 audio_channel_count_from_out_mask(out->channel_mask);
Ramjee Singh968858a2020-08-06 16:30:48 +05308426 out->config.channels = channel_count;
8427
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07008428 uint32_t buffer_size = get_stream_buffer_size(DEFAULT_VOIP_BUF_DURATION_MS,
8429 out->sample_rate, out->format,
8430 channel_count, false);
8431 uint32_t frame_size = audio_bytes_per_sample(out->format) * channel_count;
8432 if (frame_size != 0)
8433 out->config.period_size = buffer_size / frame_size;
8434 else
8435 ALOGW("%s: frame size is 0 for format %#x", __func__, out->format);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008436 }
8437 } else {
8438 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
8439 voice_extn_compress_voip_is_active(out->dev)) &&
8440 (voice_extn_compress_voip_is_config_supported(config))) {
8441 ret = voice_extn_compress_voip_open_output_stream(out);
8442 if (ret != 0) {
8443 ALOGE("%s: Compress voip output cannot be opened, error:%d",
8444 __func__, ret);
8445 goto error_open;
8446 }
Sujin Panicker19027262019-09-16 18:28:06 +05308447 } else {
8448 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8449 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008450 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008451 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008452 } else if (audio_is_linear_pcm(out->format) &&
8453 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
8454 out->channel_mask = config->channel_mask;
8455 out->sample_rate = config->sample_rate;
8456 out->format = config->format;
8457 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
8458 // does this change?
8459 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
8460 out->config.rate = config->sample_rate;
8461 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
8462 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
8463 audio_bytes_per_sample(config->format));
8464 out->config.format = pcm_format_from_audio_format(out->format);
Kogara Naveen Kumar86ef8192022-12-08 17:04:51 +05308465 }else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308466 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308467 pthread_mutex_lock(&adev->lock);
8468 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
8469 pthread_mutex_unlock(&adev->lock);
8470
8471 // reject offload during card offline to allow
8472 // fallback to s/w paths
8473 if (offline) {
8474 ret = -ENODEV;
8475 goto error_open;
8476 }
vivek mehta0ea887a2015-08-26 14:01:20 -07008477
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008478 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
8479 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
8480 ALOGE("%s: Unsupported Offload information", __func__);
8481 ret = -EINVAL;
8482 goto error_open;
8483 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008484
Atul Khare3fa6e542017-08-09 00:56:17 +05308485 if (config->offload_info.format == 0)
8486 config->offload_info.format = config->format;
8487 if (config->offload_info.sample_rate == 0)
8488 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008489
Mingming Yin90310102013-11-13 16:57:00 -08008490 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308491 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07008492 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008493 ret = -EINVAL;
8494 goto error_open;
8495 }
8496
Ben Romberger0f8c87b2017-05-24 17:41:11 -07008497 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
8498 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
8499 (audio_extn_passthru_is_passthrough_stream(out)) &&
8500 !((config->sample_rate == 48000) ||
8501 (config->sample_rate == 96000) ||
8502 (config->sample_rate == 192000))) {
8503 ALOGE("%s: Unsupported sample rate %d for audio format %x",
8504 __func__, config->sample_rate, config->offload_info.format);
8505 ret = -EINVAL;
8506 goto error_open;
8507 }
8508
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008509 out->compr_config.codec = (struct snd_codec *)
8510 calloc(1, sizeof(struct snd_codec));
8511
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008512 if (!out->compr_config.codec) {
8513 ret = -ENOMEM;
8514 goto error_open;
8515 }
8516
Dhananjay Kumarac341582017-02-23 23:42:25 +05308517 out->stream.pause = out_pause;
8518 out->stream.resume = out_resume;
8519 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05308520 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05308521 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07008522 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05308523 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07008524 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05308525 } else {
8526 out->usecase = get_offload_usecase(adev, false /* is_compress */);
8527 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07008528 }
vivek mehta446c3962015-09-14 10:57:35 -07008529
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308530 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8531 ALOGD("%s: Setting latency mode to true", __func__);
Meng Wang4c32fb42020-01-16 17:57:11 +08008532#ifdef AUDIO_GKI_ENABLED
8533 /* out->compr_config.codec->reserved[1] is for flags */
8534 out->compr_config.codec->reserved[1] |= audio_extn_utils_get_perf_mode_flag();
8535#else
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308536 out->compr_config.codec->flags |= audio_extn_utils_get_perf_mode_flag();
Meng Wang4c32fb42020-01-16 17:57:11 +08008537#endif
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308538 }
8539
vivek mehta446c3962015-09-14 10:57:35 -07008540 if (out->usecase == USECASE_INVALID) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008541 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Mingming Yin3a941d42016-02-17 18:08:05 -08008542 config->format == 0 && config->sample_rate == 0 &&
8543 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07008544 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08008545 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
8546 } else {
8547 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
8548 ret = -EEXIST;
8549 goto error_open;
8550 }
vivek mehta446c3962015-09-14 10:57:35 -07008551 }
8552
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008553 if (config->offload_info.channel_mask)
8554 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008555 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008556 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008557 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008558 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05308559 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008560 ret = -EINVAL;
8561 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008562 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008563
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008564 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008565 out->sample_rate = config->offload_info.sample_rate;
8566
Mingming Yin3ee55c62014-08-04 14:23:35 -07008567 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008568
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308569 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05308570 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308571 audio_extn_dolby_send_ddp_endp_params(adev);
8572 audio_extn_dolby_set_dmid(adev);
8573 }
vivek mehta0ea887a2015-08-26 14:01:20 -07008574
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008575 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08008576 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008577 out->compr_config.codec->bit_rate =
8578 config->offload_info.bit_rate;
8579 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05308580 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008581 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05308582 /* Update bit width only for non passthrough usecases.
8583 * For passthrough usecases, the output will always be opened @16 bit
8584 */
8585 if (!audio_extn_passthru_is_passthrough_stream(out))
8586 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308587
8588 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
Meng Wang4c32fb42020-01-16 17:57:11 +08008589#ifdef AUDIO_GKI_ENABLED
8590 /* out->compr_config.codec->reserved[1] is for flags */
8591 out->compr_config.codec->reserved[1] |= COMPRESSED_TIMESTAMP_FLAG;
8592 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->reserved[1]);
8593#else
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308594 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
8595 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
Meng Wang4c32fb42020-01-16 17:57:11 +08008596#endif
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308597
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008598 /*TODO: Do we need to change it for passthrough */
8599 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008600
Manish Dewangana6fc5442015-08-24 20:30:31 +05308601 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
8602 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308603 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05308604 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308605 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
8606 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308607
8608 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
8609 AUDIO_FORMAT_PCM) {
8610
8611 /*Based on platform support, configure appropriate alsa format for corresponding
8612 *hal input format.
8613 */
8614 out->compr_config.codec->format = hal_format_to_alsa(
8615 config->offload_info.format);
8616
Ashish Jain83a6cc22016-06-28 14:34:17 +05308617 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05308618 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308619 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308620
Dhananjay Kumarac341582017-02-23 23:42:25 +05308621 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05308622 *hal input format and alsa format might differ based on platform support.
8623 */
8624 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05308625 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308626
8627 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
8628
Deeraj Soman93155a62019-09-30 19:00:37 +05308629 if (property_get_bool("vendor.audio.offload.buffer.duration.enabled", false)) {
8630 if ((config->offload_info.duration_us >= MIN_OFFLOAD_BUFFER_DURATION_MS * 1000) &&
8631 (config->offload_info.duration_us <= MAX_OFFLOAD_BUFFER_DURATION_MS * 1000))
8632 out->info.duration_us = (int64_t)config->offload_info.duration_us;
8633 }
Deeraj Soman65358ab2019-02-07 15:40:49 +05308634
Ashish Jainf1eaa582016-05-23 20:54:24 +05308635 /* Check if alsa session is configured with the same format as HAL input format,
8636 * if not then derive correct fragment size needed to accomodate the
8637 * conversion of HAL input format to alsa format.
8638 */
8639 audio_extn_utils_update_direct_pcm_fragment_size(out);
8640
8641 /*if hal input and output fragment size is different this indicates HAL input format is
8642 *not same as the alsa format
8643 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308644 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05308645 /*Allocate a buffer to convert input data to the alsa configured format.
8646 *size of convert buffer is equal to the size required to hold one fragment size
8647 *worth of pcm data, this is because flinger does not write more than fragment_size
8648 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308649 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
8650 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05308651 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
8652 ret = -ENOMEM;
8653 goto error_open;
8654 }
8655 }
8656 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
8657 out->compr_config.fragment_size =
8658 audio_extn_passthru_get_buffer_size(&config->offload_info);
8659 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8660 } else {
8661 out->compr_config.fragment_size =
8662 platform_get_compress_offload_buffer_size(&config->offload_info);
8663 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8664 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008665
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308666 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8667 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
8668 }
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008669 if (config->offload_info.format == AUDIO_FORMAT_FLAC) {
8670#ifdef AUDIO_GKI_ENABLED
8671 generic_dec =
8672 &(out->compr_config.codec->options.generic.reserved[1]);
8673 ((struct snd_generic_dec_flac *)generic_dec)->sample_size =
8674 AUDIO_OUTPUT_BIT_WIDTH;
8675#else
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05308676 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008677#endif
8678 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008679
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05308680 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
8681 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
8682 }
8683
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008684 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
8685 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008686
Manish Dewangan69426c82017-01-30 17:35:36 +05308687 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
8688 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
8689 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
8690 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8691 out->render_mode = RENDER_MODE_AUDIO_MASTER;
8692 } else {
8693 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
8694 }
Alexy Josephaa54c872014-12-03 02:46:47 -08008695
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05308696 memset(&out->channel_map_param, 0,
8697 sizeof(struct audio_out_channel_map_param));
8698
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008699 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05308700 out->send_next_track_params = false;
8701 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008702 out->offload_state = OFFLOAD_STATE_IDLE;
8703 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08008704 out->writeAt.tv_sec = 0;
8705 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008706
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008707 audio_extn_dts_create_state_notifier_node(out->usecase);
8708
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008709 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
8710 __func__, config->offload_info.version,
8711 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05308712
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308713 /* Check if DSD audio format is supported in codec
8714 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308715 */
8716
8717 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308718 (!platform_check_codec_dsd_support(adev->platform) ||
8719 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308720 ret = -EINVAL;
8721 goto error_open;
8722 }
8723
Ashish Jain5106d362016-05-11 19:23:33 +05308724 /* Disable gapless if any of the following is true
8725 * passthrough playback
8726 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05308727 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05308728 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308729 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308730 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07008731 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308732 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308733 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05308734 check_and_set_gapless_mode(adev, false);
8735 } else
8736 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07008737
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308738 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07008739 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
8740 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308741 if (config->format == AUDIO_FORMAT_DSD) {
8742 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
Meng Wang4c32fb42020-01-16 17:57:11 +08008743#ifdef AUDIO_GKI_ENABLED
8744 /* out->compr_config.codec->reserved[0] is for compr_passthr */
8745 out->compr_config.codec->reserved[0] = PASSTHROUGH_DSD;
8746#else
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308747 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
Meng Wang4c32fb42020-01-16 17:57:11 +08008748#endif
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308749 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07008750
8751 create_offload_callback_thread(out);
8752
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008753 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008754 switch (config->sample_rate) {
8755 case 0:
8756 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8757 break;
8758 case 8000:
8759 case 16000:
8760 case 48000:
8761 out->sample_rate = config->sample_rate;
8762 break;
8763 default:
8764 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
8765 config->sample_rate);
8766 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8767 ret = -EINVAL;
8768 goto error_open;
8769 }
8770 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8771 switch (config->channel_mask) {
8772 case AUDIO_CHANNEL_NONE:
8773 case AUDIO_CHANNEL_OUT_STEREO:
8774 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8775 break;
8776 default:
8777 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
8778 config->channel_mask);
8779 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8780 ret = -EINVAL;
8781 goto error_open;
8782 }
8783 switch (config->format) {
8784 case AUDIO_FORMAT_DEFAULT:
8785 case AUDIO_FORMAT_PCM_16_BIT:
8786 out->format = AUDIO_FORMAT_PCM_16_BIT;
8787 break;
8788 default:
8789 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
8790 config->format);
8791 config->format = AUDIO_FORMAT_PCM_16_BIT;
8792 ret = -EINVAL;
8793 goto error_open;
8794 }
8795
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05308796 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008797 if (ret != 0) {
8798 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008799 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008800 goto error_open;
8801 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008802 } else if (is_single_device_type_equal(&out->device_list,
8803 AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08008804 switch (config->sample_rate) {
8805 case 0:
8806 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
8807 break;
8808 case 8000:
8809 case 16000:
8810 case 48000:
8811 out->sample_rate = config->sample_rate;
8812 break;
8813 default:
8814 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
8815 config->sample_rate);
8816 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8817 ret = -EINVAL;
8818 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008819 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008820 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8821 switch (config->channel_mask) {
8822 case AUDIO_CHANNEL_NONE:
8823 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8824 break;
8825 case AUDIO_CHANNEL_OUT_STEREO:
8826 out->channel_mask = config->channel_mask;
8827 break;
8828 default:
8829 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
8830 config->channel_mask);
8831 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8832 ret = -EINVAL;
8833 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008834 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008835 switch (config->format) {
8836 case AUDIO_FORMAT_DEFAULT:
8837 out->format = AUDIO_FORMAT_PCM_16_BIT;
8838 break;
8839 case AUDIO_FORMAT_PCM_16_BIT:
8840 out->format = config->format;
8841 break;
8842 default:
8843 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
8844 config->format);
8845 config->format = AUDIO_FORMAT_PCM_16_BIT;
8846 ret = -EINVAL;
8847 break;
8848 }
8849 if (ret != 0)
8850 goto error_open;
8851
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008852 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
8853 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08008854 out->config.rate = out->sample_rate;
8855 out->config.channels =
8856 audio_channel_count_from_out_mask(out->channel_mask);
8857 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008858 adev->voice_tx_output = out;
sasevs4f069972023-06-03 14:23:25 +05308859 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
8860 ret = audio_extn_auto_hal_open_output_stream(out);
8861 if (ret) {
8862 ALOGE("%s: Failed to open output stream for bus device", __func__);
8863 ret = -EINVAL;
8864 goto error_open;
8865 }
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008866 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05308867 unsigned int channels = 0;
8868 /*Update config params to default if not set by the caller*/
8869 if (config->sample_rate == 0)
8870 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8871 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8872 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8873 if (config->format == AUDIO_FORMAT_DEFAULT)
8874 config->format = AUDIO_FORMAT_PCM_16_BIT;
8875
8876 channels = audio_channel_count_from_out_mask(out->channel_mask);
8877
Varun Balaraje49253e2017-07-06 19:48:56 +05308878 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
8879 out->usecase = get_interactive_usecase(adev);
8880 out->config = pcm_config_low_latency;
8881 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05308882 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008883 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
8884 out->flags);
8885 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07008886 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8887 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8888 out->config = pcm_config_mmap_playback;
8889 out->stream.start = out_start;
8890 out->stream.stop = out_stop;
8891 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8892 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308893 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8894 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008895 out->hal_output_suspend_supported =
8896 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
8897 out->dynamic_pm_qos_config_supported =
8898 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
8899 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08008900 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
8901 } else {
8902 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
8903 //the mixer path will be a string similar to "low-latency-playback resume"
8904 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
8905 strlcat(out->pm_qos_mixer_path,
8906 " resume", MAX_MIXER_PATH_LEN);
8907 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
8908 out->pm_qos_mixer_path);
8909 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308910 out->config = pcm_config_low_latency;
8911 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
8912 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
8913 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05308914 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
8915 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
8916 if (out->config.period_size <= 0) {
8917 ALOGE("Invalid configuration period size is not valid");
8918 ret = -EINVAL;
8919 goto error_open;
8920 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008921 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
8922 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
8923 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008924 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
8925 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
8926 out->config = pcm_config_haptics_audio;
8927 if (force_haptic_path)
8928 adev->haptics_config = pcm_config_haptics_audio;
8929 else
8930 adev->haptics_config = pcm_config_haptics;
8931
Meng Wangd08ce322020-04-02 08:59:20 +08008932 channels =
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008933 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
8934
8935 if (force_haptic_path) {
8936 out->config.channels = 1;
8937 adev->haptics_config.channels = 1;
8938 } else
8939 adev->haptics_config.channels = audio_channel_count_from_out_mask(out->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL);
Kogara Naveen Kumar86ef8192022-12-08 17:04:51 +05308940 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05308941 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008942 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8943 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308944 }
8945 out->hal_ip_format = format = out->format;
8946 out->config.format = hal_format_to_pcm(out->hal_ip_format);
8947 out->hal_op_format = pcm_format_to_hal(out->config.format);
8948 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
8949 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008950 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05308951 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308952 if (out->hal_ip_format != out->hal_op_format) {
8953 uint32_t buffer_size = out->config.period_size *
8954 format_to_bitwidth_table[out->hal_op_format] *
8955 out->config.channels;
8956 out->convert_buffer = calloc(1, buffer_size);
8957 if (out->convert_buffer == NULL){
8958 ALOGE("Allocation failed for convert buffer for size %d",
8959 out->compr_config.fragment_size);
8960 ret = -ENOMEM;
8961 goto error_open;
8962 }
8963 ALOGD("Convert buffer allocated of size %d", buffer_size);
8964 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008965 }
8966
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008967 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
8968 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308969
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008970 /* TODO remove this hardcoding and check why width is zero*/
8971 if (out->bit_width == 0)
8972 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308973 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008974 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008975 &out->device_list, out->flags,
8976 out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05308977 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05308978 &out->app_type_cfg);
Kogara Naveen Kumar86ef8192022-12-08 17:04:51 +05308979 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
8980 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08008981 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008982 if(adev->primary_output == NULL)
8983 adev->primary_output = out;
8984 else {
8985 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008986 ret = -EEXIST;
8987 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008988 }
8989 }
8990
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008991 /* Check if this usecase is already existing */
8992 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07008993 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
8994 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008995 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008996 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008997 ret = -EEXIST;
8998 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008999 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009000
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009001 pthread_mutex_unlock(&adev->lock);
9002
9003 out->stream.common.get_sample_rate = out_get_sample_rate;
9004 out->stream.common.set_sample_rate = out_set_sample_rate;
9005 out->stream.common.get_buffer_size = out_get_buffer_size;
9006 out->stream.common.get_channels = out_get_channels;
9007 out->stream.common.get_format = out_get_format;
9008 out->stream.common.set_format = out_set_format;
9009 out->stream.common.standby = out_standby;
9010 out->stream.common.dump = out_dump;
9011 out->stream.common.set_parameters = out_set_parameters;
9012 out->stream.common.get_parameters = out_get_parameters;
9013 out->stream.common.add_audio_effect = out_add_audio_effect;
9014 out->stream.common.remove_audio_effect = out_remove_audio_effect;
9015 out->stream.get_latency = out_get_latency;
9016 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08009017#ifdef NO_AUDIO_OUT
9018 out->stream.write = out_write_for_no_output;
9019#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009020 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08009021#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009022 out->stream.get_render_position = out_get_render_position;
9023 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07009024 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009025
Haynes Mathew George16081042017-05-31 17:16:49 -07009026 if (out->realtime)
9027 out->af_period_multiplier = af_period_multiplier;
9028 else
9029 out->af_period_multiplier = 1;
9030
Andy Hunga1f48fa2019-07-01 18:14:53 -07009031 out->kernel_buffer_size = out->config.period_size * out->config.period_count;
9032
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009033 out->standby = 1;
Zhou Songbaddf9f2020-11-20 13:57:39 +08009034 out->volume_l = PLAYBACK_GAIN_MAX;
9035 out->volume_r = PLAYBACK_GAIN_MAX;
Eric Laurenta9024de2013-04-04 09:19:12 -07009036 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07009037 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009038
9039 config->format = out->stream.common.get_format(&out->stream.common);
9040 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
9041 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05309042 register_format(out->format, out->supported_formats);
9043 register_channel_mask(out->channel_mask, out->supported_channel_masks);
9044 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009045
Dechen Chai22768452021-07-30 09:29:16 +05309046#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -08009047 out->error_log = error_log_create(
9048 ERROR_LOG_ENTRIES,
9049 1000000000 /* aggregate consecutive identical errors within one second in ns */);
Dechen Chai22768452021-07-30 09:29:16 +05309050#endif
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309051 /*
9052 By locking output stream before registering, we allow the callback
9053 to update stream's state only after stream's initial state is set to
9054 adev state.
9055 */
9056 lock_output_stream(out);
9057 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
9058 pthread_mutex_lock(&adev->lock);
9059 out->card_status = adev->card_status;
9060 pthread_mutex_unlock(&adev->lock);
9061 pthread_mutex_unlock(&out->lock);
9062
Aalique Grahame22e49102018-12-18 14:23:57 -08009063 stream_app_type_cfg_init(&out->app_type_cfg);
9064
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009065 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309066 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07009067 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08009068
9069 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
9070 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
9071 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08009072 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05309073 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08009074 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07009075 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05309076 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
9077 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08009078 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
9079 out->usecase, PCM_PLAYBACK);
9080 hdlr_stream_cfg.flags = out->flags;
9081 hdlr_stream_cfg.type = PCM_PLAYBACK;
9082 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
9083 &hdlr_stream_cfg);
9084 if (ret) {
9085 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
9086 out->adsp_hdlr_stream_handle = NULL;
9087 }
9088 }
Gangadhar Sb0210342019-02-22 17:39:41 +05309089 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
9090 is_direct_passthough, false);
9091 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
9092 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07009093 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07009094 if (ret < 0) {
9095 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
9096 out->ip_hdlr_handle = NULL;
9097 }
9098 }
Derek Chenf939fb72018-11-13 13:34:41 -08009099
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009100 ret = io_streams_map_insert(adev, &out->stream.common,
9101 out->handle, AUDIO_PATCH_HANDLE_NONE);
9102 if (ret != 0)
9103 goto error_open;
9104
Susan Wang6dd13092021-01-25 10:27:11 -05009105 out->out_ctxt.output = out;
Derek Chenf939fb72018-11-13 13:34:41 -08009106
9107 pthread_mutex_lock(&adev->lock);
Susan Wang6dd13092021-01-25 10:27:11 -05009108 list_add_tail(&adev->active_outputs_list, &out->out_ctxt.list);
Derek Chenf939fb72018-11-13 13:34:41 -08009109 pthread_mutex_unlock(&adev->lock);
9110
Eric Laurent994a6932013-07-17 11:51:42 -07009111 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009112 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07009113
9114error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05309115 if (out->convert_buffer)
9116 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07009117 free(out);
9118 *stream_out = NULL;
9119 ALOGD("%s: exit: ret %d", __func__, ret);
9120 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009121}
9122
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309123void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009124 struct audio_stream_out *stream)
9125{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07009126 struct stream_out *out = (struct stream_out *)stream;
9127 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009128 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07009129
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009130 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309131
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009132 io_streams_map_remove(adev, out->handle);
9133
Susan Wang6dd13092021-01-25 10:27:11 -05009134 // remove out_ctxt early to prevent the stream
9135 // being opened in a race condition
9136 pthread_mutex_lock(&adev->lock);
9137 list_remove(&out->out_ctxt.list);
9138 pthread_mutex_unlock(&adev->lock);
9139
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309140 // must deregister from sndmonitor first to prevent races
9141 // between the callback and close_stream
9142 audio_extn_snd_mon_unregister_listener(out);
9143
Ben Rombergerd771a7c2017-02-22 18:05:17 -08009144 /* close adsp hdrl session before standby */
9145 if (out->adsp_hdlr_stream_handle) {
9146 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
9147 if (ret)
9148 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
9149 out->adsp_hdlr_stream_handle = NULL;
9150 }
9151
Manish Dewangan21a850a2017-08-14 12:03:55 +05309152 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07009153 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
9154 out->ip_hdlr_handle = NULL;
9155 }
9156
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009157 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309158 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009159 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05309160 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309161 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009162 if(ret != 0)
9163 ALOGE("%s: Compress voip output cannot be closed, error:%d",
9164 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009165 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009166 out_standby(&stream->common);
9167
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07009168 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08009169 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07009170 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07009171 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07009172 if (out->compr_config.codec != NULL)
9173 free(out->compr_config.codec);
9174 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009175
Zhou Songbaddf9f2020-11-20 13:57:39 +08009176 out->a2dp_muted = false;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05309177
Varun Balaraje49253e2017-07-06 19:48:56 +05309178 if (is_interactive_usecase(out->usecase))
9179 free_interactive_usecase(adev, out->usecase);
9180
Ashish Jain83a6cc22016-06-28 14:34:17 +05309181 if (out->convert_buffer != NULL) {
9182 free(out->convert_buffer);
9183 out->convert_buffer = NULL;
9184 }
9185
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009186 if (adev->voice_tx_output == out)
9187 adev->voice_tx_output = NULL;
9188
Dechen Chai22768452021-07-30 09:29:16 +05309189#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -08009190 error_log_destroy(out->error_log);
9191 out->error_log = NULL;
Dechen Chai22768452021-07-30 09:29:16 +05309192#endif
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05309193 if (adev->primary_output == out)
9194 adev->primary_output = NULL;
9195
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07009196 pthread_cond_destroy(&out->cond);
9197 pthread_mutex_destroy(&out->lock);
Weiyin Jiang280ea742020-09-08 20:28:22 +08009198 pthread_mutex_destroy(&out->pre_lock);
9199 pthread_mutex_destroy(&out->latch_lock);
9200 pthread_mutex_destroy(&out->position_query_lock);
Derek Chenf939fb72018-11-13 13:34:41 -08009201
9202 pthread_mutex_lock(&adev->lock);
Zhenlin Lian4f947842022-05-14 15:50:52 +05309203 clear_devices(&out->device_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009204 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08009205 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07009206 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009207}
9208
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05009209void in_set_power_policy(uint8_t enable)
9210{
9211 struct listnode *node;
9212
9213 ALOGD("%s: Enter, state %d", __func__, enable);
9214
9215 pthread_mutex_lock(&adev->lock);
9216 adev->in_power_policy = enable ? POWER_POLICY_STATUS_ONLINE : POWER_POLICY_STATUS_OFFLINE;
9217 pthread_mutex_unlock(&adev->lock);
9218
9219 if (!enable) {
9220 list_for_each(node, &adev->active_inputs_list) {
9221 streams_input_ctxt_t *in_ctxt = node_to_item(node,
9222 streams_input_ctxt_t,
9223 list);
9224 struct stream_in *in = in_ctxt->input;
9225 in_standby(&in->stream.common);
9226 }
9227 }
9228
9229 ALOGD("%s: Exit", __func__);
9230}
9231
9232void out_set_power_policy(uint8_t enable)
9233{
9234 struct listnode *node;
9235
9236 ALOGD("%s: Enter, state %d", __func__, enable);
9237
9238 pthread_mutex_lock(&adev->lock);
E V Ravi317be872022-02-23 19:08:15 +05309239 adev->out_power_policy = enable ? POWER_POLICY_STATUS_ONLINE : POWER_POLICY_STATUS_OFFLINE;
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05009240 pthread_mutex_unlock(&adev->lock);
9241
9242 if (!enable) {
9243 list_for_each(node, &adev->active_outputs_list) {
9244 streams_output_ctxt_t *out_ctxt = node_to_item(node,
9245 streams_output_ctxt_t,
9246 list);
9247 struct stream_out *out = out_ctxt->output;
9248 out_on_error(&out->stream.common);
9249 }
9250 }
9251
9252 ALOGD("%s: Exit", __func__);
9253}
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009254static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
9255{
9256 struct audio_device *adev = (struct audio_device *)dev;
9257 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009258 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07009259 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009260 int ret;
9261 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08009262 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08009263 struct listnode *node;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07009264 int controller = -1, stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009265
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009266 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009267 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009268
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05309269 if (!parms)
9270 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05309271
Derek Chen6f293672019-04-01 01:40:24 -07009272 /* notify adev and input/output streams on the snd card status */
9273 adev_snd_mon_cb((void *)adev, parms);
9274
Weiyin Jiang24f55292020-12-22 14:35:46 +08009275 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
9276 if (ret >= 0) {
9277 list_for_each(node, &adev->active_outputs_list) {
9278 streams_output_ctxt_t *out_ctxt = node_to_item(node,
9279 streams_output_ctxt_t,
9280 list);
9281 out_snd_mon_cb((void *)out_ctxt->output, parms);
9282 }
Derek Chen6f293672019-04-01 01:40:24 -07009283
Weiyin Jiang24f55292020-12-22 14:35:46 +08009284 list_for_each(node, &adev->active_inputs_list) {
9285 streams_input_ctxt_t *in_ctxt = node_to_item(node,
9286 streams_input_ctxt_t,
9287 list);
9288 in_snd_mon_cb((void *)in_ctxt->input, parms);
9289 }
Derek Chen6f293672019-04-01 01:40:24 -07009290 }
9291
Zhou Songd6d71752019-05-21 18:08:51 +08009292 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05309293 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
9294 if (ret >= 0) {
9295 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08009296 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05309297 adev->bt_sco_on = true;
Shalini Manjunatha3a2e06e2021-02-01 12:23:49 +05309298 /*
9299 * When ever BT_SCO=ON arrives, make sure to route
9300 * all use cases to SCO device, otherwise due to delay in
9301 * BT_SCO=ON and lack of synchronization with create audio patch
9302 * request for SCO device, some times use case not routed properly to
9303 * SCO device
9304 */
9305 struct audio_usecase *usecase;
9306 struct listnode *node;
9307 list_for_each(node, &adev->usecase_list) {
9308 usecase = node_to_item(node, struct audio_usecase, list);
Anver sadhiquef0efca32021-09-03 15:25:44 +05309309 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
Anver sadhique93f3c912021-08-11 11:19:45 +05309310 (!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 +05309311 ALOGD("BT_SCO ON, switch all in use case to it");
9312 select_devices(adev, usecase->id);
9313 }
Mingshu Pangef517202021-04-22 10:35:00 +08009314 if (usecase->stream.out && (usecase->type == PCM_PLAYBACK ||
9315 usecase->type == VOICE_CALL) &&
Anver sadhique93f3c912021-08-11 11:19:45 +05309316 (!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 +05309317 ALOGD("BT_SCO ON, switch all out use case to it");
9318 select_devices(adev, usecase->id);
9319 }
9320 }
9321 }
9322 else {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05309323 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08009324 audio_extn_sco_reset_configuration();
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08009325 }
9326 }
9327
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009328 status = voice_set_parameters(adev, parms);
9329 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08009330 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009331
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009332 status = platform_set_parameters(adev->platform, parms);
9333 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08009334 goto done;
9335
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009336 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
9337 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07009338 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009339 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
9340 adev->bluetooth_nrec = true;
9341 else
9342 adev->bluetooth_nrec = false;
9343 }
9344
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009345 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
9346 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009347 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
9348 adev->screen_off = false;
9349 else
9350 adev->screen_off = true;
Quinn Male70f20f32019-06-26 16:50:26 -07009351 audio_extn_sound_trigger_update_screen_status(adev->screen_off);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009352 }
9353
Eric Laurent4b084132018-10-19 17:33:43 -07009354 ret = str_parms_get_int(parms, "rotation", &val);
9355 if (ret >= 0) {
9356 bool reverse_speakers = false;
9357 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
9358 switch (val) {
9359 // FIXME: note that the code below assumes that the speakers are in the correct placement
9360 // relative to the user when the device is rotated 90deg from its default rotation. This
9361 // assumption is device-specific, not platform-specific like this code.
9362 case 270:
9363 reverse_speakers = true;
9364 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
9365 break;
9366 case 0:
9367 case 180:
9368 camera_rotation = CAMERA_ROTATION_PORTRAIT;
9369 break;
9370 case 90:
9371 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
9372 break;
9373 default:
9374 ALOGE("%s: unexpected rotation of %d", __func__, val);
9375 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07009376 }
Eric Laurent4b084132018-10-19 17:33:43 -07009377 if (status == 0) {
9378 // check and set swap
9379 // - check if orientation changed and speaker active
9380 // - set rotation and cache the rotation value
9381 adev->camera_orientation =
9382 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
9383 if (!audio_extn_is_maxx_audio_enabled())
9384 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
9385 }
9386 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07009387
Mingming Yin514a8bc2014-07-29 15:22:21 -07009388 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
9389 if (ret >= 0) {
9390 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
9391 adev->bt_wb_speech_enabled = true;
9392 else
9393 adev->bt_wb_speech_enabled = false;
9394 }
9395
Zhou Song12c29502019-03-16 10:37:18 +08009396 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
9397 if (ret >= 0) {
9398 val = atoi(value);
9399 adev->swb_speech_mode = val;
9400 }
9401
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07009402 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
9403 if (ret >= 0) {
9404 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309405 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08009406 if (audio_is_output_device(val) &&
9407 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07009408 ALOGV("cache new ext disp type and edid");
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07009409 platform_get_controller_stream_from_params(parms, &controller, &stream);
9410 platform_set_ext_display_device_v2(adev->platform, controller, stream);
9411 ret = platform_get_ext_disp_type_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07009412 if (ret < 0) {
9413 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05309414 } else {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07009415 platform_cache_edid_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07009416 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309417 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07009418 /*
9419 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
9420 * Per AudioPolicyManager, USB device is higher priority than WFD.
9421 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
9422 * If WFD use case occupies AFE proxy, it may result unintended behavior while
9423 * starting voice call on USB
9424 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08009425 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309426 if (ret >= 0)
9427 audio_extn_usb_add_device(device, atoi(value));
9428
Zhou Song6f862822017-11-06 17:27:57 +08009429 if (!audio_extn_usb_is_tunnel_supported()) {
9430 ALOGV("detected USB connect .. disable proxy");
9431 adev->allow_afe_proxy_usage = false;
9432 }
Zhou Song503196b2021-07-23 17:31:05 +08009433 } else if (audio_is_hearing_aid_out_device(device) &&
9434 property_get_bool("persist.vendor.audio.ha_proxy.enabled", false)) {
9435 adev->ha_proxy_enable = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07009436 }
9437 }
9438
9439 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
9440 if (ret >= 0) {
9441 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309442 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07009443 /*
9444 * The HDMI / Displayport disconnect handling has been moved to
9445 * audio extension to ensure that its parameters are not
9446 * invalidated prior to updating sysfs of the disconnect event
9447 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
9448 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309449 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08009450 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309451 if (ret >= 0)
9452 audio_extn_usb_remove_device(device, atoi(value));
9453
Zhou Song6f862822017-11-06 17:27:57 +08009454 if (!audio_extn_usb_is_tunnel_supported()) {
9455 ALOGV("detected USB disconnect .. enable proxy");
9456 adev->allow_afe_proxy_usage = true;
9457 }
Zhou Song503196b2021-07-23 17:31:05 +08009458 } else if (audio_is_hearing_aid_out_device(device)) {
9459 adev->ha_proxy_enable = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07009460 }
9461 }
9462
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009463 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08009464
9465 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08009466 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309467 struct audio_usecase *usecase;
9468 struct listnode *node;
9469 list_for_each(node, &adev->usecase_list) {
9470 usecase = node_to_item(node, struct audio_usecase, list);
Weiyin Jiangff56ff32020-05-08 14:32:21 +08009471 if ((usecase->stream.out == NULL) || (usecase->type != PCM_PLAYBACK))
9472 continue;
9473
9474 if (is_a2dp_out_device_type(&usecase->device_list)) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309475 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05309476 audio_extn_a2dp_set_handoff_mode(true);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05309477 ALOGD("Switching to speaker and muting the stream before select_devices");
9478 check_a2dp_restore_l(adev, usecase->stream.out, false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309479 //force device switch to re configure encoder
9480 select_devices(adev, usecase->id);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05309481 ALOGD("Unmuting the stream after select_devices");
Zhou Songbaddf9f2020-11-20 13:57:39 +08009482 check_a2dp_restore_l(adev, usecase->stream.out, true);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05309483 audio_extn_a2dp_set_handoff_mode(false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309484 break;
Zhou Songd01e7a22020-09-23 22:49:01 +08009485 } else if (is_offload_usecase(usecase->stream.out->usecase)) {
Weiyin Jiang280ea742020-09-08 20:28:22 +08009486 pthread_mutex_lock(&usecase->stream.out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +08009487 if (usecase->stream.out->a2dp_muted) {
Weiyin Jiang280ea742020-09-08 20:28:22 +08009488 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
9489 reassign_device_list(&usecase->stream.out->device_list,
9490 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, "");
9491 check_a2dp_restore_l(adev, usecase->stream.out, true);
9492 break;
9493 }
9494 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309495 }
9496 }
9497 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009498
9499 //handle vr audio setparam
9500 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9501 value, sizeof(value));
9502 if (ret >= 0) {
9503 ALOGI("Setting vr mode to be %s", value);
9504 if (!strncmp(value, "true", 4)) {
9505 adev->vr_audio_mode_enabled = true;
9506 ALOGI("Setting vr mode to true");
9507 } else if (!strncmp(value, "false", 5)) {
9508 adev->vr_audio_mode_enabled = false;
9509 ALOGI("Setting vr mode to false");
9510 } else {
9511 ALOGI("wrong vr mode set");
9512 }
9513 }
9514
Eric Laurent4b084132018-10-19 17:33:43 -07009515 //FIXME: to be replaced by proper video capture properties API
9516 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
9517 if (ret >= 0) {
9518 int camera_facing = CAMERA_FACING_BACK;
9519 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
9520 camera_facing = CAMERA_FACING_FRONT;
9521 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
9522 camera_facing = CAMERA_FACING_BACK;
9523 else {
9524 ALOGW("%s: invalid camera facing value: %s", __func__, value);
9525 goto done;
9526 }
9527 adev->camera_orientation =
9528 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
9529 struct audio_usecase *usecase;
9530 struct listnode *node;
9531 list_for_each(node, &adev->usecase_list) {
9532 usecase = node_to_item(node, struct audio_usecase, list);
9533 struct stream_in *in = usecase->stream.in;
9534 if (usecase->type == PCM_CAPTURE && in != NULL &&
9535 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
9536 select_devices(adev, in->usecase);
9537 }
9538 }
9539 }
9540
Tahir Dawson7fabad42022-06-21 12:37:55 -04009541 audio_extn_auto_hal_set_parameters(adev, parms);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05309542 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08009543done:
9544 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009545 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05309546error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009547 ALOGV("%s: exit with code(%d)", __func__, status);
9548 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009549}
9550
9551static char* adev_get_parameters(const struct audio_hw_device *dev,
9552 const char *keys)
9553{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05309554 ALOGD("%s:%s", __func__, keys);
9555
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009556 struct audio_device *adev = (struct audio_device *)dev;
9557 struct str_parms *reply = str_parms_create();
9558 struct str_parms *query = str_parms_create_str(keys);
9559 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05309560 char value[256] = {0};
9561 int ret = 0;
9562
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009563 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08009564 if (reply) {
9565 str_parms_destroy(reply);
9566 }
9567 if (query) {
9568 str_parms_destroy(query);
9569 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009570 ALOGE("adev_get_parameters: failed to create query or reply");
9571 return NULL;
9572 }
9573
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009574 //handle vr audio getparam
9575
9576 ret = str_parms_get_str(query,
9577 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9578 value, sizeof(value));
9579
9580 if (ret >= 0) {
9581 bool vr_audio_enabled = false;
9582 pthread_mutex_lock(&adev->lock);
9583 vr_audio_enabled = adev->vr_audio_mode_enabled;
9584 pthread_mutex_unlock(&adev->lock);
9585
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07009586 ALOGV("getting vr mode to %d", vr_audio_enabled);
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009587
9588 if (vr_audio_enabled) {
9589 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9590 "true");
9591 goto exit;
9592 } else {
9593 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9594 "false");
9595 goto exit;
9596 }
9597 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009598
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009599 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009600 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08009601 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08009602 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009603 platform_get_parameters(adev->platform, query, reply);
justinwengd5395152019-11-04 12:23:09 +08009604 audio_extn_ma_get_parameters(adev, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05309605 pthread_mutex_unlock(&adev->lock);
9606
Naresh Tannirud7205b62014-06-20 02:54:48 +05309607exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009608 str = str_parms_to_str(reply);
9609 str_parms_destroy(query);
9610 str_parms_destroy(reply);
9611
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07009612 ALOGV("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009613 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009614}
9615
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009616static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009617{
9618 return 0;
9619}
9620
9621static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
9622{
Haynes Mathew George5191a852013-09-11 14:19:36 -07009623 int ret;
9624 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08009625
9626 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
9627
Haynes Mathew George5191a852013-09-11 14:19:36 -07009628 pthread_mutex_lock(&adev->lock);
9629 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07009630 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07009631 pthread_mutex_unlock(&adev->lock);
9632 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009633}
9634
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009635static int adev_set_master_volume(struct audio_hw_device *dev __unused,
9636 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009637{
9638 return -ENOSYS;
9639}
9640
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009641static int adev_get_master_volume(struct audio_hw_device *dev __unused,
9642 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009643{
9644 return -ENOSYS;
9645}
9646
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009647static int adev_set_master_mute(struct audio_hw_device *dev __unused,
9648 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009649{
9650 return -ENOSYS;
9651}
9652
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009653static int adev_get_master_mute(struct audio_hw_device *dev __unused,
9654 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009655{
9656 return -ENOSYS;
9657}
9658
9659static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
9660{
9661 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07009662 struct listnode *node;
9663 struct audio_usecase *usecase = NULL;
9664 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08009665
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009666 pthread_mutex_lock(&adev->lock);
9667 if (adev->mode != mode) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309668 ALOGD("%s: mode %d , prev_mode %d \n", __func__, mode , adev->mode);
9669 adev->prev_mode = adev->mode; /* prev_mode is kept to handle voip concurrency*/
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009670 adev->mode = mode;
Weiyin Jiang96b96f72020-09-22 16:48:19 +08009671 if (mode == AUDIO_MODE_CALL_SCREEN) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309672 adev->current_call_output = adev->primary_output;
9673 voice_start_call(adev);
9674 } else if (voice_is_in_call_or_call_screen(adev) &&
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08009675 (mode == AUDIO_MODE_NORMAL ||
9676 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07009677 list_for_each(node, &adev->usecase_list) {
9678 usecase = node_to_item(node, struct audio_usecase, list);
9679 if (usecase->type == VOICE_CALL)
9680 break;
9681 }
9682 if (usecase &&
9683 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
9684 ret = audio_extn_usb_check_and_set_svc_int(usecase,
9685 true);
9686 if (ret != 0) {
9687 /* default service interval was successfully updated,
9688 reopen USB backend with new service interval */
9689 check_usecases_codec_backend(adev,
9690 usecase,
9691 usecase->out_snd_device);
9692 }
9693 }
9694
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009695 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07009696 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009697 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08009698 // restore device for other active usecases after stop call
9699 list_for_each(node, &adev->usecase_list) {
9700 usecase = node_to_item(node, struct audio_usecase, list);
9701 select_devices(adev, usecase->id);
9702 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009703 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009704 }
9705 pthread_mutex_unlock(&adev->lock);
9706 return 0;
9707}
9708
9709static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
9710{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009711 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08009712 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009713
9714 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08009715 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009716 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009717
Derek Chend2530072014-11-24 12:39:14 -08009718 if (adev->ext_hw_plugin)
9719 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009720
9721 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009722 pthread_mutex_unlock(&adev->lock);
9723
9724 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009725}
9726
9727static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
9728{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009729 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009730 return 0;
9731}
9732
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009733static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009734 const struct audio_config *config)
9735{
Avinash Chandrad7296d42021-08-04 15:07:47 +05309736 bool is_usb_hifi = IS_USB_HIFI;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009737 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009738
Aalique Grahame22e49102018-12-18 14:23:57 -08009739 /* Don't know if USB HIFI in this context so use true to be conservative */
9740 if (check_input_parameters(config->sample_rate, config->format, channel_count,
Avinash Chandrad7296d42021-08-04 15:07:47 +05309741 is_usb_hifi) != 0)
Aalique Grahame22e49102018-12-18 14:23:57 -08009742 return 0;
9743
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009744 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
9745 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009746}
9747
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009748static bool adev_input_allow_hifi_record(struct audio_device *adev,
9749 audio_devices_t devices,
9750 audio_input_flags_t flags,
9751 audio_source_t source) {
9752 const bool allowed = true;
9753
9754 if (!audio_is_usb_in_device(devices))
9755 return !allowed;
9756
9757 switch (flags) {
9758 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009759 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07009760 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
9761 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009762 default:
9763 return !allowed;
9764 }
9765
9766 switch (source) {
9767 case AUDIO_SOURCE_DEFAULT:
9768 case AUDIO_SOURCE_MIC:
9769 case AUDIO_SOURCE_UNPROCESSED:
9770 break;
9771 default:
9772 return !allowed;
9773 }
9774
9775 switch (adev->mode) {
9776 case 0:
9777 break;
9778 default:
9779 return !allowed;
9780 }
9781
9782 return allowed;
9783}
9784
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009785static int adev_update_voice_comm_input_stream(struct stream_in *in,
9786 struct audio_config *config)
9787{
9788 bool valid_rate = (config->sample_rate == 8000 ||
9789 config->sample_rate == 16000 ||
9790 config->sample_rate == 32000 ||
9791 config->sample_rate == 48000);
9792 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
9793
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009794 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08009795 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009796 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9797 in->config = default_pcm_config_voip_copp;
9798 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
9799 DEFAULT_VOIP_BUF_DURATION_MS,
9800 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009801 } else {
9802 ALOGW("%s No valid input in voip, use defaults"
9803 "sample rate %u, channel mask 0x%X",
9804 __func__, config->sample_rate, in->channel_mask);
9805 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009806 in->config.rate = config->sample_rate;
9807 in->sample_rate = config->sample_rate;
9808 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009809 //XXX needed for voice_extn_compress_voip_open_input_stream
9810 in->config.rate = config->sample_rate;
9811 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
Shalini Manjunathaa763cc42019-08-23 15:13:46 +05309812 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009813 voice_extn_compress_voip_is_active(in->dev)) &&
9814 (voice_extn_compress_voip_is_format_supported(in->format)) &&
9815 valid_rate && valid_ch) {
9816 voice_extn_compress_voip_open_input_stream(in);
9817 // update rate entries to match config from AF
9818 in->config.rate = config->sample_rate;
9819 in->sample_rate = config->sample_rate;
9820 } else {
9821 ALOGW("%s compress voip not active, use defaults", __func__);
9822 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009823 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009824 return 0;
9825}
9826
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009827static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07009828 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009829 audio_devices_t devices,
9830 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009831 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309832 audio_input_flags_t flags,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009833 const char *address,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009834 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009835{
9836 struct audio_device *adev = (struct audio_device *)dev;
9837 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009838 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009839 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009840 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05309841 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009842 bool is_usb_dev = audio_is_usb_in_device(devices);
9843 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
9844 devices,
9845 flags,
9846 source);
Andy Hung94320602018-10-29 18:31:12 -07009847 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
9848 " sample_rate %u, channel_mask %#x, format %#x",
9849 __func__, flags, is_usb_dev, may_use_hifi_record,
9850 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309851
kunleizdff872d2018-08-20 14:40:33 +08009852 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08009853 is_usb_dev = false;
9854 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
9855 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
9856 __func__, devices);
9857 }
9858
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009859 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009860
9861 if (!(is_usb_dev && may_use_hifi_record)) {
9862 if (config->sample_rate == 0)
9863 config->sample_rate = 48000;
9864 if (config->channel_mask == AUDIO_CHANNEL_NONE)
9865 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9866 if (config->format == AUDIO_FORMAT_DEFAULT)
9867 config->format = AUDIO_FORMAT_PCM_16_BIT;
9868
9869 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
9870
Aalique Grahame22e49102018-12-18 14:23:57 -08009871 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9872 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009873 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05309874 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009875
9876 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009877
9878 if (!in) {
9879 ALOGE("failed to allocate input stream");
9880 return -ENOMEM;
9881 }
9882
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309883 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05309884 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
9885 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009886 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07009887 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009888
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009889 in->stream.common.get_sample_rate = in_get_sample_rate;
9890 in->stream.common.set_sample_rate = in_set_sample_rate;
9891 in->stream.common.get_buffer_size = in_get_buffer_size;
9892 in->stream.common.get_channels = in_get_channels;
9893 in->stream.common.get_format = in_get_format;
9894 in->stream.common.set_format = in_set_format;
9895 in->stream.common.standby = in_standby;
9896 in->stream.common.dump = in_dump;
9897 in->stream.common.set_parameters = in_set_parameters;
9898 in->stream.common.get_parameters = in_get_parameters;
9899 in->stream.common.add_audio_effect = in_add_audio_effect;
9900 in->stream.common.remove_audio_effect = in_remove_audio_effect;
9901 in->stream.set_gain = in_set_gain;
9902 in->stream.read = in_read;
9903 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08009904 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309905 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07009906 in->stream.set_microphone_direction = in_set_microphone_direction;
9907 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07009908 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009909
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009910 list_init(&in->device_list);
9911 update_device_list(&in->device_list, devices, address, true);
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009912 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009913 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009914 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009915 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009916 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07009917 in->bit_width = 16;
9918 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07009919 in->direction = MIC_DIRECTION_UNSPECIFIED;
9920 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08009921 list_init(&in->aec_list);
9922 list_init(&in->ns_list);
Phil Burkd898ba62019-06-20 12:49:01 -07009923 in->mmap_shared_memory_fd = -1; // not open
Haynes Mathew George46740472017-10-27 18:40:12 -07009924
Andy Hung94320602018-10-29 18:31:12 -07009925 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08009926 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
9927 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
9928 /* Force channel config requested to mono if incall
9929 record is being requested for only uplink/downlink */
9930 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
9931 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9932 ret = -EINVAL;
9933 goto err_open;
9934 }
9935 }
9936
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009937 if (is_usb_dev && may_use_hifi_record) {
9938 /* HiFi record selects an appropriate format, channel, rate combo
9939 depending on sink capabilities*/
9940 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
9941 &config->format,
9942 &in->supported_formats[0],
9943 MAX_SUPPORTED_FORMATS,
9944 &config->channel_mask,
9945 &in->supported_channel_masks[0],
9946 MAX_SUPPORTED_CHANNEL_MASKS,
9947 &config->sample_rate,
9948 &in->supported_sample_rates[0],
9949 MAX_SUPPORTED_SAMPLE_RATES);
9950 if (ret != 0) {
9951 ret = -EINVAL;
9952 goto err_open;
9953 }
9954 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009955 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309956 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05309957 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
9958 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
9959 in->config.format = PCM_FORMAT_S32_LE;
9960 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309961 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
9962 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
9963 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
9964 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
9965 bool ret_error = false;
9966 in->bit_width = 24;
9967 /* 24 bit is restricted to UNPROCESSED source only,also format supported
9968 from HAL is 24_packed and 8_24
9969 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
9970 24_packed return error indicating supported format is 24_packed
9971 *> In case of any other source requesting 24 bit or float return error
9972 indicating format supported is 16 bit only.
9973
9974 on error flinger will retry with supported format passed
9975 */
9976 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
9977 (source != AUDIO_SOURCE_CAMCORDER)) {
9978 config->format = AUDIO_FORMAT_PCM_16_BIT;
9979 if (config->sample_rate > 48000)
9980 config->sample_rate = 48000;
9981 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07009982 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
9983 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309984 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
9985 ret_error = true;
9986 }
9987
9988 if (ret_error) {
9989 ret = -EINVAL;
9990 goto err_open;
9991 }
9992 }
9993
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009994 in->channel_mask = config->channel_mask;
9995 in->format = config->format;
9996
9997 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309998
Huicheng Liu1404ba12020-09-11 01:03:25 -04009999 /* validate bus device address */
10000 if (compare_device_type(&in->device_list, AUDIO_DEVICE_IN_BUS)) {
10001 /* extract car audio stream index */
10002 in->car_audio_stream =
10003 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
10004 if (in->car_audio_stream < 0) {
10005 ALOGE("%s: invalid car audio stream %x",
10006 __func__, in->car_audio_stream);
10007 ret = -EINVAL;
10008 goto err_open;
10009 }
10010 ALOGV("%s: car_audio_stream 0x%x", __func__, in->car_audio_stream);
Huicheng Liuea4fd422021-01-12 18:34:50 -050010011 ret = audio_extn_auto_hal_open_input_stream(in);
10012 if (ret) {
10013 ALOGE("%s: Failed to open input stream for bus device", __func__);
10014 ret = -EINVAL;
10015 goto err_open;
10016 }
Huicheng Liu1404ba12020-09-11 01:03:25 -040010017 }
10018
Susan Wange3959562021-03-11 11:50:26 -050010019 /* reassign use case for echo reference stream on automotive platforms */
10020 if (in->source == AUDIO_SOURCE_ECHO_REFERENCE) {
10021 ret = audio_extn_auto_hal_open_echo_reference_stream(in);
10022 }
10023
Kogara Naveen Kumar379ff692022-01-31 11:56:51 +053010024 if ((in->source == AUDIO_SOURCE_FM_TUNER) || (devices == AUDIO_DEVICE_IN_FM_TUNER)) {
Samyak Jain0aa07ab2019-04-04 14:36:32 +053010025 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
10026 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
10027 else {
10028 ret = -EINVAL;
10029 goto err_open;
10030 }
10031 }
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +053010032#ifdef PLATFORM_AUTO
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +053010033 if ((config->sample_rate == 48000 ||
10034 config->sample_rate == 32000 ||
10035 config->sample_rate == 24000 ||
10036 config->sample_rate == 16000 ||
10037 config->sample_rate == 8000)&&
Deeraj Somanfa377bf2019-02-06 12:57:59 +053010038 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
10039 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +053010040 (flags & AUDIO_INPUT_FLAG_FAST) != 0)
10041#else
10042 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
10043 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
10044 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
10045 (flags & AUDIO_INPUT_FLAG_FAST) != 0)
10046#endif
10047{
Haynes Mathew George484e8d22017-07-31 18:55:17 -070010048 is_low_latency = true;
10049#if LOW_LATENCY_CAPTURE_USE_CASE
Revathi Uddarajud9f23d92020-07-27 10:55:06 +053010050 if ((flags & AUDIO_INPUT_FLAG_VOIP_TX) != 0)
10051 in->usecase = USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY;
10052 else
10053 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Haynes Mathew George484e8d22017-07-31 18:55:17 -070010054#endif
10055 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -080010056 if (!in->realtime) {
10057 in->config = pcm_config_audio_capture;
10058 frame_size = audio_stream_in_frame_size(&in->stream);
10059 buffer_size = get_input_buffer_size(config->sample_rate,
10060 config->format,
10061 channel_count,
10062 is_low_latency);
10063 in->config.period_size = buffer_size / frame_size;
10064 in->config.rate = config->sample_rate;
10065 in->af_period_multiplier = 1;
10066 } else {
10067 // period size is left untouched for rt mode playback
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +053010068#ifdef PLATFORM_AUTO
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +053010069 switch(config->sample_rate)
10070 {
10071 case 48000:
10072 in->config = pcm_config_audio_capture_rt_48KHz;
10073 break;
10074 case 32000:
10075 in->config = pcm_config_audio_capture_rt_32KHz;
10076 break;
10077 case 24000:
10078 in->config = pcm_config_audio_capture_rt_24KHz;
10079 break;
10080 case 16000:
10081 in->config = pcm_config_audio_capture_rt_16KHz;
10082 break;
10083 case 8000:
10084 in->config = pcm_config_audio_capture_rt_8KHz;
10085 break;
10086 default:
10087 in->config = pcm_config_audio_capture_rt_48KHz;
10088 }
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +053010089#else
10090 in->config = pcm_config_audio_capture_rt_48KHz;
10091#endif
Aalique Grahame22e49102018-12-18 14:23:57 -080010092 in->af_period_multiplier = af_period_multiplier;
10093 }
Kogara Naveen Kumarc5758232022-11-07 20:25:40 +053010094
10095 /* assign concurrent capture usecase if record has to caried out from
10096 * actual hardware input source */
10097 if (audio_extn_is_concurrent_capture_enabled() &&
10098 !audio_is_virtual_input_source(in->source)) {
10099 /* Acquire lock to avoid two concurrent use cases initialized to
10100 same pcm record use case */
10101 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY) {
10102 pthread_mutex_lock(&adev->lock);
10103 if (!(adev->pcm_low_latency_record_uc_state)) {
10104 ALOGD("%s: using USECASE_AUDIO_RECORD_LOW_LATENCY",__func__);
10105 adev->pcm_low_latency_record_uc_state = 1;
10106 pthread_mutex_unlock(&adev->lock);
10107 } else if (audio_extn_is_concurrent_low_latency_pcm_record_enabled()) {
10108 in->usecase = get_low_latency_record_usecase(adev);
10109 pthread_mutex_unlock(&adev->lock);
10110 } else {
10111 pthread_mutex_unlock(&adev->lock);
10112 /* Assign compress record use case for second record */
10113 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
10114 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
10115 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
10116 if (audio_extn_cin_applicable_stream(in)) {
10117 in->sample_rate = config->sample_rate;
10118 ret = audio_extn_cin_configure_input_stream(in, config);
10119 if (ret)
10120 goto err_open;
10121 }
10122 }
10123 }
10124 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -070010125 }
10126
Susan Wangb803cb52021-10-14 12:03:36 -040010127 /* Additional sample rates added below must also be present
10128 in audio_policy_configuration.xml for mmap_no_irq_in */
10129 bool valid_mmap_record_rate = (config->sample_rate == 8000 ||
10130 config->sample_rate == 16000 ||
Susan Wang89da9042021-10-14 12:03:36 -040010131 config->sample_rate == 24000 ||
Susan Wangb803cb52021-10-14 12:03:36 -040010132 config->sample_rate == 32000 ||
10133 config->sample_rate == 48000);
10134 if (valid_mmap_record_rate &&
10135 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -070010136 in->realtime = 0;
10137 in->usecase = USECASE_AUDIO_RECORD_MMAP;
10138 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -070010139 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -070010140 in->stream.start = in_start;
10141 in->stream.stop = in_stop;
10142 in->stream.create_mmap_buffer = in_create_mmap_buffer;
10143 in->stream.get_mmap_position = in_get_mmap_position;
Ramjee Singhbcb3b6c2021-11-17 13:19:16 +053010144 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -070010145 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
Haynes Mathew George46740472017-10-27 18:40:12 -070010146 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -070010147 in->usecase = USECASE_AUDIO_RECORD_HIFI;
10148 in->config = pcm_config_audio_capture;
10149 frame_size = audio_stream_in_frame_size(&in->stream);
10150 buffer_size = get_input_buffer_size(config->sample_rate,
10151 config->format,
10152 channel_count,
10153 false /*is_low_latency*/);
10154 in->config.period_size = buffer_size / frame_size;
10155 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -070010156 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -070010157 switch (config->format) {
10158 case AUDIO_FORMAT_PCM_32_BIT:
10159 in->bit_width = 32;
10160 break;
10161 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
10162 case AUDIO_FORMAT_PCM_8_24_BIT:
10163 in->bit_width = 24;
10164 break;
10165 default:
10166 in->bit_width = 16;
10167 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010168 } else if (is_single_device_type_equal(&in->device_list,
10169 AUDIO_DEVICE_IN_TELEPHONY_RX) ||
10170 is_single_device_type_equal(&in->device_list,
10171 AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070010172 if (config->sample_rate == 0)
10173 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
10174 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
10175 config->sample_rate != 8000) {
10176 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
10177 ret = -EINVAL;
10178 goto err_open;
10179 }
10180 if (config->format == AUDIO_FORMAT_DEFAULT)
10181 config->format = AUDIO_FORMAT_PCM_16_BIT;
10182 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
10183 config->format = AUDIO_FORMAT_PCM_16_BIT;
10184 ret = -EINVAL;
10185 goto err_open;
10186 }
10187
10188 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
Zhou Song62ea0282020-03-22 19:53:01 +080010189 if (adev->ha_proxy_enable &&
10190 is_single_device_type_equal(&in->device_list,
10191 AUDIO_DEVICE_IN_TELEPHONY_RX))
10192 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY2;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070010193 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070010194 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -080010195 in->af_period_multiplier = 1;
10196 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
Shalini Manjunathaac412b32020-01-03 15:00:14 +053010197 (!voice_extn_is_compress_voip_supported()) &&
Aalique Grahame22e49102018-12-18 14:23:57 -080010198 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
10199 (config->sample_rate == 8000 ||
10200 config->sample_rate == 16000 ||
10201 config->sample_rate == 32000 ||
10202 config->sample_rate == 48000) &&
10203 channel_count == 1) {
10204 in->usecase = USECASE_AUDIO_RECORD_VOIP;
10205 in->config = pcm_config_audio_capture;
10206 frame_size = audio_stream_in_frame_size(&in->stream);
10207 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
10208 config->sample_rate,
10209 config->format,
10210 channel_count, false /*is_low_latency*/);
10211 in->config.period_size = buffer_size / frame_size;
10212 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
10213 in->config.rate = config->sample_rate;
10214 in->af_period_multiplier = 1;
Mingshu Pangc2d65042021-01-14 16:19:10 +080010215 } else if (in->realtime) {
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +053010216#ifdef PLATFORM_AUTO
Kogara Naveen Kumara688a812022-04-27 16:45:59 +053010217 switch(config->sample_rate)
10218 {
10219 case 48000:
10220 in->config = pcm_config_audio_capture_rt_48KHz;
10221 break;
10222 case 32000:
10223 in->config = pcm_config_audio_capture_rt_32KHz;
10224 break;
10225 case 24000:
10226 in->config = pcm_config_audio_capture_rt_24KHz;
10227 break;
10228 case 16000:
10229 in->config = pcm_config_audio_capture_rt_16KHz;
10230 break;
10231 case 8000:
10232 in->config = pcm_config_audio_capture_rt_8KHz;
10233 break;
10234 default:
10235 in->config = pcm_config_audio_capture_rt_48KHz;
10236 }
Mingshu Pangc2d65042021-01-14 16:19:10 +080010237 in->config.format = pcm_format_from_audio_format(config->format);
10238 in->af_period_multiplier = af_period_multiplier;
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +053010239#else
10240 in->config = pcm_config_audio_capture_rt_48KHz;
10241#endif
10242} else {
Revathi Uddarajud2634032017-12-07 14:42:34 +053010243 int ret_val;
10244 pthread_mutex_lock(&adev->lock);
10245 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
10246 in, config, &channel_mask_updated);
10247 pthread_mutex_unlock(&adev->lock);
10248
10249 if (!ret_val) {
10250 if (channel_mask_updated == true) {
10251 ALOGD("%s: return error to retry with updated channel mask (%#x)",
10252 __func__, config->channel_mask);
10253 ret = -EINVAL;
10254 goto err_open;
10255 }
10256 ALOGD("%s: created multi-channel session succesfully",__func__);
10257 } else if (audio_extn_compr_cap_enabled() &&
10258 audio_extn_compr_cap_format_supported(config->format) &&
10259 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
10260 audio_extn_compr_cap_init(in);
10261 } else if (audio_extn_cin_applicable_stream(in)) {
Deeraj Soman14230922019-01-30 16:39:30 +053010262 ret = audio_extn_cin_configure_input_stream(in, config);
Revathi Uddarajud2634032017-12-07 14:42:34 +053010263 if (ret)
10264 goto err_open;
10265 } else {
10266 in->config = pcm_config_audio_capture;
10267 in->config.rate = config->sample_rate;
10268 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +053010269 in->format = config->format;
10270 frame_size = audio_stream_in_frame_size(&in->stream);
10271 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -070010272 config->format,
10273 channel_count,
10274 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +020010275 /* prevent division-by-zero */
10276 if (frame_size == 0) {
10277 ALOGE("%s: Error frame_size==0", __func__);
10278 ret = -EINVAL;
10279 goto err_open;
10280 }
10281
Revathi Uddarajud2634032017-12-07 14:42:34 +053010282 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -080010283 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -080010284
Revathi Uddarajud2634032017-12-07 14:42:34 +053010285 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
10286 /* optionally use VOIP usecase depending on config(s) */
10287 ret = adev_update_voice_comm_input_stream(in, config);
10288 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -080010289
Revathi Uddarajud2634032017-12-07 14:42:34 +053010290 if (ret) {
10291 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
10292 goto err_open;
10293 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -080010294 }
Jaideep Sharmad305a4a2020-02-27 14:29:04 +053010295
10296 /* assign concurrent capture usecase if record has to caried out from
10297 * actual hardware input source */
10298 if (audio_extn_is_concurrent_capture_enabled() &&
10299 !audio_is_virtual_input_source(in->source)) {
Samyak Jainc37062f2019-04-25 18:41:06 +053010300 /* Acquire lock to avoid two concurrent use cases initialized to
10301 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +080010302
Samyak Jainc37062f2019-04-25 18:41:06 +053010303 if (in->usecase == USECASE_AUDIO_RECORD) {
10304 pthread_mutex_lock(&adev->lock);
10305 if (!(adev->pcm_record_uc_state)) {
10306 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
10307 adev->pcm_record_uc_state = 1;
10308 pthread_mutex_unlock(&adev->lock);
Krishna Kishor Jha0f4d8482022-02-18 10:56:05 +053010309 } else if (audio_extn_is_concurrent_pcm_record_enabled()) {
10310 in->usecase = get_record_usecase(adev);
10311 pthread_mutex_unlock(&adev->lock);
Samyak Jainc37062f2019-04-25 18:41:06 +053010312 } else {
10313 pthread_mutex_unlock(&adev->lock);
10314 /* Assign compress record use case for second record */
10315 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
10316 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
10317 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
10318 if (audio_extn_cin_applicable_stream(in)) {
10319 in->sample_rate = config->sample_rate;
Deeraj Soman14230922019-01-30 16:39:30 +053010320 ret = audio_extn_cin_configure_input_stream(in, config);
Samyak Jainc37062f2019-04-25 18:41:06 +053010321 if (ret)
10322 goto err_open;
10323 }
10324 }
10325 }
kunleiz28c73e72019-03-27 17:24:04 +080010326 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -070010327 }
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +053010328
Ramjee Singh82fd0c12019-08-21 16:31:33 +053010329 if (audio_extn_ssr_get_stream() != in)
10330 in->config.channels = channel_count;
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -070010331
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -070010332 in->sample_rate = in->config.rate;
10333
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010334 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
10335 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010336 &in->device_list, flags, in->format,
Haynes Mathew George4ffef292017-11-21 15:08:02 -080010337 in->sample_rate, in->bit_width,
10338 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +053010339 register_format(in->format, in->supported_formats);
10340 register_channel_mask(in->channel_mask, in->supported_channel_masks);
10341 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010342
Dechen Chai22768452021-07-30 09:29:16 +053010343#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -080010344 in->error_log = error_log_create(
10345 ERROR_LOG_ENTRIES,
10346 1000000000 /* aggregate consecutive identical errors within one second */);
Dechen Chai22768452021-07-30 09:29:16 +053010347#endif
Aalique Grahame22e49102018-12-18 14:23:57 -080010348
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010349 /* This stream could be for sound trigger lab,
10350 get sound trigger pcm if present */
10351 audio_extn_sound_trigger_check_and_get_session(in);
10352
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010353 lock_input_stream(in);
10354 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
10355 pthread_mutex_lock(&adev->lock);
10356 in->card_status = adev->card_status;
10357 pthread_mutex_unlock(&adev->lock);
10358 pthread_mutex_unlock(&in->lock);
10359
Aalique Grahame22e49102018-12-18 14:23:57 -080010360 stream_app_type_cfg_init(&in->app_type_cfg);
10361
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010362 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -080010363
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010364 ret = io_streams_map_insert(adev, &in->stream.common,
10365 handle, AUDIO_PATCH_HANDLE_NONE);
10366 if (ret != 0)
10367 goto err_open;
10368
Susan Wang6dd13092021-01-25 10:27:11 -050010369 in->in_ctxt.input = in;
Derek Chenf939fb72018-11-13 13:34:41 -080010370
10371 pthread_mutex_lock(&adev->lock);
Susan Wang6dd13092021-01-25 10:27:11 -050010372 list_add_tail(&adev->active_inputs_list, &in->in_ctxt.list);
Derek Chenf939fb72018-11-13 13:34:41 -080010373 pthread_mutex_unlock(&adev->lock);
10374
Eric Laurent994a6932013-07-17 11:51:42 -070010375 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -080010376 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010377
10378err_open:
Krishna Kishor Jha0f4d8482022-02-18 10:56:05 +053010379 if (audio_extn_is_concurrent_pcm_record_enabled() && is_pcm_record_usecase(in->usecase)) {
10380 free_record_usecase(adev, in->usecase);
10381 } else if (in->usecase == USECASE_AUDIO_RECORD) {
Samyak Jainc37062f2019-04-25 18:41:06 +053010382 pthread_mutex_lock(&adev->lock);
10383 adev->pcm_record_uc_state = 0;
10384 pthread_mutex_unlock(&adev->lock);
10385 }
Kogara Naveen Kumarc5758232022-11-07 20:25:40 +053010386 if (audio_extn_is_concurrent_low_latency_pcm_record_enabled() && is_pcm_low_latency_record_usecase(in->usecase)) {
10387 free_low_latency_record_usecase(adev, in->usecase);
10388 } else if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY) {
10389 pthread_mutex_lock(&adev->lock);
10390 adev->pcm_low_latency_record_uc_state = 0;
10391 pthread_mutex_unlock(&adev->lock);
10392 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010393 free(in);
10394 *stream_in = NULL;
10395 return ret;
10396}
10397
10398static void adev_close_input_stream(struct audio_hw_device *dev,
10399 struct audio_stream_in *stream)
10400{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080010401 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -070010402 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -070010403 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +053010404
Sidipotu Ashokf43018c2014-05-02 16:21:50 +053010405 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080010406
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010407 if (in == NULL) {
10408 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
10409 return;
10410 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010411 io_streams_map_remove(adev, in->capture_handle);
10412
Susan Wang6dd13092021-01-25 10:27:11 -050010413 // remove out_ctxt early to prevent the stream
10414 // being opened in a race condition
10415 pthread_mutex_lock(&adev->lock);
10416 list_remove(&in->in_ctxt.list);
10417 pthread_mutex_unlock(&adev->lock);
10418
kunleiz70e57612018-12-28 17:50:23 +080010419 /* must deregister from sndmonitor first to prevent races
10420 * between the callback and close_stream
10421 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010422 audio_extn_snd_mon_unregister_listener(stream);
10423
kunleiz70e57612018-12-28 17:50:23 +080010424 /* Disable echo reference if there are no active input, hfp call
10425 * and sound trigger while closing input stream
10426 */
Eric Laurent637e2d42018-11-15 12:24:31 -080010427 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +080010428 !audio_extn_hfp_is_active(adev) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010429 !audio_extn_sound_trigger_check_ec_ref_enable()) {
10430 struct listnode out_devices;
10431 list_init(&out_devices);
10432 platform_set_echo_reference(adev, false, &out_devices);
Zhenlin Lian4f947842022-05-14 15:50:52 +053010433 clear_devices(&out_devices);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010434 } else
kunleiz70e57612018-12-28 17:50:23 +080010435 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +053010436
Dechen Chai22768452021-07-30 09:29:16 +053010437#ifndef LINUX_ENABLED
Weiyin Jiang2995f662019-04-17 14:25:12 +080010438 error_log_destroy(in->error_log);
10439 in->error_log = NULL;
Dechen Chai22768452021-07-30 09:29:16 +053010440#endif
Pallavid7c7a272018-01-16 11:22:55 +053010441
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080010442 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +053010443 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080010444 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +053010445 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080010446 if (ret != 0)
10447 ALOGE("%s: Compress voip input cannot be closed, error:%d",
10448 __func__, ret);
10449 } else
10450 in_standby(&stream->common);
10451
Weiyin Jiang280ea742020-09-08 20:28:22 +080010452 pthread_mutex_destroy(&in->lock);
10453 pthread_mutex_destroy(&in->pre_lock);
10454
Revathi Uddarajud2634032017-12-07 14:42:34 +053010455 pthread_mutex_lock(&adev->lock);
Krishna Kishor Jha0f4d8482022-02-18 10:56:05 +053010456 if (audio_extn_is_concurrent_pcm_record_enabled() && is_pcm_record_usecase(in->usecase)) {
10457 free_record_usecase(adev, in->usecase);
10458 } else if (in->usecase == USECASE_AUDIO_RECORD) {
Samyak Jain15fda662018-12-18 16:40:52 +053010459 adev->pcm_record_uc_state = 0;
10460 }
10461
Kogara Naveen Kumarc5758232022-11-07 20:25:40 +053010462 if (audio_extn_is_concurrent_low_latency_pcm_record_enabled() && is_pcm_low_latency_record_usecase(in->usecase)) {
10463 free_low_latency_record_usecase(adev, in->usecase);
10464 } else if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY) {
10465 adev->pcm_low_latency_record_uc_state = 0;
10466 }
10467
Kunlei Zhang5d5d8d92020-02-26 15:00:59 +080010468 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
10469 adev->enable_voicerx = false;
10470 }
10471
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -070010472 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -070010473 audio_extn_ssr_deinit();
10474 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010475
Garmond Leunge2433c32017-09-28 21:51:22 -070010476 if (audio_extn_ffv_get_stream() == in) {
10477 audio_extn_ffv_stream_deinit();
10478 }
10479
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010480 if (audio_extn_compr_cap_enabled() &&
Subhadra Jagadeesan63a1e832023-01-13 11:26:38 +053010481 audio_extn_compr_cap_format_supported(pcm_format_to_audio_format((in->config).format)))
Mingming Yine62d7842013-10-25 16:26:03 -070010482 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +053010483
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +053010484 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +053010485 audio_extn_cin_free_input_stream_resources(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010486
Mingming Yinfd7607b2016-01-22 12:48:44 -080010487 if (in->is_st_session) {
10488 ALOGV("%s: sound trigger pcm stop lab", __func__);
10489 audio_extn_sound_trigger_stop_lab(in);
10490 }
Zhenlin Lian4f947842022-05-14 15:50:52 +053010491 clear_devices(&in->device_list);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010492 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +053010493 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010494 return;
10495}
10496
Aalique Grahame22e49102018-12-18 14:23:57 -080010497/* verifies input and output devices and their capabilities.
10498 *
10499 * This verification is required when enabling extended bit-depth or
10500 * sampling rates, as not all qcom products support it.
10501 *
10502 * Suitable for calling only on initialization such as adev_open().
10503 * It fills the audio_device use_case_table[] array.
10504 *
10505 * Has a side-effect that it needs to configure audio routing / devices
10506 * in order to power up the devices and read the device parameters.
10507 * It does not acquire any hw device lock. Should restore the devices
10508 * back to "normal state" upon completion.
10509 */
10510static int adev_verify_devices(struct audio_device *adev)
10511{
10512 /* enumeration is a bit difficult because one really wants to pull
10513 * the use_case, device id, etc from the hidden pcm_device_table[].
10514 * In this case there are the following use cases and device ids.
10515 *
10516 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
10517 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
10518 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
10519 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
10520 * [USECASE_AUDIO_RECORD] = {0, 0},
10521 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
10522 * [USECASE_VOICE_CALL] = {2, 2},
10523 *
10524 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
10525 * USECASE_VOICE_CALL omitted, but possible for either input or output.
10526 */
10527
10528 /* should be the usecases enabled in adev_open_input_stream() */
10529 static const int test_in_usecases[] = {
10530 USECASE_AUDIO_RECORD,
10531 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
10532 };
10533 /* should be the usecases enabled in adev_open_output_stream()*/
10534 static const int test_out_usecases[] = {
10535 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
10536 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
10537 };
10538 static const usecase_type_t usecase_type_by_dir[] = {
10539 PCM_PLAYBACK,
10540 PCM_CAPTURE,
10541 };
10542 static const unsigned flags_by_dir[] = {
10543 PCM_OUT,
10544 PCM_IN,
10545 };
10546
10547 size_t i;
10548 unsigned dir;
10549 const unsigned card_id = adev->snd_card;
10550
10551 for (dir = 0; dir < 2; ++dir) {
10552 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
10553 const unsigned flags_dir = flags_by_dir[dir];
10554 const size_t testsize =
10555 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
10556 const int *testcases =
10557 dir ? test_in_usecases : test_out_usecases;
10558 const audio_devices_t audio_device =
10559 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
10560
10561 for (i = 0; i < testsize; ++i) {
10562 const audio_usecase_t audio_usecase = testcases[i];
10563 int device_id;
10564 struct pcm_params **pparams;
10565 struct stream_out out;
10566 struct stream_in in;
10567 struct audio_usecase uc_info;
10568 int retval;
10569
10570 pparams = &adev->use_case_table[audio_usecase];
10571 pcm_params_free(*pparams); /* can accept null input */
10572 *pparams = NULL;
10573
10574 /* find the device ID for the use case (signed, for error) */
10575 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
10576 if (device_id < 0)
10577 continue;
10578
10579 /* prepare structures for device probing */
10580 memset(&uc_info, 0, sizeof(uc_info));
10581 uc_info.id = audio_usecase;
10582 uc_info.type = usecase_type;
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010583 list_init(&uc_info.device_list);
Aalique Grahame22e49102018-12-18 14:23:57 -080010584 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -080010585 memset(&in, 0, sizeof(in));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010586 list_init(&in.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010587 update_device_list(&in.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -080010588 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
10589 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -080010590 }
10591 memset(&out, 0, sizeof(out));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010592 list_init(&out.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010593 update_device_list(&out.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -080010594 uc_info.stream.out = &out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010595 update_device_list(&uc_info.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -080010596 uc_info.in_snd_device = SND_DEVICE_NONE;
10597 uc_info.out_snd_device = SND_DEVICE_NONE;
10598 list_add_tail(&adev->usecase_list, &uc_info.list);
10599
10600 /* select device - similar to start_(in/out)put_stream() */
10601 retval = select_devices(adev, audio_usecase);
10602 if (retval >= 0) {
10603 *pparams = pcm_params_get(card_id, device_id, flags_dir);
10604#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -070010605 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -080010606 if (*pparams) {
10607 ALOGV("%s: (%s) card %d device %d", __func__,
10608 dir ? "input" : "output", card_id, device_id);
10609 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
10610 } else {
10611 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
10612 }
10613#endif
10614 }
10615
10616 /* deselect device - similar to stop_(in/out)put_stream() */
10617 /* 1. Get and set stream specific mixer controls */
10618 retval = disable_audio_route(adev, &uc_info);
10619 /* 2. Disable the rx device */
10620 retval = disable_snd_device(adev,
10621 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
10622 list_remove(&uc_info.list);
10623 }
10624 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010625 return 0;
10626}
10627
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010628int update_patch(unsigned int num_sources,
10629 const struct audio_port_config *sources,
10630 unsigned int num_sinks,
10631 const struct audio_port_config *sinks,
10632 audio_patch_handle_t handle,
10633 struct audio_patch_info *p_info,
10634 patch_type_t patch_type, bool new_patch)
10635{
Aniket Kumar Latad13758f2020-08-06 15:11:36 -070010636 ALOGV("%s: enter", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010637
10638 if (p_info == NULL) {
10639 ALOGE("%s: Invalid patch pointer", __func__);
10640 return -EINVAL;
10641 }
10642
10643 if (new_patch) {
10644 p_info->patch = (struct audio_patch *) calloc(1, sizeof(struct audio_patch));
10645 if (p_info->patch == NULL) {
10646 ALOGE("%s: Could not allocate patch", __func__);
10647 return -ENOMEM;
10648 }
10649 }
10650
10651 p_info->patch->id = handle;
10652 p_info->patch->num_sources = num_sources;
10653 p_info->patch->num_sinks = num_sinks;
10654
10655 for (int i = 0; i < num_sources; i++)
10656 p_info->patch->sources[i] = sources[i];
10657 for (int i = 0; i < num_sinks; i++)
10658 p_info->patch->sinks[i] = sinks[i];
10659
10660 p_info->patch_type = patch_type;
10661 return 0;
10662}
10663
10664audio_patch_handle_t generate_patch_handle()
10665{
10666 static audio_patch_handle_t patch_handle = AUDIO_PATCH_HANDLE_NONE;
10667 if (++patch_handle < 0)
10668 patch_handle = AUDIO_PATCH_HANDLE_NONE + 1;
10669 return patch_handle;
10670}
10671
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010672int adev_create_audio_patch(struct audio_hw_device *dev,
10673 unsigned int num_sources,
10674 const struct audio_port_config *sources,
10675 unsigned int num_sinks,
10676 const struct audio_port_config *sinks,
10677 audio_patch_handle_t *handle)
10678{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010679 int ret = 0;
10680 struct audio_device *adev = (struct audio_device *)dev;
10681 struct audio_patch_info *p_info = NULL;
10682 patch_type_t patch_type = PATCH_NONE;
10683 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10684 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
10685 struct audio_stream_info *s_info = NULL;
10686 struct audio_stream *stream = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010687 struct listnode devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010688 audio_devices_t device_type = AUDIO_DEVICE_NONE;
10689 bool new_patch = false;
10690 char addr[AUDIO_DEVICE_MAX_ADDRESS_LEN];
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010691
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010692 ALOGD("%s: enter: num sources %d, num_sinks %d, handle %d", __func__,
10693 num_sources, num_sinks, *handle);
10694
10695 if (num_sources == 0 || num_sources > AUDIO_PATCH_PORTS_MAX ||
10696 num_sinks == 0 || num_sinks > AUDIO_PATCH_PORTS_MAX) {
10697 ALOGE("%s: Invalid patch arguments", __func__);
10698 ret = -EINVAL;
10699 goto done;
10700 }
10701
10702 if (num_sources > 1) {
10703 ALOGE("%s: Multiple sources are not supported", __func__);
10704 ret = -EINVAL;
10705 goto done;
10706 }
10707
10708 if (sources == NULL || sinks == NULL) {
10709 ALOGE("%s: Invalid sources or sinks port config", __func__);
10710 ret = -EINVAL;
10711 goto done;
10712 }
10713
10714 ALOGV("%s: source role %d, source type %d", __func__,
10715 sources[0].type, sources[0].role);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010716 list_init(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010717
10718 // Populate source/sink information and fetch stream info
10719 switch (sources[0].type) {
10720 case AUDIO_PORT_TYPE_DEVICE: // Patch for audio capture or loopback
10721 device_type = sources[0].ext.device.type;
10722 strlcpy(&addr[0], &sources[0].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010723 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010724 if (sinks[0].type == AUDIO_PORT_TYPE_MIX) {
10725 patch_type = PATCH_CAPTURE;
10726 io_handle = sinks[0].ext.mix.handle;
10727 input_source = sinks[0].ext.mix.usecase.source;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010728 ALOGD("%s: Capture patch from device %x to mix %d",
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010729 __func__, device_type, io_handle);
10730 } else {
10731 // Device to device patch is not implemented.
10732 // This space will need changes if audio HAL
10733 // handles device to device patches in the future.
10734 patch_type = PATCH_DEVICE_LOOPBACK;
10735 }
10736 break;
10737 case AUDIO_PORT_TYPE_MIX: // Patch for audio playback
10738 io_handle = sources[0].ext.mix.handle;
10739 for (int i = 0; i < num_sinks; i++) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010740 device_type = sinks[i].ext.device.type;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010741 strlcpy(&addr[0], &sinks[i].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010742 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010743 }
10744 patch_type = PATCH_PLAYBACK;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010745 ALOGD("%s: Playback patch from mix handle %d to device %x",
10746 __func__, io_handle, get_device_types(&devices));
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010747 break;
10748 case AUDIO_PORT_TYPE_SESSION:
10749 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010750 ALOGE("%s: Unsupported source type %d", __func__, sources[0].type);
10751 ret = -EINVAL;
10752 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010753 }
10754
10755 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010756
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010757 // Generate patch info and update patch
10758 if (*handle == AUDIO_PATCH_HANDLE_NONE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010759 *handle = generate_patch_handle();
10760 p_info = (struct audio_patch_info *)
10761 calloc(1, sizeof(struct audio_patch_info));
10762 if (p_info == NULL) {
10763 ALOGE("%s: Failed to allocate memory", __func__);
10764 pthread_mutex_unlock(&adev->lock);
10765 ret = -ENOMEM;
10766 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010767 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010768 new_patch = true;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010769 } else {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010770 p_info = fetch_patch_info_l(adev, *handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010771 if (p_info == NULL) {
10772 ALOGE("%s: Unable to fetch patch for received patch handle %d",
10773 __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010774 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010775 ret = -EINVAL;
10776 goto done;
10777 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010778 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010779 update_patch(num_sources, sources, num_sinks, sinks,
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010780 *handle, p_info, patch_type, new_patch);
10781
10782 // Fetch stream info of associated mix for playback or capture patches
10783 if (p_info->patch_type == PATCH_PLAYBACK ||
10784 p_info->patch_type == PATCH_CAPTURE) {
10785 s_info = hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10786 if (s_info == NULL) {
10787 ALOGE("%s: Failed to obtain stream info", __func__);
10788 if (new_patch)
10789 free(p_info);
10790 pthread_mutex_unlock(&adev->lock);
10791 ret = -EINVAL;
10792 goto done;
10793 }
10794 ALOGV("%s: Fetched stream info with io_handle %d", __func__, io_handle);
10795 s_info->patch_handle = *handle;
10796 stream = s_info->stream;
10797 }
10798 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010799
10800 // Update routing for stream
10801 if (stream != NULL) {
Revathi Uddaraju4255a632021-12-02 05:11:13 -080010802 if (p_info->patch_type == PATCH_PLAYBACK) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010803 ret = route_output_stream((struct stream_out *) stream, &devices);
Revathi Uddaraju4255a632021-12-02 05:11:13 -080010804 } else if (p_info->patch_type == PATCH_CAPTURE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010805 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Revathi Uddaraju4255a632021-12-02 05:11:13 -080010806 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010807 if (ret < 0) {
10808 pthread_mutex_lock(&adev->lock);
10809 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10810 if (new_patch)
10811 free(p_info);
10812 pthread_mutex_unlock(&adev->lock);
10813 ALOGE("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10814 goto done;
10815 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010816 }
10817
10818 // Add new patch to patch map
10819 if (!ret && new_patch) {
10820 pthread_mutex_lock(&adev->lock);
10821 hashmapPut(adev->patch_map, (void *) (intptr_t) *handle, (void *) p_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010822 ALOGD("%s: Added a new patch with handle %d", __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010823 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010824 }
10825
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010826done:
Zhenlin Lian4f947842022-05-14 15:50:52 +053010827 clear_devices(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010828 audio_extn_hw_loopback_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010829 num_sources,
10830 sources,
10831 num_sinks,
10832 sinks,
10833 handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010834 audio_extn_auto_hal_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010835 num_sources,
10836 sources,
10837 num_sinks,
10838 sinks,
10839 handle);
10840 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010841}
10842
10843int adev_release_audio_patch(struct audio_hw_device *dev,
10844 audio_patch_handle_t handle)
10845{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010846 struct audio_device *adev = (struct audio_device *) dev;
10847 int ret = 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010848 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010849 struct audio_stream *stream = NULL;
Derek Chenf939fb72018-11-13 13:34:41 -080010850
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010851 if (handle == AUDIO_PATCH_HANDLE_NONE) {
10852 ALOGE("%s: Invalid patch handle %d", __func__, handle);
10853 ret = -EINVAL;
10854 goto done;
10855 }
10856
10857 ALOGD("%s: Remove patch with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010858 pthread_mutex_lock(&adev->lock);
10859 struct audio_patch_info *p_info = fetch_patch_info_l(adev, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010860 if (p_info == NULL) {
10861 ALOGE("%s: Patch info not found with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010862 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010863 ret = -EINVAL;
10864 goto done;
10865 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010866 struct audio_patch *patch = p_info->patch;
10867 if (patch == NULL) {
10868 ALOGE("%s: Patch not found for handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010869 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010870 ret = -EINVAL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010871 goto done;
10872 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010873 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10874 switch (patch->sources[0].type) {
10875 case AUDIO_PORT_TYPE_MIX:
10876 io_handle = patch->sources[0].ext.mix.handle;
10877 break;
10878 case AUDIO_PORT_TYPE_DEVICE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010879 if (p_info->patch_type == PATCH_CAPTURE)
10880 io_handle = patch->sinks[0].ext.mix.handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010881 break;
10882 case AUDIO_PORT_TYPE_SESSION:
10883 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010884 pthread_mutex_unlock(&adev->lock);
10885 ret = -EINVAL;
10886 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010887 }
10888
10889 // Remove patch and reset patch handle in stream info
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010890 patch_type_t patch_type = p_info->patch_type;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010891 patch_map_remove_l(adev, handle);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010892 if (patch_type == PATCH_PLAYBACK ||
10893 patch_type == PATCH_CAPTURE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010894 struct audio_stream_info *s_info =
10895 hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10896 if (s_info == NULL) {
10897 ALOGE("%s: stream for io_handle %d is not available", __func__, io_handle);
10898 pthread_mutex_unlock(&adev->lock);
10899 goto done;
10900 }
10901 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10902 stream = s_info->stream;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010903 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010904 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010905
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010906 if (stream != NULL) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010907 struct listnode devices;
10908 list_init(&devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010909 if (patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010910 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010911 else if (patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010912 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Zhenlin Lian4f947842022-05-14 15:50:52 +053010913 clear_devices(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010914 }
10915
10916 if (ret < 0)
10917 ALOGW("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10918
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010919done:
10920 audio_extn_hw_loopback_release_audio_patch(dev, handle);
10921 audio_extn_auto_hal_release_audio_patch(dev, handle);
10922
10923 ALOGV("%s: Successfully released patch %d", __func__, handle);
Derek Chenf939fb72018-11-13 13:34:41 -080010924 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010925}
10926
10927int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
10928{
Derek Chenf13dd492018-11-13 14:53:51 -080010929 int ret = 0;
10930
10931 ret = audio_extn_hw_loopback_get_audio_port(dev, config);
10932 ret |= audio_extn_auto_hal_get_audio_port(dev, config);
10933 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010934}
10935
10936int adev_set_audio_port_config(struct audio_hw_device *dev,
10937 const struct audio_port_config *config)
10938{
Derek Chenf13dd492018-11-13 14:53:51 -080010939 int ret = 0;
10940
10941 ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
10942 ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
10943 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010944}
10945
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -070010946static int adev_dump(const audio_hw_device_t *device __unused,
10947 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010948{
10949 return 0;
10950}
10951
10952static int adev_close(hw_device_t *device)
10953{
Aalique Grahame22e49102018-12-18 14:23:57 -080010954 size_t i;
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010955 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -070010956
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010957 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -070010958 return 0;
10959
10960 pthread_mutex_lock(&adev_init_lock);
10961
10962 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +053010963 if (audio_extn_spkr_prot_is_enabled())
10964 audio_extn_spkr_prot_deinit();
Jaideep Sharmaa2b49672019-09-10 20:37:03 +053010965 audio_extn_battery_properties_listener_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010966 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010967 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -080010968 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010969 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -080010970 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010971 audio_extn_utils_release_streams_cfg_lists(
10972 &adev->streams_output_cfg_list,
10973 &adev->streams_input_cfg_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010974 if (audio_extn_qap_is_enabled())
10975 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010976 if (audio_extn_qaf_is_enabled())
10977 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -070010978 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +080010979 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -070010980 free(adev->snd_dev_ref_cnt);
10981 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010982 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
10983 pcm_params_free(adev->use_case_table[i]);
10984 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010985 if (adev->adm_deinit)
10986 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010987 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010988 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010989 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010990 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010991 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010992 if (adev->device_cfg_params) {
10993 free(adev->device_cfg_params);
10994 adev->device_cfg_params = NULL;
10995 }
Derek Chend2530072014-11-24 12:39:14 -080010996 if(adev->ext_hw_plugin)
10997 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -080010998 audio_extn_auto_hal_deinit();
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010999 free_map(adev->patch_map);
11000 free_map(adev->io_streams_map);
Kiran Kandi910e1862013-10-29 13:29:42 -070011001 free(device);
11002 adev = NULL;
11003 }
11004 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +053011005 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011006 return 0;
11007}
11008
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070011009/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
11010 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
11011 * just that it _might_ work.
11012 */
11013static int period_size_is_plausible_for_low_latency(int period_size)
11014{
11015 switch (period_size) {
11016 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -070011017 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070011018 case 240:
11019 case 320:
11020 case 480:
11021 return 1;
11022 default:
11023 return 0;
11024 }
11025}
11026
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053011027static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
11028{
11029 bool is_snd_card_status = false;
11030 bool is_ext_device_status = false;
11031 char value[32];
11032 int card = -1;
11033 card_status_t status;
11034
11035 if (cookie != adev || !parms)
11036 return;
11037
11038 if (!parse_snd_card_status(parms, &card, &status)) {
11039 is_snd_card_status = true;
11040 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
11041 is_ext_device_status = true;
11042 } else {
11043 // not a valid event
11044 return;
11045 }
11046
11047 pthread_mutex_lock(&adev->lock);
11048 if (card == adev->snd_card || is_ext_device_status) {
11049 if (is_snd_card_status && adev->card_status != status) {
Jaideep Sharmacb402512020-09-24 17:51:07 +053011050 ALOGD("%s card_status %d", __func__, status);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053011051 adev->card_status = status;
11052 platform_snd_card_update(adev->platform, status);
11053 audio_extn_fm_set_parameters(adev, parms);
Derek Chend6f371d2019-03-01 13:45:58 -080011054 audio_extn_auto_hal_set_parameters(adev, parms);
Zhou Song4f43e352019-07-02 00:32:23 +080011055 if (status == CARD_STATUS_OFFLINE)
11056 audio_extn_sco_reset_configuration();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053011057 } else if (is_ext_device_status) {
11058 platform_set_parameters(adev->platform, parms);
11059 }
11060 }
11061 pthread_mutex_unlock(&adev->lock);
11062 return;
11063}
11064
Weiyin Jiang280ea742020-09-08 20:28:22 +080011065/* adev lock held */
11066int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011067{
11068 struct audio_usecase *uc_info;
Zhou Song407e5aa2020-12-27 19:13:04 +080011069 struct audio_usecase *usecase;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080011070 struct listnode devices;
Zhou Song407e5aa2020-12-27 19:13:04 +080011071 struct listnode *node;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011072
11073 uc_info = get_usecase_from_list(adev, out->usecase);
11074 if (uc_info == NULL) {
11075 ALOGE("%s: Could not find the usecase (%d) in the list",
11076 __func__, out->usecase);
11077 return -EINVAL;
11078 }
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080011079 list_init(&devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011080
Zhou Songbaddf9f2020-11-20 13:57:39 +080011081 ALOGD("%s: enter: usecase(%d: %s), a2dp muted %d", __func__,
11082 out->usecase, use_case_table[out->usecase], out->a2dp_muted);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011083
11084 if (restore) {
Weiyin Jiang280ea742020-09-08 20:28:22 +080011085 pthread_mutex_lock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011086 // restore A2DP device for active usecases and unmute if required
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080011087 if (is_a2dp_out_device_type(&out->device_list)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011088 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
Zhou Songe5225132019-09-26 15:33:36 +080011089 if (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)
11090 select_devices(adev, uc_info->id);
Zhou Songbaddf9f2020-11-20 13:57:39 +080011091
11092 if (is_offload_usecase(out->usecase)) {
11093 if (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)
Weiyin Jiang280ea742020-09-08 20:28:22 +080011094 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
Zhou Songbaddf9f2020-11-20 13:57:39 +080011095 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
11096 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
11097 } else {
11098 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011099 }
Zhou Songbaddf9f2020-11-20 13:57:39 +080011100 out->a2dp_muted = false;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011101 }
Weiyin Jiang280ea742020-09-08 20:28:22 +080011102 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011103 } else {
Weiyin Jiang280ea742020-09-08 20:28:22 +080011104 pthread_mutex_lock(&out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +080011105 // mute stream and switch to speaker if suspended
11106 if (!out->a2dp_muted && !out->standby) {
Zhou Songcf77af02021-05-14 18:21:14 +080011107 if ((is_a2dp_out_device_type(&devices) && list_length(&devices) == 1) ||
11108 (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)) {
Zhou Song8edbbdb2021-01-14 16:48:03 +080011109 out->a2dp_muted = true;
11110 if (is_offload_usecase(out->usecase)) {
11111 if (out->offload_state == OFFLOAD_STATE_PLAYING)
11112 compress_pause(out->compr);
11113 out_set_compr_volume(&out->stream, (float)0, (float)0);
Zhou Song8edbbdb2021-01-14 16:48:03 +080011114 } else {
Weiyin Jiang906db3c2021-03-02 13:17:04 +080011115 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
11116 out_set_voip_volume(&out->stream, (float)0, (float)0);
11117 else
11118 out_set_pcm_volume(&out->stream, (float)0, (float)0);
11119
Zhou Song8edbbdb2021-01-14 16:48:03 +080011120 /* wait for stale pcm drained before switching to speaker */
11121 uint32_t latency =
11122 (out->config.period_count * out->config.period_size * 1000) /
11123 (out->config.rate);
11124 usleep(latency * 1000);
11125 }
Zhou Songbaddf9f2020-11-20 13:57:39 +080011126 }
Manish Chaturvedi0a8305f2023-03-17 15:47:37 +053011127 assign_devices(&devices, &out->device_list);
11128 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
11129 list_for_each(node, &adev->usecase_list) {
11130 usecase = node_to_item(node, struct audio_usecase, list);
11131 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
11132 !is_a2dp_out_device_type(&usecase->stream.out->device_list) &&
11133 !is_sco_out_device_type(&usecase->stream.out->device_list) &&
11134 platform_check_backends_match(SND_DEVICE_OUT_SPEAKER,
11135 usecase->out_snd_device)) {
11136 assign_devices(&out->device_list, &usecase->stream.out->device_list);
11137 break;
11138 }
11139 }
Zhou Songbaddf9f2020-11-20 13:57:39 +080011140 select_devices(adev, out->usecase);
Zhou Song8edbbdb2021-01-14 16:48:03 +080011141 ALOGD("%s: switched to device:%s and stream muted:%d", __func__,
11142 platform_get_snd_device_name(uc_info->out_snd_device), out->a2dp_muted);
Zhou Songbaddf9f2020-11-20 13:57:39 +080011143 if (is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011144 if (out->offload_state == OFFLOAD_STATE_PLAYING)
11145 compress_resume(out->compr);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011146 }
Zhou Songbaddf9f2020-11-20 13:57:39 +080011147 assign_devices(&out->device_list, &devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011148 }
Weiyin Jiang280ea742020-09-08 20:28:22 +080011149 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011150 }
Zhenlin Lian4f947842022-05-14 15:50:52 +053011151 clear_devices(&devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011152 ALOGV("%s: exit", __func__);
11153 return 0;
11154}
11155
Haynes Mathew George01156f92018-04-13 15:29:54 -070011156void adev_on_battery_status_changed(bool charging)
11157{
11158 pthread_mutex_lock(&adev->lock);
11159 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
11160 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +080011161 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -070011162 pthread_mutex_unlock(&adev->lock);
11163}
11164
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011165static int adev_open(const hw_module_t *module, const char *name,
11166 hw_device_t **device)
11167{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053011168 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -080011169 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053011170 char mixer_ctl_name[128] = {0};
11171 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053011172
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080011173 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011174 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
11175
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070011176 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -070011177 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070011178 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -070011179 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070011180 ALOGD("%s: returning existing instance of adev", __func__);
11181 ALOGD("%s: exit", __func__);
11182 pthread_mutex_unlock(&adev_init_lock);
11183 return 0;
11184 }
11185
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011186 adev = calloc(1, sizeof(struct audio_device));
11187
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -070011188 if (!adev) {
11189 pthread_mutex_unlock(&adev_init_lock);
11190 return -ENOMEM;
11191 }
11192
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -070011193 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
11194
Weiyin Jiange6ce6312019-01-28 18:28:22 +080011195 // register audio ext hidl at the earliest
11196 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053011197#ifdef DYNAMIC_LOG_ENABLED
11198 register_for_dynamic_logging("hal");
11199#endif
11200
Derek Chenf939fb72018-11-13 13:34:41 -080011201 /* default audio HAL major version */
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011202 uint32_t maj_version = 3;
Derek Chenf939fb72018-11-13 13:34:41 -080011203 if(property_get("vendor.audio.hal.maj.version", value, NULL))
11204 maj_version = atoi(value);
11205
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011206 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -080011207 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011208 adev->device.common.module = (struct hw_module_t *)module;
11209 adev->device.common.close = adev_close;
11210
11211 adev->device.init_check = adev_init_check;
11212 adev->device.set_voice_volume = adev_set_voice_volume;
11213 adev->device.set_master_volume = adev_set_master_volume;
11214 adev->device.get_master_volume = adev_get_master_volume;
11215 adev->device.set_master_mute = adev_set_master_mute;
11216 adev->device.get_master_mute = adev_get_master_mute;
11217 adev->device.set_mode = adev_set_mode;
11218 adev->device.set_mic_mute = adev_set_mic_mute;
11219 adev->device.get_mic_mute = adev_get_mic_mute;
11220 adev->device.set_parameters = adev_set_parameters;
11221 adev->device.get_parameters = adev_get_parameters;
11222 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
11223 adev->device.open_output_stream = adev_open_output_stream;
11224 adev->device.close_output_stream = adev_close_output_stream;
11225 adev->device.open_input_stream = adev_open_input_stream;
11226 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053011227 adev->device.create_audio_patch = adev_create_audio_patch;
11228 adev->device.release_audio_patch = adev_release_audio_patch;
11229 adev->device.get_audio_port = adev_get_audio_port;
11230 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011231 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +053011232 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011233
11234 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011235 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -080011236 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011237 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011238 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -080011239 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -070011240 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +053011241 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -070011242 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -070011243 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -070011244 /* Init audio and voice feature */
11245 audio_extn_feature_init();
11246 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070011247 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -080011248 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -080011249 list_init(&adev->active_inputs_list);
11250 list_init(&adev->active_outputs_list);
Rahul Sharma99770982019-03-06 17:05:26 +053011251 list_init(&adev->audio_patch_record_list);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011252 adev->io_streams_map = hashmapCreate(AUDIO_IO_PORTS_MAX, audio_extn_utils_hash_fn,
11253 audio_extn_utils_hash_eq);
11254 if (!adev->io_streams_map) {
11255 ALOGE("%s: Could not create io streams map", __func__);
11256 ret = -ENOMEM;
11257 goto adev_open_err;
11258 }
11259 adev->patch_map = hashmapCreate(AUDIO_PATCH_PORTS_MAX, audio_extn_utils_hash_fn,
11260 audio_extn_utils_hash_eq);
11261 if (!adev->patch_map) {
11262 ALOGE("%s: Could not create audio patch map", __func__);
11263 ret = -ENOMEM;
11264 goto adev_open_err;
11265 }
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -080011266 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -070011267 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +053011268 adev->pcm_record_uc_state = 0;
Kogara Naveen Kumarc5758232022-11-07 20:25:40 +053011269 adev->pcm_low_latency_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +053011270 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +053011271 adev->perf_lock_opts[0] = 0x101;
11272 adev->perf_lock_opts[1] = 0x20E;
11273 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +080011274 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -070011275 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053011276 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070011277 adev->adm_routing_changed = false;
Revathi Uddarajub26e3932020-06-10 14:51:02 +053011278 adev->a2dp_started = false;
Zhou Song503196b2021-07-23 17:31:05 +080011279 adev->ha_proxy_enable = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +053011280
Zhou Song68ebc352019-12-05 17:11:15 +080011281 audio_extn_perf_lock_init();
11282
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011283 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -070011284 adev->platform = platform_init(adev);
11285 if (!adev->platform) {
Eric Laurentb23d5282013-05-14 15:27:20 -070011286 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011287 ret = -EINVAL;
11288 goto adev_open_err;
Eric Laurentb23d5282013-05-14 15:27:20 -070011289 }
Eric Laurentc4aef752013-09-12 17:45:53 -070011290
Aalique Grahame22e49102018-12-18 14:23:57 -080011291 adev->extspk = audio_extn_extspk_init(adev);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053011292 if (audio_extn_qap_is_enabled()) {
11293 ret = audio_extn_qap_init(adev);
11294 if (ret < 0) {
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053011295 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011296 goto adev_open_err;
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053011297 }
11298 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
11299 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
11300 }
Aalique Grahame22e49102018-12-18 14:23:57 -080011301
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053011302 if (audio_extn_qaf_is_enabled()) {
11303 ret = audio_extn_qaf_init(adev);
11304 if (ret < 0) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053011305 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011306 goto adev_open_err;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053011307 }
11308
11309 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
11310 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
11311 }
11312
Derek Chenae7b0342019-02-08 15:17:04 -080011313 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -080011314 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
11315
Eric Laurentc4aef752013-09-12 17:45:53 -070011316 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
11317 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
11318 if (adev->visualizer_lib == NULL) {
11319 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
11320 } else {
11321 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
11322 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080011323 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070011324 "visualizer_hal_start_output");
11325 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080011326 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070011327 "visualizer_hal_stop_output");
11328 }
11329 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +053011330 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080011331 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -080011332 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +080011333 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +053011334 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070011335 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -070011336
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080011337 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
11338 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
11339 if (adev->offload_effects_lib == NULL) {
11340 ALOGE("%s: DLOPEN failed for %s", __func__,
11341 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
11342 } else {
11343 ALOGV("%s: DLOPEN successful for %s", __func__,
11344 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
11345 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +053011346 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080011347 "offload_effects_bundle_hal_start_output");
11348 adev->offload_effects_stop_output =
11349 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
11350 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080011351 adev->offload_effects_set_hpx_state =
11352 (int (*)(bool))dlsym(adev->offload_effects_lib,
11353 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +053011354 adev->offload_effects_get_parameters =
11355 (void (*)(struct str_parms *, struct str_parms *))
11356 dlsym(adev->offload_effects_lib,
11357 "offload_effects_bundle_get_parameters");
11358 adev->offload_effects_set_parameters =
11359 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
11360 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080011361 }
11362 }
11363
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070011364 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
11365 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
11366 if (adev->adm_lib == NULL) {
11367 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
11368 } else {
11369 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
11370 adev->adm_init = (adm_init_t)
11371 dlsym(adev->adm_lib, "adm_init");
11372 adev->adm_deinit = (adm_deinit_t)
11373 dlsym(adev->adm_lib, "adm_deinit");
11374 adev->adm_register_input_stream = (adm_register_input_stream_t)
11375 dlsym(adev->adm_lib, "adm_register_input_stream");
11376 adev->adm_register_output_stream = (adm_register_output_stream_t)
11377 dlsym(adev->adm_lib, "adm_register_output_stream");
11378 adev->adm_deregister_stream = (adm_deregister_stream_t)
11379 dlsym(adev->adm_lib, "adm_deregister_stream");
11380 adev->adm_request_focus = (adm_request_focus_t)
11381 dlsym(adev->adm_lib, "adm_request_focus");
11382 adev->adm_abandon_focus = (adm_abandon_focus_t)
11383 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -070011384 adev->adm_set_config = (adm_set_config_t)
11385 dlsym(adev->adm_lib, "adm_set_config");
11386 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
11387 dlsym(adev->adm_lib, "adm_request_focus_v2");
11388 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
11389 dlsym(adev->adm_lib, "adm_is_noirq_avail");
11390 adev->adm_on_routing_change = (adm_on_routing_change_t)
11391 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070011392 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
11393 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070011394 }
11395 }
11396
Aalique Grahame22e49102018-12-18 14:23:57 -080011397 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070011398 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +080011399 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Kunlei Zhanga3c4cb02021-03-05 16:03:54 +080011400 adev->fluence_nn_usecase_id = USECASE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -080011401 //initialize this to false for now,
11402 //this will be set to true through set param
11403 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070011404
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -070011405 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011406 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -080011407
11408 if (k_enable_extended_precision)
11409 adev_verify_devices(adev);
11410
Xiaojun Sang785b5da2017-08-03 15:52:29 +080011411 adev->dsp_bit_width_enforce_mode =
11412 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011413
Dhananjay Kumard6d32152016-10-13 16:11:03 +053011414 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
11415 &adev->streams_output_cfg_list,
11416 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070011417
Kiran Kandi910e1862013-10-29 13:29:42 -070011418 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070011419
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070011420 int trial;
Manisha Agarwalc75a0202019-12-06 18:48:25 +053011421 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070011422 trial = atoi(value);
11423 if (period_size_is_plausible_for_low_latency(trial)) {
11424 pcm_config_low_latency.period_size = trial;
11425 pcm_config_low_latency.start_threshold = trial / 4;
11426 pcm_config_low_latency.avail_min = trial / 4;
11427 configured_low_latency_capture_period_size = trial;
11428 }
11429 }
ronghuiz93177262021-04-21 19:58:13 +080011430 if (property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070011431 trial = atoi(value);
11432 if (period_size_is_plausible_for_low_latency(trial)) {
11433 configured_low_latency_capture_period_size = trial;
11434 }
11435 }
11436
Vignesh Kulothungan7d374312018-02-21 17:12:00 -080011437 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
11438
Eric Laurent4b084132018-10-19 17:33:43 -070011439 adev->camera_orientation = CAMERA_DEFAULT;
11440
Manisha Agarwalc75a0202019-12-06 18:48:25 +053011441 if (property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -070011442 af_period_multiplier = atoi(value);
11443 if (af_period_multiplier < 0)
11444 af_period_multiplier = 2;
11445 else if (af_period_multiplier > 4)
11446 af_period_multiplier = 4;
11447
11448 ALOGV("new period_multiplier = %d", af_period_multiplier);
11449 }
11450
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080011451 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080011452
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -070011453 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070011454 pthread_mutex_unlock(&adev_init_lock);
11455
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070011456 if (adev->adm_init)
11457 adev->adm_data = adev->adm_init();
11458
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053011459 qahwi_init(*device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080011460 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053011461
11462 audio_extn_snd_mon_init();
11463 pthread_mutex_lock(&adev->lock);
11464 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
11465 adev->card_status = CARD_STATUS_ONLINE;
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -050011466 adev->out_power_policy = POWER_POLICY_STATUS_ONLINE;
11467 adev->in_power_policy = POWER_POLICY_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -070011468 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
11469 /*
11470 * if the battery state callback happens before charging can be queried,
11471 * it will be guarded with the adev->lock held in the cb function and so
11472 * the callback value will reflect the latest state
11473 */
11474 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053011475 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +080011476 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -070011477 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +080011478 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053011479 /* Allocate memory for Device config params */
11480 adev->device_cfg_params = (struct audio_device_config_param*)
11481 calloc(platform_get_max_codec_backend(),
11482 sizeof(struct audio_device_config_param));
11483 if (adev->device_cfg_params == NULL)
11484 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053011485
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053011486 /*
11487 * Check if new PSPD matrix mixer control is supported. If not
11488 * supported, then set flag so that old mixer ctrl is sent while
11489 * sending pspd coefficients on older kernel version. Query mixer
11490 * control for default pcm id and channel value one.
11491 */
11492 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
11493 "AudStr %d ChMixer Weight Ch %d", 0, 1);
11494
11495 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
11496 if (!ctl) {
11497 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
11498 __func__, mixer_ctl_name);
11499 adev->use_old_pspd_mix_ctrl = true;
11500 }
11501
Jaideep Sharma0fa53812020-09-17 09:00:11 +053011502 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011503 return 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011504
11505adev_open_err:
11506 free_map(adev->patch_map);
11507 free_map(adev->io_streams_map);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080011508 free(adev->snd_dev_ref_cnt);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011509 pthread_mutex_destroy(&adev->lock);
11510 free(adev);
11511 adev = NULL;
11512 *device = NULL;
11513 pthread_mutex_unlock(&adev_init_lock);
11514 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011515}
11516
11517static struct hw_module_methods_t hal_module_methods = {
11518 .open = adev_open,
11519};
11520
11521struct audio_module HAL_MODULE_INFO_SYM = {
11522 .common = {
11523 .tag = HARDWARE_MODULE_TAG,
11524 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
11525 .hal_api_version = HARDWARE_HAL_API_VERSION,
11526 .id = AUDIO_HARDWARE_MODULE_ID,
11527 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -080011528 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011529 .methods = &hal_module_methods,
11530 },
11531};