blob: 0e221e2d98a62e00e85d2a77c4448bccb3bda9f0 [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 *
37 * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080038 */
39
40#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070041#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080042/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070043/*#define VERY_VERY_VERBOSE_LOGGING*/
44#ifdef VERY_VERY_VERBOSE_LOGGING
45#define ALOGVV ALOGV
46#else
47#define ALOGVV(a...) do { } while(0)
48#endif
George Gao3018ede2019-10-23 13:23:00 -070049#include <limits.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080050#include <errno.h>
51#include <pthread.h>
52#include <stdint.h>
53#include <sys/time.h>
54#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080055#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070056#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070057#include <sys/resource.h>
58#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080059
Aalique Grahame22e49102018-12-18 14:23:57 -080060#include <log/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070061#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080062#include <cutils/str_parms.h>
63#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070064#include <cutils/atomic.h>
65#include <cutils/sched_policy.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070066#include <hardware/audio_effect.h>
Haynes Mathew George484e8d22017-07-31 18:55:17 -070067#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070068#include <system/thread_defs.h>
Haynes Mathew George16081042017-05-31 17:16:49 -070069#include <tinyalsa/asoundlib.h>
Andy Hunga1f48fa2019-07-01 18:14:53 -070070#include <utils/Timers.h> // systemTime
Eric Laurentb23d5282013-05-14 15:27:20 -070071#include <audio_effects/effect_aec.h>
72#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053073#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080074#include "audio_hw.h"
Wei Wangf7ca6c92017-11-21 14:51:20 -080075#include "audio_perf.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070076#include "platform_api.h"
77#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070078#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080079#include "voice_extn.h"
Ashish Jaind5694242017-09-05 20:09:06 +053080#include "ip_hdlr_intf.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080081
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070082#include "sound/compress_params.h"
Xiaojun Sang782e5b12020-06-29 21:13:06 +080083
84#ifdef AUDIO_GKI_ENABLED
85#include "sound/audio_compressed_formats.h"
86#endif
87
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080088#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080089
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053090#ifdef DYNAMIC_LOG_ENABLED
91#include <log_xml_parser.h>
92#define LOG_MASK HAL_MOD_FILE_AUDIO_HW
93#include <log_utils.h>
94#endif
95
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070096#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053097/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
98#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070099#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700100#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Arun Mirpuri5d170872019-03-26 13:21:31 -0700101#define MMAP_PLAYBACK_VOLUME_MAX 0x2000
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530102#define PCM_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530103#define DSD_VOLUME_MIN_DB (-110)
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700104#define INVALID_OUT_VOLUME -1
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700105#define AUDIO_IO_PORTS_MAX 32
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700106
Zhou Songbaddf9f2020-11-20 13:57:39 +0800107#define PLAYBACK_GAIN_MAX 1.0f
Aalique Grahame22e49102018-12-18 14:23:57 -0800108#define RECORD_GAIN_MIN 0.0f
109#define RECORD_GAIN_MAX 1.0f
110#define RECORD_VOLUME_CTL_MAX 0x2000
111
112/* treat as unsigned Q1.13 */
113#define APP_TYPE_GAIN_DEFAULT 0x2000
114
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700115#define PROXY_OPEN_RETRY_COUNT 100
116#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800117
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800118#define GET_USECASE_AUDIO_PLAYBACK_PRIMARY(db) \
119 (db)? USECASE_AUDIO_PLAYBACK_DEEP_BUFFER : \
120 USECASE_AUDIO_PLAYBACK_LOW_LATENCY
121#define GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(db) \
122 (db)? pcm_config_deep_buffer : pcm_config_low_latency
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800123
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700124#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700125#define DEFAULT_VOIP_BUF_DURATION_MS 20
126#define DEFAULT_VOIP_BIT_DEPTH_BYTE sizeof(int16_t)
127#define DEFAULT_VOIP_SAMP_RATE 48000
128
129#define VOIP_IO_BUF_SIZE(SR, DURATION_MS, BIT_DEPTH) (SR)/1000 * DURATION_MS * BIT_DEPTH
130
131struct pcm_config default_pcm_config_voip_copp = {
132 .channels = 1,
133 .rate = DEFAULT_VOIP_SAMP_RATE, /* changed when the stream is opened */
134 .period_size = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
135 .period_count = 2,
136 .format = PCM_FORMAT_S16_LE,
kunleiz95b597a2017-10-23 17:07:33 +0800137 .avail_min = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
138 .stop_threshold = INT_MAX,
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700139};
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700140
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700141#define MIN_CHANNEL_COUNT 1
142#define DEFAULT_CHANNEL_COUNT 2
143#define MAX_HIFI_CHANNEL_COUNT 8
144
Aalique Grahame22e49102018-12-18 14:23:57 -0800145#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
146#define MAX_CHANNEL_COUNT 1
147#else
148#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
149#define XSTR(x) STR(x)
150#define STR(x) #x
151#endif
152
Avinash Chandrad7296d42021-08-04 15:07:47 +0530153#define IS_USB_HIFI (MAX_HIFI_CHANNEL_COUNT >= MAX_CHANNEL_COUNT) ? \
154 true : false
155
Dechen Chai22768452021-07-30 09:29:16 +0530156#ifdef LINUX_ENABLED
157static inline int64_t audio_utils_ns_from_timespec(const struct timespec *ts)
158{
159 return ts->tv_sec * 1000000000LL + ts->tv_nsec;
160}
161#endif
162
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700163static unsigned int configured_low_latency_capture_period_size =
164 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
165
Haynes Mathew George16081042017-05-31 17:16:49 -0700166#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
167#define MMAP_PERIOD_COUNT_MIN 32
168#define MMAP_PERIOD_COUNT_MAX 512
169#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
170
Aalique Grahame22e49102018-12-18 14:23:57 -0800171/* This constant enables extended precision handling.
172 * TODO The flag is off until more testing is done.
173 */
174static const bool k_enable_extended_precision = false;
Arun Mirpurie008ed22019-03-21 11:21:04 -0700175extern int AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Aalique Grahame22e49102018-12-18 14:23:57 -0800176
Eric Laurentb23d5282013-05-14 15:27:20 -0700177struct pcm_config pcm_config_deep_buffer = {
178 .channels = 2,
179 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
180 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
181 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
182 .format = PCM_FORMAT_S16_LE,
183 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
184 .stop_threshold = INT_MAX,
185 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
186};
187
188struct pcm_config pcm_config_low_latency = {
189 .channels = 2,
190 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
191 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
192 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
193 .format = PCM_FORMAT_S16_LE,
194 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
195 .stop_threshold = INT_MAX,
196 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
197};
198
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800199struct pcm_config pcm_config_haptics_audio = {
200 .channels = 1,
201 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
202 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
203 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
204 .format = PCM_FORMAT_S16_LE,
205 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
206 .stop_threshold = INT_MAX,
207 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
208};
209
210struct pcm_config pcm_config_haptics = {
211 .channels = 1,
212 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
213 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
214 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
215 .format = PCM_FORMAT_S16_LE,
216 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
217 .stop_threshold = INT_MAX,
218 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
219};
220
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700221static int af_period_multiplier = 4;
222struct pcm_config pcm_config_rt = {
223 .channels = 2,
224 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
225 .period_size = ULL_PERIOD_SIZE, //1 ms
226 .period_count = 512, //=> buffer size is 512ms
227 .format = PCM_FORMAT_S16_LE,
228 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
229 .stop_threshold = INT_MAX,
230 .silence_threshold = 0,
231 .silence_size = 0,
232 .avail_min = ULL_PERIOD_SIZE, //1 ms
233};
234
Eric Laurentb23d5282013-05-14 15:27:20 -0700235struct pcm_config pcm_config_hdmi_multi = {
236 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
237 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
238 .period_size = HDMI_MULTI_PERIOD_SIZE,
239 .period_count = HDMI_MULTI_PERIOD_COUNT,
240 .format = PCM_FORMAT_S16_LE,
241 .start_threshold = 0,
242 .stop_threshold = INT_MAX,
243 .avail_min = 0,
244};
245
Haynes Mathew George16081042017-05-31 17:16:49 -0700246struct pcm_config pcm_config_mmap_playback = {
247 .channels = 2,
248 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
249 .period_size = MMAP_PERIOD_SIZE,
250 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
251 .format = PCM_FORMAT_S16_LE,
252 .start_threshold = MMAP_PERIOD_SIZE*8,
253 .stop_threshold = INT32_MAX,
254 .silence_threshold = 0,
255 .silence_size = 0,
256 .avail_min = MMAP_PERIOD_SIZE, //1 ms
257};
258
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700259struct pcm_config pcm_config_hifi = {
260 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
261 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
262 .period_size = HIFI_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
263 .period_count = HIFI_BUFFER_OUTPUT_PERIOD_COUNT,
264 .format = PCM_FORMAT_S24_3LE,
265 .start_threshold = 0,
266 .stop_threshold = INT_MAX,
267 .avail_min = 0,
268};
269
Eric Laurentb23d5282013-05-14 15:27:20 -0700270struct pcm_config pcm_config_audio_capture = {
271 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700272 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
273 .format = PCM_FORMAT_S16_LE,
274};
275
Haynes Mathew George16081042017-05-31 17:16:49 -0700276struct pcm_config pcm_config_mmap_capture = {
277 .channels = 2,
278 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
279 .period_size = MMAP_PERIOD_SIZE,
280 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
281 .format = PCM_FORMAT_S16_LE,
282 .start_threshold = 0,
283 .stop_threshold = INT_MAX,
284 .silence_threshold = 0,
285 .silence_size = 0,
286 .avail_min = MMAP_PERIOD_SIZE, //1 ms
287};
288
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700289#define AFE_PROXY_CHANNEL_COUNT 2
290#define AFE_PROXY_SAMPLING_RATE 48000
291
292#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
293#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
294
295struct pcm_config pcm_config_afe_proxy_playback = {
296 .channels = AFE_PROXY_CHANNEL_COUNT,
297 .rate = AFE_PROXY_SAMPLING_RATE,
298 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
299 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
300 .format = PCM_FORMAT_S16_LE,
301 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
302 .stop_threshold = INT_MAX,
303 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
304};
305
306#define AFE_PROXY_RECORD_PERIOD_SIZE 768
307#define AFE_PROXY_RECORD_PERIOD_COUNT 4
308
Aalique Grahame22e49102018-12-18 14:23:57 -0800309struct pcm_config pcm_config_audio_capture_rt = {
310 .channels = 2,
311 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
312 .period_size = ULL_PERIOD_SIZE,
313 .period_count = 512,
314 .format = PCM_FORMAT_S16_LE,
315 .start_threshold = 0,
316 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
317 .silence_threshold = 0,
318 .silence_size = 0,
319 .avail_min = ULL_PERIOD_SIZE, //1 ms
320};
321
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +0530322struct pcm_config pcm_config_audio_capture_rt_48KHz = {
323 .channels = 2,
324 .rate = 48000,
325 .period_size = 48,
326 .period_count = 512,
327 .format = PCM_FORMAT_S16_LE,
328 .start_threshold = 0,
329 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
330 .silence_threshold = 0,
331 .silence_size = 0,
332 .avail_min = 48, //1 ms
333};
334struct pcm_config pcm_config_audio_capture_rt_32KHz = {
335 .channels = 2,
336 .rate = 32000,
337 .period_size = 32,
338 .period_count = 512,
339 .format = PCM_FORMAT_S16_LE,
340 .start_threshold = 0,
341 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
342 .silence_threshold = 0,
343 .silence_size = 0,
344 .avail_min = 32, //1 ms
345};
346struct pcm_config pcm_config_audio_capture_rt_24KHz = {
347 .channels = 2,
348 .rate = 24000,
349 .period_size = 24,
350 .period_count = 512,
351 .format = PCM_FORMAT_S16_LE,
352 .start_threshold = 0,
353 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
354 .silence_threshold = 0,
355 .silence_size = 0,
356 .avail_min = 24, //1 ms
357};
358struct pcm_config pcm_config_audio_capture_rt_16KHz = {
359 .channels = 2,
360 .rate = 16000,
361 .period_size = 16,
362 .period_count = 512,
363 .format = PCM_FORMAT_S16_LE,
364 .start_threshold = 0,
365 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
366 .silence_threshold = 0,
367 .silence_size = 0,
368 .avail_min = 16, //1 ms
369};
370struct pcm_config pcm_config_audio_capture_rt_8KHz = {
371 .channels = 2,
372 .rate = 8000,
373 .period_size = 8,
374 .period_count = 512,
375 .format = PCM_FORMAT_S16_LE,
376 .start_threshold = 0,
377 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
378 .silence_threshold = 0,
379 .silence_size = 0,
380 .avail_min = 8, //1 ms
381};
382
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700383struct pcm_config pcm_config_afe_proxy_record = {
384 .channels = AFE_PROXY_CHANNEL_COUNT,
385 .rate = AFE_PROXY_SAMPLING_RATE,
386 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
387 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
388 .format = PCM_FORMAT_S16_LE,
389 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
390 .stop_threshold = INT_MAX,
391 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
392};
393
Ashish Jainf1eaa582016-05-23 20:54:24 +0530394#define AUDIO_MAX_PCM_FORMATS 7
395
396const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
397 [AUDIO_FORMAT_DEFAULT] = 0,
398 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
399 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
400 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
401 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
402 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
403 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
404};
405
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800406const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700407 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
408 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800409 [USECASE_AUDIO_PLAYBACK_WITH_HAPTICS] = "audio-with-haptics-playback",
Meng Wang51d8c2a2020-04-27 15:23:21 +0800410 [USECASE_AUDIO_PLAYBACK_HAPTICS] = "haptics-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700411 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
412 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700413 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700414 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700415 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
416 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
417 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
418 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
419 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
420 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
421 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
422 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
Haynes Mathew George16081042017-05-31 17:16:49 -0700423 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
424 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700425 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Aalique Grahame22e49102018-12-18 14:23:57 -0800426 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
vivek mehta0ea887a2015-08-26 14:01:20 -0700427
Eric Laurentb23d5282013-05-14 15:27:20 -0700428 [USECASE_AUDIO_RECORD] = "audio-record",
Krishna Kishor Jha0f4d8482022-02-18 10:56:05 +0530429 [USECASE_AUDIO_RECORD2] = "audio-record2",
430 [USECASE_AUDIO_RECORD3] = "audio-record3",
Mingming Yine62d7842013-10-25 16:26:03 -0700431 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530432 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
433 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
434 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Dhananjay Kumar376e38b2017-09-28 22:26:23 +0530435 [USECASE_AUDIO_RECORD_COMPRESS5] = "audio-record-compress5",
436 [USECASE_AUDIO_RECORD_COMPRESS6] = "audio-record-compress6",
Eric Laurentb23d5282013-05-14 15:27:20 -0700437 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700438 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700439 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700440 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700441
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800442 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800443 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Derek Chenf7092792017-05-23 12:23:53 -0400444 [USECASE_AUDIO_HFP_SCO_DOWNLINK] = "hfp-sco-downlink",
445 [USECASE_AUDIO_HFP_SCO_WB_DOWNLINK] = "hfp-sco-wb-downlink",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700446
Derek Chenf7092792017-05-23 12:23:53 -0400447 [USECASE_VOICE_CALL] = "voice-call",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700448 [USECASE_VOICE2_CALL] = "voice2-call",
449 [USECASE_VOLTE_CALL] = "volte-call",
450 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800451 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800452 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
453 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800454 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700455 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
456 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
457 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800458 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
459 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
460 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
461
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700462 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
463 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700464 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
465 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700466
467 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
468 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Zhou Song62ea0282020-03-22 19:53:01 +0800469 [USECASE_AUDIO_RECORD_AFE_PROXY2] = "afe-proxy-record2",
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +0530470 [USECASE_AUDIO_PLAYBACK_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700471
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530472 /* Transcode loopback cases */
Surendar Karka93cd25a2018-08-28 14:21:37 +0530473 [USECASE_AUDIO_TRANSCODE_LOOPBACK_RX] = "audio-transcode-loopback-rx",
474 [USECASE_AUDIO_TRANSCODE_LOOPBACK_TX] = "audio-transcode-loopback-tx",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700475
476 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
477 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Revathi Uddarajud9f23d92020-07-27 10:55:06 +0530478 [USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY] = "audio-record-voip-low-latency",
Varun Balaraje49253e2017-07-06 19:48:56 +0530479 /* For Interactive Audio Streams */
480 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
481 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
482 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
483 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
484 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
485 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
486 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
487 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700488
Aniket Kumar Lata7fd86e12018-02-20 19:26:10 -0800489 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture",
490
Derek Chenf6318be2017-06-12 17:16:24 -0400491 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
492
493 [USECASE_AUDIO_PLAYBACK_MEDIA] = "media-playback",
494 [USECASE_AUDIO_PLAYBACK_SYS_NOTIFICATION] = "sys-notification-playback",
495 [USECASE_AUDIO_PLAYBACK_NAV_GUIDANCE] = "nav-guidance-playback",
496 [USECASE_AUDIO_PLAYBACK_PHONE] = "phone-playback",
Kogara Naveen Kumar65828fe2022-10-14 16:41:04 +0530497 [USECASE_AUDIO_PLAYBACK_PHONE_LL] = "phone-playback-ll",
Susan Wang117cf6f2022-04-06 20:11:46 -0400498 [USECASE_AUDIO_PLAYBACK_ALERTS] = "alerts-playback",
Derek Chen1bcdc6b2020-02-06 22:44:53 -0800499 [USECASE_AUDIO_PLAYBACK_FRONT_PASSENGER] = "front-passenger-playback",
Derek Chendf05eea2019-08-01 13:57:49 -0700500 [USECASE_AUDIO_PLAYBACK_REAR_SEAT] = "rear-seat-playback",
Rahul Sharma99770982019-03-06 17:05:26 +0530501 [USECASE_AUDIO_FM_TUNER_EXT] = "fm-tuner-ext",
Derek Chena30a5f42019-12-03 11:17:09 -0500502 [USECASE_ICC_CALL] = "icc-call",
Huicheng Liu1404ba12020-09-11 01:03:25 -0400503
504 [USECASE_AUDIO_RECORD_BUS] = "audio-record",
505 [USECASE_AUDIO_RECORD_BUS_FRONT_PASSENGER] = "front-passenger-record",
506 [USECASE_AUDIO_RECORD_BUS_REAR_SEAT] = "rear-seat-record",
Fei Tongaffdf732020-02-20 20:39:05 +0800507 [USECASE_AUDIO_PLAYBACK_SYNTHESIZER] = "synth-loopback",
Susan Wange3959562021-03-11 11:50:26 -0500508 [USECASE_AUDIO_RECORD_ECHO_REF_EXT] = "echo-reference-external",
Eric Laurentb23d5282013-05-14 15:27:20 -0700509};
510
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700511static const audio_usecase_t offload_usecases[] = {
512 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700513 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
514 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
515 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
516 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
517 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
518 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
519 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
520 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700521};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800522
Varun Balaraje49253e2017-07-06 19:48:56 +0530523static const audio_usecase_t interactive_usecases[] = {
524 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
525 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
526 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
527 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
528 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
529 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
530 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
531 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
532};
533
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800534#define STRING_TO_ENUM(string) { #string, string }
535
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800536struct string_to_enum {
537 const char *name;
538 uint32_t value;
539};
540
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700541static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800542 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800543 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
544 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
545 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700546 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800547 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
548 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800549 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700550 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
551 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
552 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
553 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
554 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
555 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
556 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
557 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
558 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
559 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
560 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800561};
562
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700563static const struct string_to_enum formats_name_to_enum_table[] = {
564 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
565 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
566 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700567 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
568 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
569 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700570 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800571 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
572 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700573 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800574};
575
576//list of all supported sample rates by HDMI specification.
577static const int out_hdmi_sample_rates[] = {
578 32000, 44100, 48000, 88200, 96000, 176400, 192000,
579};
580
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700581static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800582 STRING_TO_ENUM(32000),
583 STRING_TO_ENUM(44100),
584 STRING_TO_ENUM(48000),
585 STRING_TO_ENUM(88200),
586 STRING_TO_ENUM(96000),
587 STRING_TO_ENUM(176400),
588 STRING_TO_ENUM(192000),
Mingshu pange8aedf12019-10-25 15:38:27 +0800589 STRING_TO_ENUM(352800),
590 STRING_TO_ENUM(384000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700591};
592
Carter Hsu2e429db2019-05-14 18:50:52 +0800593struct in_effect_list {
594 struct listnode list;
595 effect_handle_t handle;
596};
597
Krishna Kishor Jha0f4d8482022-02-18 10:56:05 +0530598static const audio_usecase_t record_usecases[] = {
599 USECASE_AUDIO_RECORD,
600 USECASE_AUDIO_RECORD2,
601 USECASE_AUDIO_RECORD3,
602};
603
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700604static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700605static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700606static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700607//cache last MBDRC cal step level
608static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700609
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530610static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Arun Mirpuri5d170872019-03-26 13:21:31 -0700611static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800612static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530613static int out_set_pcm_volume(struct audio_stream_out *stream, float left, float right);
Krishna Kishor Jha10ad39f2022-02-21 17:02:47 +0530614#ifdef SOFT_VOLUME
615static int out_set_soft_volume_params(struct audio_stream_out *stream);
616#endif
Derek Chen6f293672019-04-01 01:40:24 -0700617static void adev_snd_mon_cb(void *cookie, struct str_parms *parms);
618static void in_snd_mon_cb(void * stream, struct str_parms * parms);
619static void out_snd_mon_cb(void * stream, struct str_parms * parms);
620
Zhou Song331c8e52019-08-26 14:16:12 +0800621static int configure_btsco_sample_rate(snd_device_t snd_device);
622
Vatsal Buchac09ae062018-11-14 13:25:08 +0530623#ifdef AUDIO_FEATURE_ENABLED_GCOV
624extern void __gcov_flush();
625static void enable_gcov()
626{
627 __gcov_flush();
628}
629#else
630static void enable_gcov()
631{
632}
633#endif
634
justinweng20fb6d82019-02-21 18:49:00 -0700635static int in_set_microphone_direction(const struct audio_stream_in *stream,
636 audio_microphone_direction_t dir);
637static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom);
638
Krishna Kishor Jha0f4d8482022-02-18 10:56:05 +0530639static bool is_pcm_record_usecase(audio_usecase_t uc_id)
640{
641 unsigned int record_uc_index;
642 unsigned int num_usecase = sizeof(record_usecases)/sizeof(record_usecases[0]);
643
644 for (record_uc_index = 0; record_uc_index < num_usecase; record_uc_index++) {
645 if (uc_id == record_usecases[record_uc_index])
646 return true;
647 }
648 return false;
649}
650
651static audio_usecase_t get_record_usecase(struct audio_device *adev)
652{
653 audio_usecase_t ret_uc = USECASE_INVALID;
654 unsigned int record_uc_index;
655 unsigned int num_usecase = sizeof(record_usecases)/sizeof(record_usecases[0]);
656
657 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
658 for (record_uc_index = 0; record_uc_index < num_usecase; record_uc_index++) {
659 if (!(adev->pcm_record_uc_state & (0x1 << record_uc_index))) {
660 adev->pcm_record_uc_state |= 0x1 << record_uc_index;
661 ret_uc = record_usecases[record_uc_index];
662 break;
663 }
664 }
665
666 ALOGV("%s: pcm record usecase is %d", __func__, ret_uc);
667 return ret_uc;
668}
669
670static void free_record_usecase(struct audio_device *adev,
671 audio_usecase_t uc_id)
672{
673 unsigned int record_uc_index;
674 unsigned int num_usecase = sizeof(record_usecases)/sizeof(record_usecases[0]);
675
676 for (record_uc_index = 0; record_uc_index < num_usecase; record_uc_index++) {
677 if (record_usecases[record_uc_index] == uc_id) {
678 adev->pcm_record_uc_state &= ~(0x1 << record_uc_index);
679 break;
680 }
681 }
682 ALOGV("%s: free pcm record usecase %d", __func__, uc_id);
683}
684
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700685static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
686 int flags __unused)
687{
688 int dir = 0;
689 switch (uc_id) {
690 case USECASE_AUDIO_RECORD_LOW_LATENCY:
Revathi Uddarajud9f23d92020-07-27 10:55:06 +0530691 case USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY:
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700692 dir = 1;
693 case USECASE_AUDIO_PLAYBACK_ULL:
694 break;
695 default:
696 return false;
697 }
698
699 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
700 PCM_PLAYBACK : PCM_CAPTURE);
701 if (adev->adm_is_noirq_avail)
702 return adev->adm_is_noirq_avail(adev->adm_data,
703 adev->snd_card, dev_id, dir);
704 return false;
705}
706
707static void register_out_stream(struct stream_out *out)
708{
709 struct audio_device *adev = out->dev;
710 if (is_offload_usecase(out->usecase) ||
711 !adev->adm_register_output_stream)
712 return;
713
714 // register stream first for backward compatibility
715 adev->adm_register_output_stream(adev->adm_data,
716 out->handle,
717 out->flags);
718
719 if (!adev->adm_set_config)
720 return;
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +0530721#ifdef PLATFORM_AUTO
Kogara Naveen Kumar6db5fb02022-05-07 00:22:50 +0530722 if (out->realtime || (out->flags & AUDIO_OUTPUT_FLAG_SYS_NOTIFICATION))
723 adev->adm_set_config(adev->adm_data,
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700724 out->handle,
725 out->pcm, &out->config);
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +0530726#else
727 if (out->realtime)
728 adev->adm_set_config(adev->adm_data,
729 out->handle,
730 out->pcm, &out->config);
731#endif
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700732}
733
734static void register_in_stream(struct stream_in *in)
735{
736 struct audio_device *adev = in->dev;
737 if (!adev->adm_register_input_stream)
738 return;
739
740 adev->adm_register_input_stream(adev->adm_data,
741 in->capture_handle,
742 in->flags);
743
744 if (!adev->adm_set_config)
745 return;
746
747 if (in->realtime)
748 adev->adm_set_config(adev->adm_data,
749 in->capture_handle,
750 in->pcm,
751 &in->config);
752}
753
754static void request_out_focus(struct stream_out *out, long ns)
755{
756 struct audio_device *adev = out->dev;
757
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700758 if (adev->adm_request_focus_v2)
759 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
760 else if (adev->adm_request_focus)
761 adev->adm_request_focus(adev->adm_data, out->handle);
762}
763
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700764static int request_in_focus(struct stream_in *in, long ns)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700765{
766 struct audio_device *adev = in->dev;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700767 int ret = 0;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700768
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700769 if (adev->adm_request_focus_v2_1)
770 ret = adev->adm_request_focus_v2_1(adev->adm_data, in->capture_handle, ns);
771 else if (adev->adm_request_focus_v2)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700772 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
773 else if (adev->adm_request_focus)
774 adev->adm_request_focus(adev->adm_data, in->capture_handle);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700775
776 return ret;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700777}
778
779static void release_out_focus(struct stream_out *out)
780{
781 struct audio_device *adev = out->dev;
782
783 if (adev->adm_abandon_focus)
784 adev->adm_abandon_focus(adev->adm_data, out->handle);
785}
786
787static void release_in_focus(struct stream_in *in)
788{
789 struct audio_device *adev = in->dev;
790 if (adev->adm_abandon_focus)
791 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
792}
793
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530794static int parse_snd_card_status(struct str_parms *parms, int *card,
795 card_status_t *status)
796{
797 char value[32]={0};
798 char state[32]={0};
799
800 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
801 if (ret < 0)
802 return -1;
803
804 // sscanf should be okay as value is of max length 32.
805 // same as sizeof state.
806 if (sscanf(value, "%d,%s", card, state) < 2)
807 return -1;
808
809 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
810 CARD_STATUS_OFFLINE;
811 return 0;
812}
813
Avinash Chandrad7296d42021-08-04 15:07:47 +0530814bool is_combo_audio_input_device(struct listnode *devices){
815
Sandhya Mutha Naga Venkata153d95e2022-07-12 14:54:43 +0530816 if ((devices == NULL) || (!list_empty(devices)))
Avinash Chandrad7296d42021-08-04 15:07:47 +0530817 return false;
818
819 if(compare_device_type(devices, AUDIO_DEVICE_IN_BUILTIN_MIC|AUDIO_DEVICE_IN_SPEAKER_MIC2))
820 return true;
821 else
822 return false;
823}
824
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700825static inline void adjust_frames_for_device_delay(struct stream_out *out,
826 uint32_t *dsp_frames) {
827 // Adjustment accounts for A2dp encoder latency with offload usecases
828 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -0800829 if (is_a2dp_out_device_type(&out->device_list)) {
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700830 unsigned long offset =
831 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
832 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
833 }
834}
835
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700836static inline bool free_entry(void *key __unused,
837 void *value, void *context __unused)
838{
839 free(value);
840 return true;
841}
842
843static inline void free_map(Hashmap *map)
844{
845 if (map) {
846 hashmapForEach(map, free_entry, (void *) NULL);
847 hashmapFree(map);
848 }
849}
850
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800851static inline void patch_map_remove_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700852 audio_patch_handle_t patch_handle)
853{
854 if (patch_handle == AUDIO_PATCH_HANDLE_NONE)
855 return;
856
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700857 struct audio_patch_info *p_info =
858 hashmapGet(adev->patch_map, (void *) (intptr_t) patch_handle);
859 if (p_info) {
860 ALOGV("%s: Remove patch %d", __func__, patch_handle);
861 hashmapRemove(adev->patch_map, (void *) (intptr_t) patch_handle);
862 free(p_info->patch);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700863 free(p_info);
864 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700865}
866
867static inline int io_streams_map_insert(struct audio_device *adev,
868 struct audio_stream *stream,
869 audio_io_handle_t handle,
870 audio_patch_handle_t patch_handle)
871{
872 struct audio_stream_info *s_info =
873 (struct audio_stream_info *) calloc(1, sizeof(struct audio_stream_info));
874
875 if (s_info == NULL) {
876 ALOGE("%s: Could not allocate stream info", __func__);
877 return -ENOMEM;
878 }
879 s_info->stream = stream;
880 s_info->patch_handle = patch_handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700881
882 pthread_mutex_lock(&adev->lock);
883 struct audio_stream_info *stream_info =
884 hashmapPut(adev->io_streams_map, (void *) (intptr_t) handle, (void *) s_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700885 if (stream_info != NULL)
886 free(stream_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800887 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Latad13758f2020-08-06 15:11:36 -0700888 ALOGV("%s: Added stream in io_streams_map with handle %d", __func__, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700889 return 0;
890}
891
892static inline void io_streams_map_remove(struct audio_device *adev,
893 audio_io_handle_t handle)
894{
895 pthread_mutex_lock(&adev->lock);
896 struct audio_stream_info *s_info =
897 hashmapRemove(adev->io_streams_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700898 if (s_info == NULL)
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800899 goto done;
Aniket Kumar Latad13758f2020-08-06 15:11:36 -0700900 ALOGV("%s: Removed stream with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800901 patch_map_remove_l(adev, s_info->patch_handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700902 free(s_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800903done:
904 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700905 return;
906}
907
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800908static struct audio_patch_info* fetch_patch_info_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700909 audio_patch_handle_t handle)
910{
911 struct audio_patch_info *p_info = NULL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700912 p_info = (struct audio_patch_info *)
913 hashmapGet(adev->patch_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700914 return p_info;
915}
916
vivek mehtaa76401a2015-04-24 14:12:15 -0700917__attribute__ ((visibility ("default")))
918bool audio_hw_send_gain_dep_calibration(int level) {
919 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700920 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700921
922 pthread_mutex_lock(&adev_init_lock);
923
924 if (adev != NULL && adev->platform != NULL) {
925 pthread_mutex_lock(&adev->lock);
926 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700927
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530928 // cache level info for any of the use case which
929 // was not started.
930 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700931
vivek mehtaa76401a2015-04-24 14:12:15 -0700932 pthread_mutex_unlock(&adev->lock);
933 } else {
934 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
935 }
936
937 pthread_mutex_unlock(&adev_init_lock);
938
939 return ret_val;
940}
941
Ashish Jain5106d362016-05-11 19:23:33 +0530942static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
943{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800944 bool gapless_enabled = false;
945 const char *mixer_ctl_name = "Compress Gapless Playback";
946 struct mixer_ctl *ctl;
947
948 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700949 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530950
951 /*Disable gapless if its AV playback*/
952 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800953
954 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
955 if (!ctl) {
956 ALOGE("%s: Could not get ctl for mixer cmd - %s",
957 __func__, mixer_ctl_name);
958 return -EINVAL;
959 }
960
961 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
962 ALOGE("%s: Could not set gapless mode %d",
963 __func__, gapless_enabled);
964 return -EINVAL;
965 }
966 return 0;
967}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700968
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700969__attribute__ ((visibility ("default")))
970int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
971 int table_size) {
972 int ret_val = 0;
973 ALOGV("%s: enter ... ", __func__);
974
975 pthread_mutex_lock(&adev_init_lock);
976 if (adev == NULL) {
977 ALOGW("%s: adev is NULL .... ", __func__);
978 goto done;
979 }
980
981 pthread_mutex_lock(&adev->lock);
982 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
983 pthread_mutex_unlock(&adev->lock);
984done:
985 pthread_mutex_unlock(&adev_init_lock);
986 ALOGV("%s: exit ... ", __func__);
987 return ret_val;
988}
989
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800990bool audio_hw_send_qdsp_parameter(int stream_type, float vol, bool active)
Aalique Grahame22e49102018-12-18 14:23:57 -0800991{
992 bool ret = false;
993 ALOGV("%s: enter ...", __func__);
994
995 pthread_mutex_lock(&adev_init_lock);
996
997 if (adev != NULL && adev->platform != NULL) {
998 pthread_mutex_lock(&adev->lock);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800999 ret = audio_extn_qdsp_set_state(adev, stream_type, vol, active);
Aalique Grahame22e49102018-12-18 14:23:57 -08001000 pthread_mutex_unlock(&adev->lock);
1001 }
1002
1003 pthread_mutex_unlock(&adev_init_lock);
1004
1005 ALOGV("%s: exit with ret %d", __func__, ret);
1006 return ret;
1007}
Aalique Grahame22e49102018-12-18 14:23:57 -08001008
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001009static bool is_supported_format(audio_format_t format)
1010{
Eric Laurent86e17132013-09-12 17:49:30 -07001011 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +05301012 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +05301013 format == AUDIO_FORMAT_AAC_LC ||
1014 format == AUDIO_FORMAT_AAC_HE_V1 ||
1015 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +05301016 format == AUDIO_FORMAT_AAC_ADTS_LC ||
1017 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
1018 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05301019 format == AUDIO_FORMAT_AAC_LATM_LC ||
1020 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
1021 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +05301022 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
1023 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +05301024 format == AUDIO_FORMAT_PCM_FLOAT ||
1025 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -07001026 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301027 format == AUDIO_FORMAT_AC3 ||
1028 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -07001029 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301030 format == AUDIO_FORMAT_DTS ||
1031 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001032 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301033 format == AUDIO_FORMAT_ALAC ||
1034 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301035 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301036 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001037 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05301038 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07001039 format == AUDIO_FORMAT_APTX ||
1040 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08001041 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001042
1043 return false;
1044}
1045
Kunlei Zhang67cc7072020-12-18 17:16:49 +08001046static bool is_supported_conc_usecase_for_power_mode_call(struct audio_device *adev)
1047{
1048 struct listnode *node;
1049 struct audio_usecase *usecase;
1050
1051 list_for_each(node, &adev->usecase_list) {
1052 usecase = node_to_item(node, struct audio_usecase, list);
1053 if (usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1054 ALOGD("%s: FM usecase is active, not setting power mode", __func__);
1055 return false;
1056 }
1057 }
1058
1059 return true;
1060}
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001061static inline bool is_mmap_usecase(audio_usecase_t uc_id)
1062{
1063 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
Zhou Song62ea0282020-03-22 19:53:01 +08001064 (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY2) ||
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001065 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
1066}
1067
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07001068static inline bool is_valid_volume(float left, float right)
1069{
1070 return ((left >= 0.0f && right >= 0.0f) ? true : false);
1071}
1072
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301073static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301074{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301075 ALOGV("%s", __func__);
1076 audio_route_apply_and_update_path(adev->audio_route,
1077 "asrc-mode");
1078 adev->asrc_mode_enabled = true;
1079}
1080
1081static void disable_asrc_mode(struct audio_device *adev)
1082{
1083 ALOGV("%s", __func__);
1084 audio_route_reset_and_update_path(adev->audio_route,
1085 "asrc-mode");
1086 adev->asrc_mode_enabled = false;
1087}
1088
Saurav Kumarc1411662020-10-14 10:50:45 +05301089static void check_and_configure_headphone(struct audio_device *adev,
1090 struct audio_usecase *uc_info,
1091 snd_device_t snd_device)
1092{
1093 struct listnode *node;
1094 struct audio_usecase *usecase;
1095 int new_backend_idx, usecase_backend_idx;
1096 bool spkr_hph_single_be_native_concurrency;
1097
1098 new_backend_idx = platform_get_backend_index(snd_device);
1099 spkr_hph_single_be_native_concurrency = platform_get_spkr_hph_single_be_native_concurrency_flag();
Zhou Songd4b18c42021-01-14 15:15:29 +08001100 if ((spkr_hph_single_be_native_concurrency && (new_backend_idx == DEFAULT_CODEC_BACKEND)) ||
1101 uc_info->id == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
Saurav Kumarc1411662020-10-14 10:50:45 +05301102 list_for_each(node, &adev->usecase_list) {
1103 usecase = node_to_item(node, struct audio_usecase, list);
1104 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
1105 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
1106 if (((usecase_backend_idx == HEADPHONE_BACKEND) ||
1107 (usecase_backend_idx == HEADPHONE_44_1_BACKEND)) &&
1108 ((usecase->stream.out->sample_rate % OUTPUT_SAMPLING_RATE_44100) == 0)) {
1109 disable_audio_route(adev, usecase);
1110 disable_snd_device(adev, usecase->out_snd_device);
1111 usecase->stream.out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Saurav Kumar70902382020-10-28 11:16:04 +05301112 platform_check_and_set_codec_backend_cfg(adev, usecase,
1113 usecase->out_snd_device);
Saurav Kumarc1411662020-10-14 10:50:45 +05301114 enable_snd_device(adev, usecase->out_snd_device);
Zhou Songd4b18c42021-01-14 15:15:29 +08001115 enable_audio_route(adev, usecase);
Saurav Kumarc1411662020-10-14 10:50:45 +05301116 }
1117 }
Revathi Uddaraju2c0eac02021-07-27 02:06:42 -07001118 else if ((usecase->type != PCM_CAPTURE) && (usecase == uc_info)) {
1119 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
1120 if (((usecase_backend_idx == HEADPHONE_BACKEND) ||
1121 (usecase_backend_idx == HEADPHONE_44_1_BACKEND)) &&
1122 ((usecase->stream.out->sample_rate % OUTPUT_SAMPLING_RATE_44100) == 0)) {
1123 usecase->stream.out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1124 platform_check_and_set_codec_backend_cfg(adev, usecase,
1125 usecase->out_snd_device);
1126 }
1127 }
Saurav Kumarc1411662020-10-14 10:50:45 +05301128 }
1129 }
1130}
1131
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301132/*
1133 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
1134 * 44.1 or Native DSD backends are enabled for any of current use case.
1135 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
1136 * - Disable current mix path use case(Headphone backend) and re-enable it with
1137 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
1138 * e.g. Naitve DSD or Headphone 44.1 -> + 48
1139 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301140static void check_and_set_asrc_mode(struct audio_device *adev,
1141 struct audio_usecase *uc_info,
1142 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301143{
1144 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301145 int i, num_new_devices = 0;
1146 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
1147 /*
1148 *Split snd device for new combo use case
1149 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
1150 */
1151 if (platform_split_snd_device(adev->platform,
1152 snd_device,
1153 &num_new_devices,
1154 split_new_snd_devices) == 0) {
1155 for (i = 0; i < num_new_devices; i++)
1156 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
1157 } else {
1158 int new_backend_idx = platform_get_backend_index(snd_device);
1159 if (((new_backend_idx == HEADPHONE_BACKEND) ||
1160 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
1161 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
1162 !adev->asrc_mode_enabled) {
1163 struct listnode *node = NULL;
1164 struct audio_usecase *uc = NULL;
1165 struct stream_out *curr_out = NULL;
1166 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
1167 int i, num_devices, ret = 0;
1168 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301169
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301170 list_for_each(node, &adev->usecase_list) {
1171 uc = node_to_item(node, struct audio_usecase, list);
1172 curr_out = (struct stream_out*) uc->stream.out;
1173 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
1174 /*
1175 *Split snd device for existing combo use case
1176 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
1177 */
1178 ret = platform_split_snd_device(adev->platform,
1179 uc->out_snd_device,
1180 &num_devices,
1181 split_snd_devices);
1182 if (ret < 0 || num_devices == 0) {
1183 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
1184 split_snd_devices[0] = uc->out_snd_device;
1185 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -08001186 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301187 for (i = 0; i < num_devices; i++) {
1188 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
1189 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
1190 if((new_backend_idx == HEADPHONE_BACKEND) &&
1191 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
1192 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07001193 ALOGV("%s:DSD or native stream detected enabling asrcmode in hardware",
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301194 __func__);
1195 enable_asrc_mode(adev);
1196 break;
1197 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
1198 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
1199 (usecase_backend_idx == HEADPHONE_BACKEND)) {
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07001200 ALOGV("%s: 48K stream detected, disabling and enabling it \
1201 with asrcmode in hardware", __func__);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301202 disable_audio_route(adev, uc);
1203 disable_snd_device(adev, uc->out_snd_device);
1204 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
1205 if (new_backend_idx == DSD_NATIVE_BACKEND)
1206 audio_route_apply_and_update_path(adev->audio_route,
1207 "hph-true-highquality-mode");
1208 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
1209 (curr_out->bit_width >= 24))
1210 audio_route_apply_and_update_path(adev->audio_route,
1211 "hph-highquality-mode");
1212 enable_asrc_mode(adev);
1213 enable_snd_device(adev, uc->out_snd_device);
1214 enable_audio_route(adev, uc);
1215 break;
1216 }
1217 }
1218 // reset split devices count
1219 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -08001220 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301221 if (adev->asrc_mode_enabled)
1222 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301223 }
1224 }
1225 }
1226}
1227
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001228static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
1229 struct audio_effect_config effect_config,
1230 unsigned int param_value)
1231{
1232 char mixer_ctl_name[] = "Audio Effect";
1233 struct mixer_ctl *ctl;
1234 long set_values[6];
Eric Laurent637e2d42018-11-15 12:24:31 -08001235 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001236
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001237 if (in == NULL) {
1238 ALOGE("%s: active input stream is NULL", __func__);
1239 return -EINVAL;
1240 }
1241
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001242 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1243 if (!ctl) {
1244 ALOGE("%s: Could not get mixer ctl - %s",
1245 __func__, mixer_ctl_name);
1246 return -EINVAL;
1247 }
1248
1249 set_values[0] = 1; //0:Rx 1:Tx
1250 set_values[1] = in->app_type_cfg.app_type;
1251 set_values[2] = (long)effect_config.module_id;
1252 set_values[3] = (long)effect_config.instance_id;
1253 set_values[4] = (long)effect_config.param_id;
1254 set_values[5] = param_value;
1255
1256 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
1257
1258 return 0;
1259
1260}
1261
1262static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
1263 int effect_type, unsigned int *param_value)
1264{
1265 int ret = 0;
1266 struct audio_effect_config other_effect_config;
1267 struct audio_usecase *usecase = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08001268 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001269
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001270 if (in == NULL) {
1271 ALOGE("%s: active input stream is NULL", __func__);
1272 return -EINVAL;
1273 }
1274
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001275 usecase = get_usecase_from_list(adev, in->usecase);
1276 if (!usecase)
1277 return -EINVAL;
1278
1279 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
1280 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
1281 if (ret < 0) {
1282 ALOGE("%s Failed to get effect params %d", __func__, ret);
1283 return ret;
1284 }
1285
1286 if (module_id == other_effect_config.module_id) {
1287 //Same module id for AEC/NS. Values need to be combined
1288 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
1289 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
1290 *param_value |= other_effect_config.param_value;
1291 }
1292 }
1293
1294 return ret;
1295}
1296
1297static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
Gangadhar Sb0210342019-02-22 17:39:41 +05301298{
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001299 struct audio_effect_config effect_config;
1300 struct audio_usecase *usecase = NULL;
1301 int ret = 0;
1302 unsigned int param_value = 0;
Eric Laurent637e2d42018-11-15 12:24:31 -08001303 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001304
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001305 if(!voice_extn_is_dynamic_ecns_enabled())
1306 return ENOSYS;
1307
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001308 if (!in) {
1309 ALOGE("%s: Invalid input stream", __func__);
1310 return -EINVAL;
1311 }
1312
1313 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
1314
1315 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +08001316 if (usecase == NULL) {
1317 ALOGE("%s: Could not find the usecase (%d) in the list",
1318 __func__, in->usecase);
1319 return -EINVAL;
1320 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001321
1322 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
1323 if (ret < 0) {
1324 ALOGE("%s Failed to get module id %d", __func__, ret);
1325 return ret;
1326 }
1327 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
1328 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
1329
1330 if(enable)
1331 param_value = effect_config.param_value;
1332
1333 /*Special handling for AEC & NS effects Param values need to be
1334 updated if module ids are same*/
1335
1336 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
1337 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
1338 if (ret < 0)
1339 return ret;
1340 }
1341
1342 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
1343
1344 return ret;
1345}
1346
1347static void check_and_enable_effect(struct audio_device *adev)
1348{
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001349 if(!voice_extn_is_dynamic_ecns_enabled())
1350 return;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001351
Eric Laurent637e2d42018-11-15 12:24:31 -08001352 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001353
Eric Laurent637e2d42018-11-15 12:24:31 -08001354 if (in != NULL && !in->standby) {
1355 if (in->enable_aec)
1356 enable_disable_effect(adev, EFFECT_AEC, true);
1357
1358 if (in->enable_ns &&
1359 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1360 enable_disable_effect(adev, EFFECT_NS, true);
1361 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001362 }
1363}
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001364
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001365int pcm_ioctl(struct pcm *pcm, int request, ...)
1366{
1367 va_list ap;
1368 void * arg;
1369 int pcm_fd = *(int*)pcm;
1370
1371 va_start(ap, request);
1372 arg = va_arg(ap, void *);
1373 va_end(ap);
1374
1375 return ioctl(pcm_fd, request, arg);
1376}
1377
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001378int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001379 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001380{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001381 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001382 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +05301383 struct stream_out *out = NULL;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301384 struct stream_in *in = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001385 struct listnode out_devices;
Soumya Managoli6993b762018-06-28 16:04:57 +05301386 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001387
1388 if (usecase == NULL)
1389 return -EINVAL;
1390
1391 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
1392
Carter Hsu2e429db2019-05-14 18:50:52 +08001393 if (usecase->type == PCM_CAPTURE) {
1394 struct stream_in *in = usecase->stream.in;
1395 struct audio_usecase *uinfo;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001396 snd_device = usecase->in_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001397
1398 if (in) {
1399 if (in->enable_aec || in->enable_ec_port) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001400 list_init(&out_devices);
1401 update_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "", true);
Carter Hsu2e429db2019-05-14 18:50:52 +08001402 struct listnode *node;
1403 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1404 USECASE_AUDIO_PLAYBACK_VOIP);
1405 if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001406 assign_devices(&out_devices,
1407 &voip_usecase->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001408 } else if (adev->primary_output &&
1409 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001410 assign_devices(&out_devices,
1411 &adev->primary_output->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001412 } else {
1413 list_for_each(node, &adev->usecase_list) {
1414 uinfo = node_to_item(node, struct audio_usecase, list);
1415 if (uinfo->type != PCM_CAPTURE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001416 assign_devices(&out_devices,
1417 &uinfo->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001418 break;
1419 }
1420 }
1421 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001422
1423 platform_set_echo_reference(adev, true, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001424 in->ec_opened = true;
Zhenlin Lian4f947842022-05-14 15:50:52 +05301425 clear_devices(&out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001426 }
1427 }
Guodong Huf5e614d2019-06-24 18:42:03 +08001428 } else if ((usecase->type == TRANSCODE_LOOPBACK_TX) || ((usecase->type == PCM_HFP_CALL) &&
1429 ((usecase->id == USECASE_AUDIO_HFP_SCO) || (usecase->id == USECASE_AUDIO_HFP_SCO_WB)) &&
1430 (usecase->in_snd_device == SND_DEVICE_IN_VOICE_SPEAKER_MIC_HFP_MMSECNS))) {
Carter Hsu2e429db2019-05-14 18:50:52 +08001431 snd_device = usecase->in_snd_device;
1432 } else {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001433 snd_device = usecase->out_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001434 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001435
Kunlei Zhanga3c4cb02021-03-05 16:03:54 +08001436 if (usecase->type == PCM_CAPTURE) {
1437 if (platform_get_fluence_nn_state(adev->platform) == 0) {
1438 platform_set_fluence_nn_state(adev->platform, true);
1439 ALOGD("%s: set fluence nn capture state", __func__);
1440 }
1441 }
1442
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001443#ifdef DS1_DOLBY_DAP_ENABLED
1444 audio_extn_dolby_set_dmid(adev);
1445 audio_extn_dolby_set_endpoint(adev);
1446#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001447 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001448 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301449 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001450 audio_extn_utils_send_app_type_cfg(adev, usecase);
Jasmine Cha4dcc1092019-03-04 18:12:47 +08001451 if (audio_extn_is_maxx_audio_enabled())
1452 audio_extn_ma_set_device(usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301453 audio_extn_utils_send_audio_calibration(adev, usecase);
Zhou Songbaddf9f2020-11-20 13:57:39 +08001454 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1455 out = usecase->stream.out;
1456 if (out && out->compr)
Manish Dewangan58229382017-02-02 15:48:41 +05301457 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1458 }
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301459
1460 if (usecase->type == PCM_CAPTURE) {
Kunlei Zhanga3c4cb02021-03-05 16:03:54 +08001461 if (platform_get_fluence_nn_state(adev->platform) == 1 &&
1462 adev->fluence_nn_usecase_id == USECASE_INVALID ) {
1463 adev->fluence_nn_usecase_id = usecase->id;
1464 ALOGD("%s: assign fluence nn usecase %d", __func__, usecase->id);
1465 }
1466 }
1467
1468 if (usecase->type == PCM_CAPTURE) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301469 in = usecase->stream.in;
Avinash Chandrad7296d42021-08-04 15:07:47 +05301470 if ((in && is_loopback_input_device(get_device_types(&in->device_list))) ||
1471 (in && is_combo_audio_input_device(&in->device_list)) ||
1472 (in && ((compare_device_type(&in->device_list, AUDIO_DEVICE_IN_BUILTIN_MIC) ||
1473 compare_device_type(&in->device_list, AUDIO_DEVICE_IN_LINE)) &&
1474 (snd_device == SND_DEVICE_IN_HANDSET_GENERIC_6MIC)))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301475 ALOGD("%s: set custom mtmx params v1", __func__);
1476 audio_extn_set_custom_mtmx_params_v1(adev, usecase, true);
1477 }
1478 } else {
1479 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
1480 }
Manish Dewangan58229382017-02-02 15:48:41 +05301481
Andy Hung756ecc12018-10-19 17:47:12 -07001482 // we shouldn't truncate mixer_path
1483 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1484 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1485 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001486 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001487 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301488 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1489 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1490 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1491 if (parms) {
1492 audio_extn_fm_set_parameters(adev, parms);
1493 str_parms_destroy(parms);
1494 }
1495 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001496 ALOGV("%s: exit", __func__);
1497 return 0;
1498}
1499
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001500int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001501 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001502{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001503 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001504 char mixer_path[MIXER_PATH_MAX_LENGTH];
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301505 struct stream_in *in = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001506
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301507 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001508 return -EINVAL;
1509
1510 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301511 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001512 snd_device = usecase->in_snd_device;
1513 else
1514 snd_device = usecase->out_snd_device;
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001515
1516 /* disable island and power mode on supported device for voice call */
1517 if (usecase->type == VOICE_CALL) {
1518 if (usecase->in_snd_device != SND_DEVICE_NONE) {
1519 if (platform_get_island_cfg_on_device(adev->platform, usecase->in_snd_device) &&
1520 platform_get_power_mode_on_device(adev->platform, usecase->in_snd_device)) {
1521 platform_set_island_cfg_on_device(adev, usecase->in_snd_device, false);
1522 platform_set_power_mode_on_device(adev, usecase->in_snd_device, false);
1523 platform_reset_island_power_status(adev->platform, usecase->in_snd_device);
Kunlei Zhang91c4b332020-07-20 17:53:14 +08001524 if (voice_is_lte_call_active(adev))
1525 platform_set_tx_lpi_mode(adev->platform, false);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001526 ALOGD("%s: disable island cfg and power mode in voice tx path",
1527 __func__);
1528 }
1529 }
1530 if (usecase->out_snd_device != SND_DEVICE_NONE) {
1531 if (platform_get_island_cfg_on_device(adev->platform, usecase->out_snd_device) &&
1532 platform_get_power_mode_on_device(adev->platform, usecase->out_snd_device)) {
1533 platform_set_island_cfg_on_device(adev, usecase->out_snd_device, false);
1534 platform_set_power_mode_on_device(adev, usecase->out_snd_device, false);
1535 platform_reset_island_power_status(adev->platform, usecase->out_snd_device);
1536 ALOGD("%s: disable island cfg and power mode in voice rx path",
1537 __func__);
1538 }
1539 }
1540 }
1541
Andy Hung756ecc12018-10-19 17:47:12 -07001542 // we shouldn't truncate mixer_path
1543 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1544 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1545 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001546 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001547 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001548 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Carter Hsu2e429db2019-05-14 18:50:52 +08001549 if (usecase->type == PCM_CAPTURE) {
1550 struct stream_in *in = usecase->stream.in;
1551 if (in && in->ec_opened) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001552 struct listnode out_devices;
1553 list_init(&out_devices);
1554 platform_set_echo_reference(in->dev, false, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001555 in->ec_opened = false;
Zhenlin Lian4f947842022-05-14 15:50:52 +05301556 clear_devices(&out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001557 }
1558 }
Kunlei Zhanga3c4cb02021-03-05 16:03:54 +08001559 if (usecase->id == adev->fluence_nn_usecase_id) {
1560 platform_set_fluence_nn_state(adev->platform, false);
1561 adev->fluence_nn_usecase_id = USECASE_INVALID;
1562 ALOGD("%s: reset fluence nn capture state", __func__);
1563 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001564 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301565 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301566
1567 if (usecase->type == PCM_CAPTURE) {
1568 in = usecase->stream.in;
Avinash Chandrad7296d42021-08-04 15:07:47 +05301569 if ((in && is_loopback_input_device(get_device_types(&in->device_list))) ||
1570 (in && is_combo_audio_input_device(&in->device_list)) ||
1571 (in && ((compare_device_type(&in->device_list, AUDIO_DEVICE_IN_BUILTIN_MIC) ||
1572 compare_device_type(&in->device_list, AUDIO_DEVICE_IN_LINE)) &&
1573 (snd_device == SND_DEVICE_IN_HANDSET_GENERIC_6MIC)))){
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301574 ALOGD("%s: reset custom mtmx params v1", __func__);
1575 audio_extn_set_custom_mtmx_params_v1(adev, usecase, false);
1576 }
1577 } else {
1578 audio_extn_set_custom_mtmx_params_v2(adev, usecase, false);
1579 }
1580
Weiyin Jiang298ffd92019-06-03 14:29:30 +08001581 if ((usecase->type == PCM_PLAYBACK) &&
1582 (usecase->stream.out != NULL))
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05301583 usecase->stream.out->pspd_coeff_sent = false;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301584
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001585 ALOGV("%s: exit", __func__);
1586 return 0;
1587}
1588
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001589int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001590 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001591{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301592 int i, num_devices = 0;
1593 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001594 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1595
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001596 if (snd_device < SND_DEVICE_MIN ||
1597 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001598 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001599 return -EINVAL;
1600 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001601
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001602 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001603 ALOGE("%s: Invalid sound device returned", __func__);
1604 return -EINVAL;
1605 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001606
1607 adev->snd_dev_ref_cnt[snd_device]++;
1608
1609 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1610 (platform_split_snd_device(adev->platform,
1611 snd_device,
1612 &num_devices,
1613 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001614 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001615 __func__, snd_device, device_name);
Aniket Kumar Lata990de552019-07-11 14:20:23 -07001616 /* Set backend config for A2DP to ensure slimbus configuration
1617 is correct if A2DP is already active and backend is closed
1618 and re-opened */
1619 if (snd_device == SND_DEVICE_OUT_BT_A2DP)
1620 audio_extn_a2dp_set_source_backend_cfg();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001621 return 0;
1622 }
1623
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001624 if (audio_extn_spkr_prot_is_enabled())
1625 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001626
Aalique Grahame22e49102018-12-18 14:23:57 -08001627 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1628
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001629 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1630 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001631 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1632 goto err;
1633 }
1634 audio_extn_dev_arbi_acquire(snd_device);
1635 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001636 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001637 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001638 goto err;
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001639 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001640 } else if (platform_split_snd_device(adev->platform,
1641 snd_device,
1642 &num_devices,
1643 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301644 for (i = 0; i < num_devices; i++) {
1645 enable_snd_device(adev, new_snd_devices[i]);
1646 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001647 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001648 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001649 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301650
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001651 /* enable island and power mode on supported device */
1652 if (platform_get_island_cfg_on_device(adev->platform, snd_device) &&
1653 platform_get_power_mode_on_device(adev->platform, snd_device)) {
1654 platform_set_island_cfg_on_device(adev, snd_device, true);
1655 platform_set_power_mode_on_device(adev, snd_device, true);
Kunlei Zhang91c4b332020-07-20 17:53:14 +08001656 if (voice_is_lte_call_active(adev) &&
1657 (snd_device >= SND_DEVICE_IN_BEGIN &&
1658 snd_device < SND_DEVICE_IN_END))
1659 platform_set_tx_lpi_mode(adev->platform, true);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001660 ALOGD("%s: enable island cfg and power mode on: %s",
1661 __func__, device_name);
1662 }
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301663
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301664 if (SND_DEVICE_OUT_BT_A2DP == snd_device) {
Ramjee Singh2d2944a2021-12-14 14:13:41 +05301665
1666 struct audio_usecase *usecase;
1667 struct listnode *node;
1668 /* Disable SCO Devices and enable handset mic for active input stream */
1669 list_for_each(node, &adev->usecase_list) {
1670 usecase = node_to_item(node, struct audio_usecase, list);
1671 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
1672 is_sco_in_device_type(&usecase->stream.in->device_list)) {
1673 ALOGD("a2dp resumed, switch bt sco mic to handset mic");
1674 reassign_device_list(&usecase->stream.in->device_list,
1675 AUDIO_DEVICE_IN_BUILTIN_MIC, "");
1676 select_devices(adev, usecase->id);
1677 }
1678 }
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301679 if (audio_extn_a2dp_start_playback() < 0) {
1680 ALOGE(" fail to configure A2dp Source control path ");
1681 goto err;
1682 } else {
1683 adev->a2dp_started = true;
1684 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001685 }
Florian Pfister1a84f312018-07-19 14:38:18 +02001686
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001687 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1688 (audio_extn_a2dp_start_capture() < 0)) {
1689 ALOGE(" fail to configure A2dp Sink control path ");
1690 goto err;
1691 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301692
Mingshu Pang7be5b1d2020-03-04 15:24:38 +08001693 if ((SND_DEVICE_OUT_BT_SCO_SWB == snd_device) ||
1694 (SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC == snd_device) ||
1695 (SND_DEVICE_IN_BT_SCO_MIC_SWB == snd_device)) {
1696 if (!adev->bt_sco_on || (audio_extn_sco_start_configuration() < 0)) {
1697 ALOGE(" fail to configure sco control path ");
1698 goto err;
1699 }
Zhou Song12c29502019-03-16 10:37:18 +08001700 }
1701
Zhou Song331c8e52019-08-26 14:16:12 +08001702 configure_btsco_sample_rate(snd_device);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001703 /* due to the possibility of calibration overwrite between listen
1704 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001705 audio_extn_sound_trigger_update_device_status(snd_device,
1706 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301707 audio_extn_listen_update_device_status(snd_device,
1708 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001709 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001710 audio_extn_sound_trigger_update_device_status(snd_device,
1711 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301712 audio_extn_listen_update_device_status(snd_device,
1713 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001714 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001715 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001716 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001717 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301718
1719 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1720 !adev->native_playback_enabled &&
1721 audio_is_true_native_stream_active(adev)) {
1722 ALOGD("%s: %d: napb: enabling native mode in hardware",
1723 __func__, __LINE__);
1724 audio_route_apply_and_update_path(adev->audio_route,
1725 "true-native-mode");
1726 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301727 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301728 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1729 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001730 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001731 ALOGD("%s: init ec ref loopback", __func__);
1732 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1733 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001734 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001735 return 0;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001736err:
1737 adev->snd_dev_ref_cnt[snd_device]--;
1738 return -EINVAL;;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001739}
1740
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001741int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001742 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001743{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301744 int i, num_devices = 0;
1745 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001746 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1747
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001748 if (snd_device < SND_DEVICE_MIN ||
1749 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001750 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001751 return -EINVAL;
1752 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001753
1754 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1755 ALOGE("%s: Invalid sound device returned", __func__);
1756 return -EINVAL;
1757 }
1758
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001759 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1760 ALOGE("%s: device ref cnt is already 0", __func__);
1761 return -EINVAL;
1762 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001763
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001764 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001765
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001766
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001767 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001768 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301769
Aalique Grahame22e49102018-12-18 14:23:57 -08001770 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1771
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001772 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1773 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001774 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001775
1776 // when speaker device is disabled, reset swap.
1777 // will be renabled on usecase start
1778 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001779 } else if (platform_split_snd_device(adev->platform,
1780 snd_device,
1781 &num_devices,
1782 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301783 for (i = 0; i < num_devices; i++) {
1784 disable_snd_device(adev, new_snd_devices[i]);
1785 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001786 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001787 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001788 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001789 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001790
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301791 if (snd_device == SND_DEVICE_OUT_BT_A2DP) {
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301792 audio_extn_a2dp_stop_playback();
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301793 adev->a2dp_started = false;
1794 } else if (snd_device == SND_DEVICE_IN_BT_A2DP)
Florian Pfister1a84f312018-07-19 14:38:18 +02001795 audio_extn_a2dp_stop_capture();
Zhou Songd6d71752019-05-21 18:08:51 +08001796 else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001797 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
Ashish Jain81eb2a82015-05-13 10:52:34 +05301798 adev->is_channel_status_set = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001799 else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301800 adev->native_playback_enabled) {
1801 ALOGD("%s: %d: napb: disabling native mode in hardware",
1802 __func__, __LINE__);
1803 audio_route_reset_and_update_path(adev->audio_route,
1804 "true-native-mode");
1805 adev->native_playback_enabled = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001806 } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301807 adev->asrc_mode_enabled) {
1808 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301809 disable_asrc_mode(adev);
1810 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001811 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301812 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001813 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001814 ALOGD("%s: deinit ec ref loopback", __func__);
1815 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1816 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001817
1818 audio_extn_utils_release_snd_device(snd_device);
1819 } else {
1820 if (platform_split_snd_device(adev->platform,
1821 snd_device,
1822 &num_devices,
1823 new_snd_devices) == 0) {
1824 for (i = 0; i < num_devices; i++) {
1825 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1826 }
1827 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001828 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001829
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001830 return 0;
1831}
1832
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001833/*
1834 legend:
1835 uc - existing usecase
1836 new_uc - new usecase
1837 d1, d11, d2 - SND_DEVICE enums
1838 a1, a2 - corresponding ANDROID device enums
1839 B1, B2 - backend strings
1840
1841case 1
1842 uc->dev d1 (a1) B1
1843 new_uc->dev d1 (a1), d2 (a2) B1, B2
1844
1845 resolution: disable and enable uc->dev on d1
1846
1847case 2
1848 uc->dev d1 (a1) B1
1849 new_uc->dev d11 (a1) B1
1850
1851 resolution: need to switch uc since d1 and d11 are related
1852 (e.g. speaker and voice-speaker)
1853 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1854
1855case 3
1856 uc->dev d1 (a1) B1
1857 new_uc->dev d2 (a2) B2
1858
1859 resolution: no need to switch uc
1860
1861case 4
1862 uc->dev d1 (a1) B1
1863 new_uc->dev d2 (a2) B1
1864
1865 resolution: disable enable uc-dev on d2 since backends match
1866 we cannot enable two streams on two different devices if they
1867 share the same backend. e.g. if offload is on speaker device using
1868 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1869 using the same backend, offload must also be switched to voice-handset.
1870
1871case 5
1872 uc->dev d1 (a1) B1
1873 new_uc->dev d1 (a1), d2 (a2) B1
1874
1875 resolution: disable enable uc-dev on d2 since backends match
1876 we cannot enable two streams on two different devices if they
1877 share the same backend.
1878
1879case 6
1880 uc->dev d1 (a1) B1
1881 new_uc->dev d2 (a1) B2
1882
1883 resolution: no need to switch
1884
1885case 7
1886 uc->dev d1 (a1), d2 (a2) B1, B2
1887 new_uc->dev d1 (a1) B1
1888
1889 resolution: no need to switch
1890
Zhou Song4ba65882018-07-09 14:48:07 +08001891case 8
1892 uc->dev d1 (a1) B1
1893 new_uc->dev d11 (a1), d2 (a2) B1, B2
1894 resolution: compared to case 1, for this case, d1 and d11 are related
1895 then need to do the same as case 2 to siwtch to new uc
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301896
1897case 9
1898 uc->dev d1 (a1), d2(a2) B1 B2
1899 new_uc->dev d1 (a1), d22 (a2) B1, B2
1900 resolution: disable enable uc-dev on d2 since backends match
1901 we cannot enable two streams on two different devices if they
1902 share the same backend. This is special case for combo use case
1903 with a2dp and sco devices which uses same backend.
1904 e.g. speaker-a2dp and speaker-btsco
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001905*/
1906static snd_device_t derive_playback_snd_device(void * platform,
1907 struct audio_usecase *uc,
1908 struct audio_usecase *new_uc,
1909 snd_device_t new_snd_device)
1910{
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001911 struct listnode a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001912
1913 snd_device_t d1 = uc->out_snd_device;
1914 snd_device_t d2 = new_snd_device;
Sandhya Mutha Naga Venkataa597a962023-02-07 11:35:51 +05301915 int ret = 0;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001916
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001917 list_init(&a1);
1918 list_init(&a2);
1919
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301920 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301921 case TRANSCODE_LOOPBACK_RX :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001922 assign_devices(&a1, &uc->stream.inout->out_config.device_list);
1923 assign_devices(&a2, &new_uc->stream.inout->out_config.device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301924 break;
1925 default :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001926 assign_devices(&a1, &uc->stream.out->device_list);
1927 assign_devices(&a2, &new_uc->stream.out->device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301928 break;
1929 }
1930
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001931 // Treat as a special case when a1 and a2 are not disjoint
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001932 if (!compare_devices(&a1, &a2) &&
1933 compare_devices_for_any_match(&a1 ,&a2)) {
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001934 snd_device_t d3[2];
1935 int num_devices = 0;
Sandhya Mutha Naga Venkataa597a962023-02-07 11:35:51 +05301936 ret = platform_split_snd_device(platform,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001937 list_length(&a1) > 1 ? d1 : d2,
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001938 &num_devices,
1939 d3);
1940 if (ret < 0) {
1941 if (ret != -ENOSYS) {
1942 ALOGW("%s failed to split snd_device %d",
1943 __func__,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001944 list_length(&a1) > 1 ? d1 : d2);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001945 }
Sandhya Mutha Naga Venkata4c6fc9f2022-10-14 19:38:02 +05301946 ret = d2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001947 goto end;
1948 }
1949
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001950 if (platform_check_backends_match(d3[0], d3[1])) {
Sandhya Mutha Naga Venkata4c6fc9f2022-10-14 19:38:02 +05301951 ret = d2;
1952 goto end; // case 5
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001953 } else {
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301954 if ((list_length(&a1) > 1) && (list_length(&a2) > 1) &&
Sandhya Mutha Naga Venkata4c6fc9f2022-10-14 19:38:02 +05301955 platform_check_backends_match(d1, d2)) {
1956 ret = d2;
1957 goto end; //case 9
1958 }
1959 if (list_length(&a1) > 1) {
1960 ret = d1;
1961 goto end; //case 7
1962 }
Garmond Leungb9eeba42018-09-18 11:10:41 -07001963 // check if d1 is related to any of d3's
Sandhya Mutha Naga Venkata4c6fc9f2022-10-14 19:38:02 +05301964 if (d1 == d3[0] || d1 == d3[1]) {
1965 ret = d1;
1966 goto end; // case 1
1967 } else {
1968 ret = d3[1];
1969 goto end; // case 8
1970 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001971 }
1972 } else {
1973 if (platform_check_backends_match(d1, d2)) {
Sandhya Mutha Naga Venkata4c6fc9f2022-10-14 19:38:02 +05301974 ret = d2;
1975 goto end; // case 2, 4
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001976 } else {
Sandhya Mutha Naga Venkata4c6fc9f2022-10-14 19:38:02 +05301977 ret = d1;
1978 goto end; // case 6, 3
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001979 }
1980 }
1981
1982end:
Sandhya Mutha Naga Venkata4c6fc9f2022-10-14 19:38:02 +05301983 clear_devices(&a1);
1984 clear_devices(&a2);
1985 return ret; // return whatever was calculated before.
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001986}
1987
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001988static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301989 struct audio_usecase *uc_info,
1990 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001991{
1992 struct listnode *node;
1993 struct audio_usecase *usecase;
1994 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301995 snd_device_t uc_derive_snd_device;
1996 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001997 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1998 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001999 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302000 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002001 /*
2002 * This function is to make sure that all the usecases that are active on
2003 * the hardware codec backend are always routed to any one device that is
2004 * handled by the hardware codec.
2005 * For example, if low-latency and deep-buffer usecases are currently active
2006 * on speaker and out_set_parameters(headset) is received on low-latency
2007 * output, then we have to make sure deep-buffer is also switched to headset,
2008 * because of the limitation that both the devices cannot be enabled
2009 * at the same time as they share the same backend.
2010 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07002011 /*
2012 * This call is to check if we need to force routing for a particular stream
2013 * If there is a backend configuration change for the device when a
2014 * new stream starts, then ADM needs to be closed and re-opened with the new
2015 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08002016 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07002017 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08002018 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
2019 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302020 /* For a2dp device reconfigure all active sessions
2021 * with new AFE encoder format based on a2dp state
2022 */
2023 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05302024 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device ||
2025 SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP == snd_device) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302026 audio_extn_a2dp_is_force_device_switch()) {
2027 force_routing = true;
2028 force_restart_session = true;
2029 }
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08002030
2031 /*
2032 * Island cfg and power mode config needs to set before AFE port start.
2033 * Set force routing in case of voice device was enable before.
2034 */
2035 if (uc_info->type == VOICE_CALL &&
2036 voice_extn_is_voice_power_mode_supported() &&
Kunlei Zhang67cc7072020-12-18 17:16:49 +08002037 is_supported_conc_usecase_for_power_mode_call(adev) &&
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08002038 platform_check_and_update_island_power_status(adev->platform,
2039 uc_info,
2040 snd_device)) {
2041 force_routing = true;
2042 ALOGD("%s:becf: force routing %d for power mode supported device",
2043 __func__, force_routing);
2044 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302045 ALOGD("%s:becf: force routing %d", __func__, force_routing);
2046
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002047 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002048 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002049 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002050 for (i = 0; i < AUDIO_USECASE_MAX; i++)
2051 switch_device[i] = false;
2052
2053 list_for_each(node, &adev->usecase_list) {
2054 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08002055
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05302056 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
2057 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302058 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05302059 platform_get_snd_device_name(usecase->out_snd_device),
2060 platform_check_backends_match(snd_device, usecase->out_snd_device));
Rahul Sharma99770982019-03-06 17:05:26 +05302061 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
2062 (usecase->type != PCM_PASSTHROUGH)) {
Ashish Jain6a65b352017-03-21 17:24:40 +05302063 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
2064 usecase, uc_info, snd_device);
2065 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002066 (is_codec_backend_out_device_type(&usecase->device_list) ||
2067 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
2068 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_DEVICE) ||
2069 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_HEADSET) ||
2070 is_a2dp_out_device_type(&usecase->device_list) ||
2071 is_sco_out_device_type(&usecase->device_list)) &&
Ashish Jain6a65b352017-03-21 17:24:40 +05302072 ((force_restart_session) ||
2073 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05302074 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
2075 __func__, use_case_table[usecase->id],
2076 platform_get_snd_device_name(usecase->out_snd_device));
2077 disable_audio_route(adev, usecase);
2078 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05302079 /* Enable existing usecase on derived playback device */
2080 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05302081 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05302082 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002083 }
2084 }
2085
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302086 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
2087 num_uc_to_switch);
2088
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002089 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07002090 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002091
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05302092 /* Make sure the previous devices to be disabled first and then enable the
2093 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002094 list_for_each(node, &adev->usecase_list) {
2095 usecase = node_to_item(node, struct audio_usecase, list);
2096 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08002097 /* Check if output sound device to be switched can be split and if any
2098 of the split devices match with derived sound device */
2099 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
2100 &num_devices, split_snd_devices) == 0) {
2101 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
2102 for (i = 0; i < num_devices; i++) {
2103 /* Disable devices that do not match with derived sound device */
2104 if (split_snd_devices[i] != derive_snd_device[usecase->id])
2105 disable_snd_device(adev, split_snd_devices[i]);
2106 }
2107 } else {
2108 disable_snd_device(adev, usecase->out_snd_device);
2109 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002110 }
2111 }
2112
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07002113 list_for_each(node, &adev->usecase_list) {
2114 usecase = node_to_item(node, struct audio_usecase, list);
2115 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08002116 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
2117 &num_devices, split_snd_devices) == 0) {
2118 /* Enable derived sound device only if it does not match with
2119 one of the split sound devices. This is because the matching
2120 sound device was not disabled */
2121 bool should_enable = true;
2122 for (i = 0; i < num_devices; i++) {
2123 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
2124 should_enable = false;
2125 break;
2126 }
2127 }
2128 if (should_enable)
2129 enable_snd_device(adev, derive_snd_device[usecase->id]);
2130 } else {
2131 enable_snd_device(adev, derive_snd_device[usecase->id]);
2132 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07002133 }
2134 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002135
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002136 /* Re-route all the usecases on the shared backend other than the
2137 specified usecase to new snd devices */
2138 list_for_each(node, &adev->usecase_list) {
2139 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05302140 /* Update the out_snd_device only before enabling the audio route */
2141 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05302142 usecase->out_snd_device = derive_snd_device[usecase->id];
Lakshman Chaluvarajuab7e5572020-10-28 19:29:23 +05302143 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
2144 use_case_table[usecase->id],
2145 platform_get_snd_device_name(usecase->out_snd_device));
2146 /* Update voc calibration before enabling Voice/VoIP route */
2147 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL)
2148 status = platform_switch_voice_call_device_post(adev->platform,
2149 usecase->out_snd_device,
2150 platform_get_input_snd_device(
2151 adev->platform, NULL,
2152 &uc_info->device_list,
2153 usecase->type));
2154 enable_audio_route(adev, usecase);
2155 if (usecase->stream.out && usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
2156 out_set_voip_volume(&usecase->stream.out->stream,
2157 usecase->stream.out->volume_l,
2158 usecase->stream.out->volume_r);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05302159 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002160 }
2161 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002162 }
2163}
2164
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302165static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002166 struct audio_usecase *uc_info,
2167 snd_device_t snd_device)
2168{
2169 struct listnode *node;
2170 struct audio_usecase *usecase;
2171 bool switch_device[AUDIO_USECASE_MAX];
2172 int i, num_uc_to_switch = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002173 int backend_check_cond = is_codec_backend_out_device_type(&uc_info->device_list);
kunleiz5cd52b82016-11-07 17:22:52 +08002174 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002175
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302176 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
2177 snd_device);
2178 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05302179
2180 /*
2181 * Make sure out devices is checked against out codec backend device and
2182 * also in devices against in codec backend. Checking out device against in
2183 * codec backend or vice versa causes issues.
2184 */
2185 if (uc_info->type == PCM_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002186 backend_check_cond = is_codec_backend_in_device_type(&uc_info->device_list);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08002187
2188 /*
2189 * Island cfg and power mode config needs to set before AFE port start.
2190 * Set force routing in case of voice device was enable before.
2191 */
2192
2193 if (uc_info->type == VOICE_CALL &&
2194 voice_extn_is_voice_power_mode_supported() &&
Kunlei Zhang67cc7072020-12-18 17:16:49 +08002195 is_supported_conc_usecase_for_power_mode_call(adev) &&
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08002196 platform_check_and_update_island_power_status(adev->platform,
2197 uc_info,
2198 snd_device)) {
2199 force_routing = true;
2200 ALOGD("%s:becf: force routing %d for power mode supported device",
2201 __func__, force_routing);
2202 }
2203
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002204 /*
2205 * This function is to make sure that all the active capture usecases
2206 * are always routed to the same input sound device.
2207 * For example, if audio-record and voice-call usecases are currently
2208 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
2209 * is received for voice call then we have to make sure that audio-record
2210 * usecase is also switched to earpiece i.e. voice-dmic-ef,
2211 * because of the limitation that two devices cannot be enabled
2212 * at the same time if they share the same backend.
2213 */
2214 for (i = 0; i < AUDIO_USECASE_MAX; i++)
2215 switch_device[i] = false;
2216
2217 list_for_each(node, &adev->usecase_list) {
2218 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05302219 /*
2220 * TODO: Enhance below condition to handle BT sco/USB multi recording
2221 */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302222
2223 bool capture_uc_needs_routing = usecase->type != PCM_PLAYBACK && (usecase != uc_info &&
2224 (usecase->in_snd_device != snd_device || force_routing));
2225 bool call_proxy_snd_device = platform_is_call_proxy_snd_device(snd_device) ||
2226 platform_is_call_proxy_snd_device(usecase->in_snd_device);
2227 if (capture_uc_needs_routing && !call_proxy_snd_device &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002228 ((backend_check_cond &&
2229 (is_codec_backend_in_device_type(&usecase->device_list) ||
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08002230 (usecase->type == VOIP_CALL))) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08002231 ((uc_info->type == VOICE_CALL &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002232 is_single_device_type_equal(&usecase->device_list,
2233 AUDIO_DEVICE_IN_VOICE_CALL)) ||
Anver sadhique4fdc6992022-01-21 12:26:28 +05302234 platform_check_all_backends_match(snd_device,\
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002235 usecase->in_snd_device))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07002236 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05302237 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..",
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002238 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07002239 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002240 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002241 switch_device[usecase->id] = true;
2242 num_uc_to_switch++;
2243 }
2244 }
2245
2246 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07002247 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002248
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05302249 /* Make sure the previous devices to be disabled first and then enable the
2250 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002251 list_for_each(node, &adev->usecase_list) {
2252 usecase = node_to_item(node, struct audio_usecase, list);
2253 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002254 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08002255 }
2256 }
2257
2258 list_for_each(node, &adev->usecase_list) {
2259 usecase = node_to_item(node, struct audio_usecase, list);
2260 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002261 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002262 }
2263 }
2264
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002265 /* Re-route all the usecases on the shared backend other than the
2266 specified usecase to new snd devices */
2267 list_for_each(node, &adev->usecase_list) {
2268 usecase = node_to_item(node, struct audio_usecase, list);
2269 /* Update the in_snd_device only before enabling the audio route */
2270 if (switch_device[usecase->id] ) {
2271 usecase->in_snd_device = snd_device;
Lakshman Chaluvarajuab7e5572020-10-28 19:29:23 +05302272 /* Update voc calibration before enabling Voice/VoIP route */
2273 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
2274 snd_device_t voip_snd_device;
2275 voip_snd_device = platform_get_output_snd_device(adev->platform,
2276 usecase->stream.out,
2277 usecase->type);
2278 status = platform_switch_voice_call_device_post(adev->platform,
2279 voip_snd_device,
2280 usecase->in_snd_device);
kunleiz5cd52b82016-11-07 17:22:52 +08002281 }
Lakshman Chaluvarajuab7e5572020-10-28 19:29:23 +05302282 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002283 }
2284 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002285 }
2286}
2287
Mingming Yin3a941d42016-02-17 18:08:05 -08002288static void reset_hdmi_sink_caps(struct stream_out *out) {
2289 int i = 0;
2290
2291 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
2292 out->supported_channel_masks[i] = 0;
2293 }
2294 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
2295 out->supported_formats[i] = 0;
2296 }
2297 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
2298 out->supported_sample_rates[i] = 0;
2299 }
2300}
2301
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002302/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08002303static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002304{
Mingming Yin3a941d42016-02-17 18:08:05 -08002305 int ret = 0, i = 0, j = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002306 int channels = platform_edid_get_max_channels_v2(out->dev->platform,
2307 out->extconn.cs.controller,
2308 out->extconn.cs.stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002309
Mingming Yin3a941d42016-02-17 18:08:05 -08002310 reset_hdmi_sink_caps(out);
2311
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002312 /* Cache ext disp type */
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002313 ret = platform_get_ext_disp_type_v2(adev->platform,
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002314 out->extconn.cs.controller,
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002315 out->extconn.cs.stream);
2316 if(ret < 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002317 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07002318 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002319 }
2320
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002321 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002322 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08002323 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002324 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08002325 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
2326 case 6:
2327 ALOGV("%s: HDMI supports 5.1 channels", __func__);
2328 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
2329 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
2330 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
2331 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
2332 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002333 break;
2334 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08002335 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002336 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002337 break;
2338 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002339
2340 // check channel format caps
2341 i = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002342 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_AC3,
2343 out->extconn.cs.controller,
2344 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002345 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
2346 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
2347 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
2348 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
2349 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
2350 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
2351 }
2352
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002353 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD,
2354 out->extconn.cs.controller,
2355 out->extconn.cs.stream)) {
Ben Romberger1aaaf862017-04-06 17:49:46 -07002356 ALOGV(":%s HDMI supports TRUE HD format", __func__);
2357 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
2358 }
2359
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002360 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS,
2361 out->extconn.cs.controller,
2362 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002363 ALOGV(":%s HDMI supports DTS format", __func__);
2364 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
2365 }
2366
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002367 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS_HD,
2368 out->extconn.cs.controller,
2369 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002370 ALOGV(":%s HDMI supports DTS HD format", __func__);
2371 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
2372 }
2373
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002374 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_IEC61937,
2375 out->extconn.cs.controller,
2376 out->extconn.cs.stream)) {
Naresh Tanniru928f0862017-04-07 16:44:23 -07002377 ALOGV(":%s HDMI supports IEC61937 format", __func__);
2378 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
2379 }
2380
Mingming Yin3a941d42016-02-17 18:08:05 -08002381
2382 // check sample rate caps
2383 i = 0;
2384 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002385 if (platform_is_edid_supported_sample_rate_v2(out->dev->platform, out_hdmi_sample_rates[j],
2386 out->extconn.cs.controller,
2387 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002388 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
2389 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
2390 }
2391 }
2392
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002393 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002394}
2395
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002396static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
2397 uint32_t *supported_sample_rates __unused,
2398 uint32_t max_rates __unused)
2399{
2400 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
2401 supported_sample_rates,
2402 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05302403 ssize_t i = 0;
2404
2405 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002406 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
2407 supported_sample_rates[i]);
2408 }
2409 return count;
2410}
2411
2412static inline int read_usb_sup_channel_masks(bool is_playback,
2413 audio_channel_mask_t *supported_channel_masks,
2414 uint32_t max_masks)
2415{
2416 int channels = audio_extn_usb_get_max_channels(is_playback);
2417 int channel_count;
2418 uint32_t num_masks = 0;
2419 if (channels > MAX_HIFI_CHANNEL_COUNT)
2420 channels = MAX_HIFI_CHANNEL_COUNT;
2421
2422 if (is_playback) {
Eric Laurent68a87112019-05-01 18:07:29 -07002423 // start from 2 channels as framework currently doesn't support mono.
2424 if (channels >= FCC_2) {
2425 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(FCC_2);
2426 }
2427 for (channel_count = FCC_2;
2428 channel_count <= channels && num_masks < max_masks;
2429 ++channel_count) {
2430 supported_channel_masks[num_masks++] =
2431 audio_channel_mask_for_index_assignment_from_count(channel_count);
2432 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002433 } else {
vincenttewf51c94e2019-05-07 10:28:53 +08002434 // For capture we report all supported channel masks from 1 channel up.
2435 channel_count = MIN_CHANNEL_COUNT;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002436 // audio_channel_in_mask_from_count() does the right conversion to either positional or
2437 // indexed mask
Eric Laurent68a87112019-05-01 18:07:29 -07002438 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
2439 audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
2440 if (channel_count <= FCC_2) {
2441 mask = audio_channel_in_mask_from_count(channel_count);
2442 supported_channel_masks[num_masks++] = mask;
2443 }
2444 const audio_channel_mask_t index_mask =
2445 audio_channel_mask_for_index_assignment_from_count(channel_count);
2446 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
2447 supported_channel_masks[num_masks++] = index_mask;
2448 }
2449 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002450 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302451
vincenttewf51c94e2019-05-07 10:28:53 +08002452 for (size_t i = 0; i < num_masks; ++i) {
2453 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
2454 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302455 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002456 return num_masks;
2457}
2458
2459static inline int read_usb_sup_formats(bool is_playback __unused,
2460 audio_format_t *supported_formats,
2461 uint32_t max_formats __unused)
2462{
2463 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
2464 switch (bitwidth) {
2465 case 24:
2466 // XXX : usb.c returns 24 for s24 and s24_le?
2467 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
2468 break;
2469 case 32:
2470 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
2471 break;
2472 case 16:
2473 default :
2474 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
2475 break;
2476 }
2477 ALOGV("%s: %s supported format %d", __func__,
2478 is_playback ? "P" : "C", bitwidth);
2479 return 1;
2480}
2481
2482static inline int read_usb_sup_params_and_compare(bool is_playback,
2483 audio_format_t *format,
2484 audio_format_t *supported_formats,
2485 uint32_t max_formats,
2486 audio_channel_mask_t *mask,
2487 audio_channel_mask_t *supported_channel_masks,
2488 uint32_t max_masks,
2489 uint32_t *rate,
2490 uint32_t *supported_sample_rates,
2491 uint32_t max_rates) {
2492 int ret = 0;
2493 int num_formats;
2494 int num_masks;
2495 int num_rates;
2496 int i;
2497
2498 num_formats = read_usb_sup_formats(is_playback, supported_formats,
2499 max_formats);
2500 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
2501 max_masks);
2502
2503 num_rates = read_usb_sup_sample_rates(is_playback,
2504 supported_sample_rates, max_rates);
2505
2506#define LUT(table, len, what, dflt) \
2507 for (i=0; i<len && (table[i] != what); i++); \
2508 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
2509
2510 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
2511 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
2512 LUT(supported_sample_rates, num_rates, *rate, 0);
2513
2514#undef LUT
2515 return ret < 0 ? -EINVAL : 0; // HACK TBD
2516}
2517
Alexy Josephb1379942016-01-29 15:49:38 -08002518audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002519 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002520{
2521 struct audio_usecase *usecase;
2522 struct listnode *node;
2523
2524 list_for_each(node, &adev->usecase_list) {
2525 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002526 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002527 ALOGV("%s: usecase id %d", __func__, usecase->id);
2528 return usecase->id;
2529 }
2530 }
2531 return USECASE_INVALID;
2532}
2533
Alexy Josephb1379942016-01-29 15:49:38 -08002534struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002535 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002536{
2537 struct audio_usecase *usecase;
2538 struct listnode *node;
2539
2540 list_for_each(node, &adev->usecase_list) {
2541 usecase = node_to_item(node, struct audio_usecase, list);
2542 if (usecase->id == uc_id)
2543 return usecase;
2544 }
2545 return NULL;
2546}
2547
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302548/*
2549 * is a true native playback active
2550 */
2551bool audio_is_true_native_stream_active(struct audio_device *adev)
2552{
2553 bool active = false;
2554 int i = 0;
2555 struct listnode *node;
2556
2557 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
2558 ALOGV("%s:napb: not in true mode or non hdphones device",
2559 __func__);
2560 active = false;
2561 goto exit;
2562 }
2563
2564 list_for_each(node, &adev->usecase_list) {
2565 struct audio_usecase *uc;
2566 uc = node_to_item(node, struct audio_usecase, list);
2567 struct stream_out *curr_out =
2568 (struct stream_out*) uc->stream.out;
2569
2570 if (curr_out && PCM_PLAYBACK == uc->type) {
2571 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
2572 "(%d) device %s", __func__, i++, use_case_table[uc->id],
2573 uc->id, curr_out->sample_rate,
2574 curr_out->bit_width,
2575 platform_get_snd_device_name(uc->out_snd_device));
2576
2577 if (is_offload_usecase(uc->id) &&
2578 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
2579 active = true;
2580 ALOGD("%s:napb:native stream detected", __func__);
2581 }
2582 }
2583 }
2584exit:
2585 return active;
2586}
2587
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002588uint32_t adev_get_dsp_bit_width_enforce_mode()
2589{
2590 if (adev == NULL) {
2591 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
2592 return 0;
2593 }
2594 return adev->dsp_bit_width_enforce_mode;
2595}
2596
2597static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
2598{
2599 char value[PROPERTY_VALUE_MAX];
2600 int trial;
2601 uint32_t dsp_bit_width_enforce_mode = 0;
2602
2603 if (!mixer) {
2604 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
2605 __func__);
2606 return 0;
2607 }
2608
2609 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
2610 value, NULL) > 0) {
2611 trial = atoi(value);
2612 switch (trial) {
2613 case 16:
2614 dsp_bit_width_enforce_mode = 16;
2615 break;
2616 case 24:
2617 dsp_bit_width_enforce_mode = 24;
2618 break;
2619 case 32:
2620 dsp_bit_width_enforce_mode = 32;
2621 break;
2622 default:
2623 dsp_bit_width_enforce_mode = 0;
2624 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
2625 break;
2626 }
2627 }
2628
2629 return dsp_bit_width_enforce_mode;
2630}
2631
2632static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
2633 uint32_t enforce_mode,
2634 bool enable)
2635{
2636 struct mixer_ctl *ctl = NULL;
2637 const char *mixer_ctl_name = "ASM Bit Width";
2638 uint32_t asm_bit_width_mode = 0;
2639
2640 if (enforce_mode == 0) {
2641 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
2642 return;
2643 }
2644
2645 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
2646 if (!ctl) {
2647 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2648 __func__, mixer_ctl_name);
2649 return;
2650 }
2651
2652 if (enable)
2653 asm_bit_width_mode = enforce_mode;
2654 else
2655 asm_bit_width_mode = 0;
2656
2657 ALOGV("%s DSP bit width feature status is %d width=%d",
2658 __func__, enable, asm_bit_width_mode);
2659 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2660 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2661 asm_bit_width_mode);
2662
2663 return;
2664}
2665
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302666/*
2667 * if native DSD playback active
2668 */
2669bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2670{
2671 bool active = false;
2672 struct listnode *node = NULL;
2673 struct audio_usecase *uc = NULL;
2674 struct stream_out *curr_out = NULL;
2675
2676 list_for_each(node, &adev->usecase_list) {
2677 uc = node_to_item(node, struct audio_usecase, list);
2678 curr_out = (struct stream_out*) uc->stream.out;
2679
2680 if (curr_out && PCM_PLAYBACK == uc->type &&
2681 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2682 active = true;
2683 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302684 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302685 }
2686 }
2687 return active;
2688}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302689
2690static bool force_device_switch(struct audio_usecase *usecase)
2691{
2692 bool ret = false;
2693 bool is_it_true_mode = false;
2694
Zhou Song30f2c3e2018-02-08 14:02:15 +08002695 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302696 usecase->type == TRANSCODE_LOOPBACK_RX ||
2697 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002698 return false;
2699 }
2700
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002701 if(usecase->stream.out == NULL) {
2702 ALOGE("%s: stream.out is NULL", __func__);
2703 return false;
2704 }
2705
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302706 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002707 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002708 (compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADSET) ||
2709 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADPHONE))) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302710 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2711 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2712 (!is_it_true_mode && adev->native_playback_enabled)){
2713 ret = true;
2714 ALOGD("napb: time to toggle native mode");
2715 }
2716 }
2717
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302718 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302719 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2720 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002721 if(is_a2dp_out_device_type(&usecase->stream.out->device_list) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302722 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302723 ALOGD("Force a2dp device switch to update new encoder config");
2724 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002725 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302726
Florian Pfister1a84f312018-07-19 14:38:18 +02002727 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302728 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2729 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002730 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302731 return ret;
2732}
2733
Aalique Grahame22e49102018-12-18 14:23:57 -08002734static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2735{
2736 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2737}
2738
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302739bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2740{
2741 bool ret=false;
2742 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
Zhou Song5657f492019-08-07 11:30:39 +08002743 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
2744 out_snd_device == SND_DEVICE_OUT_BT_SCO_SWB) ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302745 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2746 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
Zhou Song5657f492019-08-07 11:30:39 +08002747 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302748 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
Mingshu Pang16093502020-04-20 11:21:16 +08002749 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC ||
2750 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC)
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302751 ret = true;
2752
2753 return ret;
2754}
2755
2756bool is_a2dp_device(snd_device_t out_snd_device)
2757{
2758 bool ret=false;
2759 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2760 ret = true;
2761
2762 return ret;
2763}
2764
2765bool is_bt_soc_on(struct audio_device *adev)
2766{
2767 struct mixer_ctl *ctl;
2768 char *mixer_ctl_name = "BT SOC status";
2769 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2770 bool bt_soc_status = true;
2771 if (!ctl) {
2772 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2773 __func__, mixer_ctl_name);
2774 /*This is to ensure we dont break targets which dont have the kernel change*/
2775 return true;
2776 }
2777 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2778 ALOGD("BT SOC status: %d",bt_soc_status);
2779 return bt_soc_status;
2780}
2781
Zhou Song331c8e52019-08-26 14:16:12 +08002782static int configure_btsco_sample_rate(snd_device_t snd_device)
2783{
2784 struct mixer_ctl *ctl = NULL;
2785 struct mixer_ctl *ctl_sr_rx = NULL, *ctl_sr_tx = NULL, *ctl_sr = NULL;
2786 char *rate_str = NULL;
2787 bool is_rx_dev = true;
2788
2789 if (is_btsco_device(snd_device, snd_device)) {
2790 ctl_sr_tx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate TX");
2791 ctl_sr_rx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate RX");
2792 if (!ctl_sr_tx || !ctl_sr_rx) {
2793 ctl_sr = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate");
2794 if (!ctl_sr)
2795 return -ENOSYS;
2796 }
2797
2798 switch (snd_device) {
2799 case SND_DEVICE_OUT_BT_SCO:
2800 rate_str = "KHZ_8";
2801 break;
2802 case SND_DEVICE_IN_BT_SCO_MIC_NREC:
2803 case SND_DEVICE_IN_BT_SCO_MIC:
2804 rate_str = "KHZ_8";
2805 is_rx_dev = false;
2806 break;
2807 case SND_DEVICE_OUT_BT_SCO_WB:
2808 rate_str = "KHZ_16";
2809 break;
2810 case SND_DEVICE_IN_BT_SCO_MIC_WB_NREC:
2811 case SND_DEVICE_IN_BT_SCO_MIC_WB:
2812 rate_str = "KHZ_16";
2813 is_rx_dev = false;
2814 break;
2815 default:
2816 return 0;
2817 }
2818
2819 ctl = (ctl_sr == NULL) ? (is_rx_dev ? ctl_sr_rx : ctl_sr_tx) : ctl_sr;
2820 if (mixer_ctl_set_enum_by_string(ctl, rate_str) != 0)
2821 return -ENOSYS;
2822 }
2823 return 0;
2824}
2825
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302826int out_standby_l(struct audio_stream *stream);
2827
Eric Laurent637e2d42018-11-15 12:24:31 -08002828struct stream_in *adev_get_active_input(const struct audio_device *adev)
2829{
2830 struct listnode *node;
2831 struct stream_in *last_active_in = NULL;
2832
2833 /* Get last added active input.
2834 * TODO: We may use a priority mechanism to pick highest priority active source */
2835 list_for_each(node, &adev->usecase_list)
2836 {
2837 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2838 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL)
2839 last_active_in = usecase->stream.in;
2840 }
2841
2842 return last_active_in;
2843}
2844
2845struct stream_in *get_voice_communication_input(const struct audio_device *adev)
2846{
2847 struct listnode *node;
2848
2849 /* First check active inputs with voice communication source and then
2850 * any input if audio mode is in communication */
2851 list_for_each(node, &adev->usecase_list)
2852 {
2853 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2854 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
2855 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
2856 return usecase->stream.in;
2857 }
2858 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION)
2859 return adev_get_active_input(adev);
2860
2861 return NULL;
2862}
2863
Carter Hsu2e429db2019-05-14 18:50:52 +08002864/*
2865 * Aligned with policy.h
2866 */
2867static inline int source_priority(int inputSource)
2868{
2869 switch (inputSource) {
2870 case AUDIO_SOURCE_VOICE_COMMUNICATION:
2871 return 9;
2872 case AUDIO_SOURCE_CAMCORDER:
2873 return 8;
2874 case AUDIO_SOURCE_VOICE_PERFORMANCE:
2875 return 7;
2876 case AUDIO_SOURCE_UNPROCESSED:
2877 return 6;
2878 case AUDIO_SOURCE_MIC:
2879 return 5;
2880 case AUDIO_SOURCE_ECHO_REFERENCE:
2881 return 4;
2882 case AUDIO_SOURCE_FM_TUNER:
2883 return 3;
2884 case AUDIO_SOURCE_VOICE_RECOGNITION:
2885 return 2;
2886 case AUDIO_SOURCE_HOTWORD:
2887 return 1;
2888 default:
2889 break;
2890 }
2891 return 0;
2892}
2893
2894static struct stream_in *get_priority_input(struct audio_device *adev)
2895{
2896 struct listnode *node;
2897 struct audio_usecase *usecase;
2898 int last_priority = 0, priority;
2899 struct stream_in *priority_in = NULL;
2900 struct stream_in *in;
2901
2902 list_for_each(node, &adev->usecase_list) {
2903 usecase = node_to_item(node, struct audio_usecase, list);
2904 if (usecase->type == PCM_CAPTURE) {
2905 in = usecase->stream.in;
2906 if (!in)
2907 continue;
Krishna Kishor Jha0b7175d2022-07-28 22:33:46 +05302908
2909 if (USECASE_AUDIO_RECORD_FM_VIRTUAL == usecase->id)
2910 continue;
Carter Hsu2e429db2019-05-14 18:50:52 +08002911 priority = source_priority(in->source);
2912
2913 if (priority > last_priority) {
2914 last_priority = priority;
2915 priority_in = in;
2916 }
2917 }
2918 }
2919 return priority_in;
2920}
2921
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002922int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002923{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002924 snd_device_t out_snd_device = SND_DEVICE_NONE;
2925 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002926 struct audio_usecase *usecase = NULL;
2927 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002928 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002929 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302930 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002931 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002932 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002933
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302934 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2935
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002936 usecase = get_usecase_from_list(adev, uc_id);
2937 if (usecase == NULL) {
2938 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2939 return -EINVAL;
2940 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002941
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002942 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002943 (usecase->type == VOIP_CALL) ||
Derek Chena30a5f42019-12-03 11:17:09 -05002944 (usecase->type == PCM_HFP_CALL)||
Fei Tongaffdf732020-02-20 20:39:05 +08002945 (usecase->type == ICC_CALL) ||
2946 (usecase->type == SYNTH_LOOPBACK)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302947 if(usecase->stream.out == NULL) {
2948 ALOGE("%s: stream.out is NULL", __func__);
2949 return -EINVAL;
2950 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002951 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS)) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002952 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev,
2953 uc_id);
2954 in_snd_device = audio_extn_auto_hal_get_input_snd_device(adev,
2955 uc_id);
2956 } else {
2957 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302958 usecase->stream.out, usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002959 in_snd_device = platform_get_input_snd_device(adev->platform,
2960 NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302961 &usecase->stream.out->device_list,
2962 usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002963 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002964 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302965 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302966 if (usecase->stream.inout == NULL) {
2967 ALOGE("%s: stream.inout is NULL", __func__);
2968 return -EINVAL;
2969 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002970 assign_devices(&stream_out.device_list, &usecase->stream.inout->out_config.device_list);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302971 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2972 stream_out.format = usecase->stream.inout->out_config.format;
2973 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
Jaideep Sharma477917f2020-03-13 18:13:33 +05302974 out_snd_device = platform_get_output_snd_device(adev->platform, &stream_out, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002975 assign_devices(&usecase->device_list,
2976 &usecase->stream.inout->out_config.device_list);
Zhenlin Lian4f947842022-05-14 15:50:52 +05302977 clear_devices(&stream_out.device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302978 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2979 if (usecase->stream.inout == NULL) {
2980 ALOGE("%s: stream.inout is NULL", __func__);
2981 return -EINVAL;
2982 }
Manisha Agarwal03297972020-04-17 15:36:55 +05302983 struct listnode out_devices;
2984 list_init(&out_devices);
2985 in_snd_device = platform_get_input_snd_device(adev->platform, NULL,
2986 &out_devices, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002987 assign_devices(&usecase->device_list,
2988 &usecase->stream.inout->in_config.device_list);
Zhenlin Lian4f947842022-05-14 15:50:52 +05302989 clear_devices(&out_devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002990 } else {
2991 /*
2992 * If the voice call is active, use the sound devices of voice call usecase
2993 * so that it would not result any device switch. All the usecases will
2994 * be switched to new device when select_devices() is called for voice call
2995 * usecase. This is to avoid switching devices for voice call when
2996 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002997 * choose voice call device only if the use case device is
2998 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002999 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08003000 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003001 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08003002 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003003 if ((vc_usecase) && ((is_codec_backend_out_device_type(&vc_usecase->device_list) &&
3004 is_codec_backend_out_device_type(&usecase->device_list)) ||
3005 (is_codec_backend_out_device_type(&vc_usecase->device_list) &&
3006 is_codec_backend_in_device_type(&usecase->device_list)) ||
3007 is_single_device_type_equal(&vc_usecase->device_list,
3008 AUDIO_DEVICE_OUT_HEARING_AID) ||
3009 is_single_device_type_equal(&usecase->device_list,
Robert Lee8a6aaf32019-09-20 16:40:19 +08003010 AUDIO_DEVICE_IN_VOICE_CALL) ||
3011 (is_single_device_type_equal(&usecase->device_list,
Gautam Manam8fa06162021-09-24 10:41:29 +05303012 AUDIO_DEVICE_IN_BUILTIN_MIC) &&
3013 is_single_device_type_equal(&vc_usecase->device_list,
3014 AUDIO_DEVICE_OUT_USB_HEADSET)) ||
3015 (is_single_device_type_equal(&usecase->device_list,
Robert Lee8a6aaf32019-09-20 16:40:19 +08003016 AUDIO_DEVICE_IN_USB_HEADSET) &&
3017 is_single_device_type_equal(&vc_usecase->device_list,
Kamalakar Yalasiri5edba852021-01-28 14:52:38 +05303018 AUDIO_DEVICE_OUT_USB_HEADSET))||
Gautam Manamf4002142021-09-13 22:05:56 +05303019 (is_single_device_type_equal(&usecase->device_list,
3020 AUDIO_DEVICE_IN_USB_HEADSET) &&
3021 is_codec_backend_out_device_type(&vc_usecase->device_list)) ||
Kamalakar Yalasiri5edba852021-01-28 14:52:38 +05303022 (is_single_device_type_equal(&usecase->device_list,
3023 AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) &&
3024 is_codec_backend_out_device_type(&vc_usecase->device_list)))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003025 in_snd_device = vc_usecase->in_snd_device;
3026 out_snd_device = vc_usecase->out_snd_device;
3027 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003028 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08003029 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08003030 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08003031 if ((voip_usecase != NULL) &&
3032 (usecase->type == PCM_PLAYBACK) &&
3033 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08003034 out_snd_device_backend_match = platform_check_backends_match(
3035 voip_usecase->out_snd_device,
3036 platform_get_output_snd_device(
3037 adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05303038 usecase->stream.out, usecase->type));
yidongh02ef86f2017-04-21 15:36:04 +08003039 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003040 if ((voip_usecase) && (is_codec_backend_out_device_type(&voip_usecase->device_list) &&
3041 (is_codec_backend_out_device_type(&usecase->device_list) ||
3042 is_codec_backend_in_device_type(&usecase->device_list)) &&
yidongh02ef86f2017-04-21 15:36:04 +08003043 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07003044 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003045 in_snd_device = voip_usecase->in_snd_device;
3046 out_snd_device = voip_usecase->out_snd_device;
3047 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08003048 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08003049 hfp_ucid = audio_extn_hfp_get_usecase();
3050 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003051 if ((hfp_usecase) && is_codec_backend_out_device_type(&hfp_usecase->device_list)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08003052 in_snd_device = hfp_usecase->in_snd_device;
3053 out_snd_device = hfp_usecase->out_snd_device;
3054 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003055 }
3056 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05303057 if (usecase->stream.out == NULL) {
3058 ALOGE("%s: stream.out is NULL", __func__);
3059 return -EINVAL;
3060 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003061 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003062 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003063 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003064 struct stream_out *voip_out = adev->primary_output;
3065 struct stream_in *voip_in = get_voice_communication_input(adev);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003066 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS))
Guodong Hu267bdf82019-08-12 19:22:32 +08003067 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev, uc_id);
3068 else
3069 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05303070 usecase->stream.out,
3071 usecase->type);
kunleizdcf967a2018-08-07 17:09:11 +08003072 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizdcf967a2018-08-07 17:09:11 +08003073
Eric Laurent637e2d42018-11-15 12:24:31 -08003074 if (voip_usecase)
3075 voip_out = voip_usecase->stream.out;
3076
3077 if (usecase->stream.out == voip_out && voip_in != NULL)
3078 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003079 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003080 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05303081 if (usecase->stream.in == NULL) {
3082 ALOGE("%s: stream.in is NULL", __func__);
3083 return -EINVAL;
3084 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003085 assign_devices(&usecase->device_list, &usecase->stream.in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003086 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003087 if (in_snd_device == SND_DEVICE_NONE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003088 struct listnode out_devices;
Eric Laurent637e2d42018-11-15 12:24:31 -08003089 struct stream_in *voip_in = get_voice_communication_input(adev);
Carter Hsu2e429db2019-05-14 18:50:52 +08003090 struct stream_in *priority_in = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08003091
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003092 list_init(&out_devices);
Eric Laurent637e2d42018-11-15 12:24:31 -08003093 if (voip_in != NULL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003094 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
3095 USECASE_AUDIO_PLAYBACK_VOIP);
3096
Carter Hsu2e429db2019-05-14 18:50:52 +08003097 usecase->stream.in->enable_ec_port = false;
3098
Zhou Song503196b2021-07-23 17:31:05 +08003099 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY ||
3100 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY2) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003101 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_TELEPHONY_TX, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08003102 } else if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003103 assign_devices(&out_devices, &voip_usecase->stream.out->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08003104 } else if (adev->primary_output &&
3105 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003106 assign_devices(&out_devices, &adev->primary_output->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08003107 } else {
3108 /* forcing speaker o/p device to get matching i/p pair
3109 in case o/p is not routed from same primary HAL */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003110 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08003111 }
Carter Hsu2e429db2019-05-14 18:50:52 +08003112 priority_in = voip_in;
3113 } else {
3114 /* get the input with the highest priority source*/
3115 priority_in = get_priority_input(adev);
3116
Susan Wang727dd6b2021-03-26 11:28:59 -04003117 if (!priority_in ||
3118 audio_extn_auto_hal_overwrite_priority_for_auto(usecase->stream.in))
Carter Hsu2e429db2019-05-14 18:50:52 +08003119 priority_in = usecase->stream.in;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003120 }
Huicheng Liu1404ba12020-09-11 01:03:25 -04003121 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_IN_BUS)){
3122 in_snd_device = audio_extn_auto_hal_get_snd_device_for_car_audio_stream(priority_in->car_audio_stream);
3123 }
3124 else
3125 in_snd_device = platform_get_input_snd_device(adev->platform,
3126 priority_in,
3127 &out_devices,
3128 usecase->type);
Zhenlin Lian4f947842022-05-14 15:50:52 +05303129 clear_devices(&out_devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003130 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003131 }
3132 }
3133
3134 if (out_snd_device == usecase->out_snd_device &&
3135 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05303136
3137 if (!force_device_switch(usecase))
3138 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003139 }
3140
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003141 if (!compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS) &&
Guodong Hu267bdf82019-08-12 19:22:32 +08003142 ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003143 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready()))) {
Guodong Hu267bdf82019-08-12 19:22:32 +08003144 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
3145 return 0;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303146 }
3147
Aalique Grahame22e49102018-12-18 14:23:57 -08003148 if (out_snd_device != SND_DEVICE_NONE &&
3149 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
3150 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
3151 __func__,
3152 use_case_table[uc_id],
3153 adev->last_logged_snd_device[uc_id][0],
3154 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
3155 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
3156 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
3157 -1,
3158 out_snd_device,
3159 platform_get_snd_device_name(out_snd_device),
3160 platform_get_snd_device_acdb_id(out_snd_device));
3161 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
3162 }
3163 if (in_snd_device != SND_DEVICE_NONE &&
3164 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
3165 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
3166 __func__,
3167 use_case_table[uc_id],
3168 adev->last_logged_snd_device[uc_id][1],
3169 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
3170 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
3171 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
3172 -1,
3173 in_snd_device,
3174 platform_get_snd_device_name(in_snd_device),
3175 platform_get_snd_device_acdb_id(in_snd_device));
3176 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
3177 }
3178
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003179
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003180 /*
3181 * Limitation: While in call, to do a device switch we need to disable
3182 * and enable both RX and TX devices though one of them is same as current
3183 * device.
3184 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07003185 if ((usecase->type == VOICE_CALL) &&
3186 (usecase->in_snd_device != SND_DEVICE_NONE) &&
3187 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07003188 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07003189 }
3190
3191 if (((usecase->type == VOICE_CALL) ||
3192 (usecase->type == VOIP_CALL)) &&
3193 (usecase->out_snd_device != SND_DEVICE_NONE)) {
3194 /* Disable sidetone only if voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303195 if (voice_is_call_state_active_in_call(adev) ||
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07003196 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07003197 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003198
3199 /* Disable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303200 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003201 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08003202 }
3203
Aalique Grahame22e49102018-12-18 14:23:57 -08003204 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
3205 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003206 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303207 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08003208 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
3209 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
3210 else
3211 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303212 }
3213
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003214 /* Disable current sound devices */
3215 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003216 disable_audio_route(adev, usecase);
3217 disable_snd_device(adev, usecase->out_snd_device);
Gautam Manam274f4752021-09-24 10:58:49 +05303218 if (usecase->id == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
3219 disable_snd_device(adev, SND_DEVICE_OUT_HAPTICS);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003220 }
3221
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003222 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003223 disable_audio_route(adev, usecase);
3224 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003225 }
3226
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08003227 /* Applicable only on the targets that has external modem.
3228 * New device information should be sent to modem before enabling
3229 * the devices to reduce in-call device switch time.
3230 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07003231 if ((usecase->type == VOICE_CALL) &&
3232 (usecase->in_snd_device != SND_DEVICE_NONE) &&
3233 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08003234 status = platform_switch_voice_call_enable_device_config(adev->platform,
3235 out_snd_device,
3236 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07003237 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08003238
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003239 /* Enable new sound devices */
3240 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08003241 check_usecases_codec_backend(adev, usecase, out_snd_device);
Saurav Kumarc1411662020-10-14 10:50:45 +05303242 check_and_configure_headphone(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05303243 if (platform_check_codec_asrc_support(adev->platform))
3244 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003245 enable_snd_device(adev, out_snd_device);
Zhou Songd9bd9302020-08-04 16:34:45 +08003246 /* Enable haptics device for haptic usecase */
3247 if (usecase->id == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
3248 enable_snd_device(adev, SND_DEVICE_OUT_HAPTICS);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003249 }
3250
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07003251 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303252 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003253 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07003254 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003255
Lakshman Chaluvarajuab7e5572020-10-28 19:29:23 +05303256 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL)
Eric Laurentb23d5282013-05-14 15:27:20 -07003257 status = platform_switch_voice_call_device_post(adev->platform,
3258 out_snd_device,
3259 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08003260
sangwoo170731f2013-06-08 15:36:36 +09003261 usecase->in_snd_device = in_snd_device;
3262 usecase->out_snd_device = out_snd_device;
3263
Dhananjay Kumard6d32152016-10-13 16:11:03 +05303264 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
3265 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05303266 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003267 if ((24 == usecase->stream.out->bit_width) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003268 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_SPEAKER)) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003269 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3270 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
3271 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
3272 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
3273 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
3274 /*
3275 * To best utlize DSP, check if the stream sample rate is supported/multiple of
3276 * configured device sample rate, if not update the COPP rate to be equal to the
3277 * device sample rate, else open COPP at stream sample rate
3278 */
3279 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
3280 usecase->stream.out->sample_rate,
3281 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05303282 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
Preetam Singh Ranawat590d0432019-09-30 14:39:47 +05303283 out_snd_device != SND_DEVICE_OUT_HEADPHONES &&
3284 out_snd_device != SND_DEVICE_OUT_HEADPHONES_HIFI_FILTER &&
Ashish Jain4826f6c2017-02-06 13:33:20 +05303285 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003286 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
3287 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +05303288#ifdef PLATFORM_AUTO
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +05303289 if (!(compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS) && ((usecase->stream.out->flags &
3290 (audio_output_flags_t)AUDIO_OUTPUT_FLAG_SYS_NOTIFICATION) || (usecase->stream.out->flags &
3291 (audio_output_flags_t)AUDIO_OUTPUT_FLAG_PHONE)))) {
3292 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3293 }
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +05303294#else
3295 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3296#endif
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003297 }
Weiyin Jiangcdece202019-07-08 16:13:16 +08003298 }
3299 enable_audio_route(adev, usecase);
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003300
Shalini Manjunatha5e610912020-12-29 13:02:25 +05303301 if (uc_id == USECASE_AUDIO_PLAYBACK_VOIP) {
3302 struct stream_in *voip_in = get_voice_communication_input(adev);
3303 struct audio_usecase *voip_in_usecase = NULL;
3304 voip_in_usecase = get_usecase_from_list(adev, USECASE_AUDIO_RECORD_VOIP);
3305 if (voip_in != NULL &&
3306 voip_in_usecase != NULL &&
3307 !(out_snd_device == AUDIO_DEVICE_OUT_SPEAKER ||
3308 out_snd_device == AUDIO_DEVICE_OUT_SPEAKER_SAFE) &&
3309 (voip_in_usecase->in_snd_device ==
3310 platform_get_input_snd_device(adev->platform, voip_in,
3311 &usecase->stream.out->device_list,usecase->type))) {
3312 /*
3313 * if VOIP TX is enabled before VOIP RX, needs to re-route the TX path
3314 * for enabling echo-reference-voip with correct port
3315 */
3316 ALOGD("%s: VOIP TX is enabled before VOIP RX,needs to re-route the TX path",__func__);
3317 disable_audio_route(adev, voip_in_usecase);
3318 disable_snd_device(adev, voip_in_usecase->in_snd_device);
3319 enable_snd_device(adev, voip_in_usecase->in_snd_device);
3320 enable_audio_route(adev, voip_in_usecase);
3321 }
3322 }
Ramjee Singhcdf67af2021-09-29 14:20:27 +05303323 if (voice_extn_compress_voip_is_active(adev)) {
3324 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
3325 USECASE_COMPRESS_VOIP_CALL);
3326 /*
3327 * If only compress voip input is opened voip out will be primary out.
3328 * Need to consider re-routing to select correct i/p pair
3329 */
3330 if ((voip_usecase != NULL) &&
3331 (usecase->type == PCM_PLAYBACK) &&
3332 (usecase->stream.out == voip_usecase->stream.out)) {
3333 in_snd_device = platform_get_input_snd_device(adev->platform,
3334 NULL,
3335 &usecase->stream.out->device_list,
3336 usecase->type);
3337 if (voip_usecase->in_snd_device != in_snd_device ) {
3338 ALOGD("%s:Re routing compress voip tx snd device matching voip rx pair",
3339 __func__);
3340 disable_audio_route(adev, voip_usecase);
3341 disable_snd_device(adev, voip_usecase->in_snd_device);
3342 voip_usecase->in_snd_device = in_snd_device;
3343 voip_usecase->out_snd_device = usecase->out_snd_device;
3344 /* Route all TX usecase to Compress voip BE */
3345 check_usecases_capture_codec_backend(adev, voip_usecase, in_snd_device);
3346 enable_snd_device(adev, in_snd_device);
3347 /* Send Voice related calibration for RX /TX pair */
3348 status = platform_switch_voice_call_device_post(adev->platform,
3349 out_snd_device,
3350 in_snd_device);
3351 enable_audio_route(adev, voip_usecase);
3352 }
3353 }
3354 }
Shalini Manjunatha5e610912020-12-29 13:02:25 +05303355
3356
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08003357 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08003358
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003359 /* If input stream is already running then effect needs to be
3360 applied on the new input device that's being enabled here. */
Eric Laurent637e2d42018-11-15 12:24:31 -08003361 if (in_snd_device != SND_DEVICE_NONE)
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003362 check_and_enable_effect(adev);
3363
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003364 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003365 /* Enable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303366 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003367 voice_check_and_update_aanc_path(adev, out_snd_device, true);
3368
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003369 /* Enable sidetone only if other voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303370 if (voice_is_call_state_active_in_call(adev) ||
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003371 voice_extn_compress_voip_is_started(adev))
3372 voice_set_sidetone(adev, out_snd_device, true);
3373 }
3374
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003375 /* Applicable only on the targets that has external modem.
3376 * Enable device command should be sent to modem only after
3377 * enabling voice call mixer controls
3378 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07003379 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003380 status = platform_switch_voice_call_usecase_route_post(adev->platform,
3381 out_snd_device,
3382 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303383
3384 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003385 struct stream_in *in = adev_get_active_input(adev);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303386 if (usecase->type == VOIP_CALL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003387 if (in != NULL && !in->standby) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303388 if (is_bt_soc_on(adev) == false){
3389 ALOGD("BT SCO MIC disconnected while in connection");
Eric Laurent637e2d42018-11-15 12:24:31 -08003390 if (in->pcm != NULL)
3391 pcm_stop(in->pcm);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303392 }
3393 }
3394 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
3395 && usecase->stream.out->started) {
3396 if (is_bt_soc_on(adev) == false) {
3397 ALOGD("BT SCO/A2DP disconnected while in connection");
3398 out_standby_l(&usecase->stream.out->stream.common);
3399 }
3400 }
3401 } else if ((usecase->stream.out != NULL) &&
3402 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05303403 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
3404 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Weiyin Jiang0d373242019-07-25 13:18:17 +08003405 (usecase->type != PCM_CAPTURE) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303406 usecase->stream.out->started) {
3407 if (is_bt_soc_on(adev) == false) {
3408 ALOGD("BT SCO/A2dp disconnected while in connection");
3409 out_standby_l(&usecase->stream.out->stream.common);
3410 }
3411 }
3412 }
3413
Yung Ti Su70cb8242018-06-22 17:38:47 +08003414 if (usecase->type != PCM_CAPTURE && usecase == voip_usecase) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003415 struct stream_out *voip_out = voip_usecase->stream.out;
3416 audio_extn_utils_send_app_type_gain(adev,
3417 voip_out->app_type_cfg.app_type,
3418 &voip_out->app_type_cfg.gain[0]);
3419 }
3420
Ajender Reddyb940b832021-07-07 11:51:42 +05303421 ALOGD("%s: done",__func__);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303422
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003423 return status;
3424}
3425
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003426static int stop_input_stream(struct stream_in *in)
3427{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303428 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003429 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05303430
3431 if (in == NULL) {
3432 ALOGE("%s: stream_in ptr is NULL", __func__);
3433 return -EINVAL;
3434 }
3435
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003436 struct audio_device *adev = in->dev;
Carter Hsu2e429db2019-05-14 18:50:52 +08003437 struct stream_in *priority_in = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003438
Eric Laurent994a6932013-07-17 11:51:42 -07003439 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003440 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003441 uc_info = get_usecase_from_list(adev, in->usecase);
3442 if (uc_info == NULL) {
3443 ALOGE("%s: Could not find the usecase (%d) in the list",
3444 __func__, in->usecase);
3445 return -EINVAL;
3446 }
3447
Carter Hsu2e429db2019-05-14 18:50:52 +08003448 priority_in = get_priority_input(adev);
3449
Derek Chenea197282019-01-07 17:35:01 -08003450 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3451 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003452
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003453 /* Close in-call recording streams */
3454 voice_check_and_stop_incall_rec_usecase(adev, in);
3455
Eric Laurent150dbfe2013-02-27 14:31:02 -08003456 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003457 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003458
3459 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003460 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003461
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003462 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303463 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_PRIMARY);
3464
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003465 list_remove(&uc_info->list);
Zhenlin Lian4f947842022-05-14 15:50:52 +05303466 clear_devices(&uc_info->device_list);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003467 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003468
Carter Hsu2e429db2019-05-14 18:50:52 +08003469 if (priority_in == in) {
3470 priority_in = get_priority_input(adev);
Sujin Panicker110f7942021-08-26 17:01:22 +05303471 if (priority_in) {
3472 if (is_usb_in_device_type(&priority_in->device_list)) {
3473 if (audio_extn_usb_connected(NULL))
3474 select_devices(adev, priority_in->usecase);
3475 } else {
3476 select_devices(adev, priority_in->usecase);
3477 }
3478 }
Carter Hsu2e429db2019-05-14 18:50:52 +08003479 }
3480
Vatsal Buchac09ae062018-11-14 13:25:08 +05303481 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07003482 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003483 return ret;
3484}
3485
3486int start_input_stream(struct stream_in *in)
3487{
3488 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08003489 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003490 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05303491
3492 if (in == NULL) {
3493 ALOGE("%s: stream_in ptr is NULL", __func__);
3494 return -EINVAL;
3495 }
3496
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003497 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07003498 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07003499 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003500
Mingming Yin2664a5b2015-09-03 10:53:11 -07003501 if (get_usecase_from_list(adev, usecase) == NULL)
3502 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303503 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
3504 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003505
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303506 if (CARD_STATUS_OFFLINE == in->card_status||
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05003507 CARD_STATUS_OFFLINE == adev->card_status ||
3508 POWER_POLICY_STATUS_OFFLINE == adev->in_power_policy) {
3509 ALOGW("in->card_status or adev->card_status or adev->input_power offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303510 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303511 goto error_config;
3512 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303513
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003514 if (is_sco_in_device_type(&in->device_list)) {
Lakshman Chaluvaraju87f53aa2021-02-02 15:50:11 +05303515 if (!adev->bt_sco_on || audio_extn_a2dp_source_is_ready()) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303516 ALOGE("%s: SCO profile is not ready, return error", __func__);
3517 ret = -EIO;
3518 goto error_config;
3519 }
3520 }
3521
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003522 /* Check if source matches incall recording usecase criteria */
3523 ret = voice_check_and_set_incall_rec_usecase(adev, in);
3524 if (ret)
3525 goto error_config;
3526 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07003527 ALOGV("%s: usecase(%d)", __func__, in->usecase);
3528
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303529 if (audio_extn_cin_attached_usecase(in))
3530 audio_extn_cin_acquire_usecase(in);
3531
Mingming Yin2664a5b2015-09-03 10:53:11 -07003532 if (get_usecase_from_list(adev, in->usecase) != NULL) {
3533 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
3534 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Weiyin Jiang38c0e612020-09-10 16:10:51 +08003535 ret = -EINVAL;
3536 goto error_config;
Mingming Yin2664a5b2015-09-03 10:53:11 -07003537 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003538
Eric Laurentb23d5282013-05-14 15:27:20 -07003539 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003540 if (in->pcm_device_id < 0) {
3541 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
3542 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08003543 ret = -EINVAL;
3544 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003545 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003546
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003547 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003548
3549 if (!uc_info) {
3550 ret = -ENOMEM;
3551 goto error_config;
3552 }
3553
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003554 uc_info->id = in->usecase;
3555 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003556 uc_info->stream.in = in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003557 list_init(&uc_info->device_list);
3558 assign_devices(&uc_info->device_list, &in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003559 uc_info->in_snd_device = SND_DEVICE_NONE;
3560 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003561
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003562 list_add_tail(&adev->usecase_list, &uc_info->list);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003563 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303564 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3565 adev->perf_lock_opts,
3566 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003567 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003568
Derek Chenea197282019-01-07 17:35:01 -08003569 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3570 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003571
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05303572 android_atomic_acquire_cas(true, false, &(in->capture_stopped));
3573
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303574 if (audio_extn_cin_attached_usecase(in)) {
Manish Dewangan46e07982018-12-13 18:18:59 +05303575 ret = audio_extn_cin_open_input_stream(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303576 if (ret)
3577 goto error_open;
3578 else
3579 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003580 }
3581
Haynes Mathew George16081042017-05-31 17:16:49 -07003582 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003583 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003584 ALOGE("%s: pcm stream not ready", __func__);
3585 goto error_open;
3586 }
3587 ret = pcm_start(in->pcm);
3588 if (ret < 0) {
3589 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3590 goto error_open;
3591 }
3592 } else {
3593 unsigned int flags = PCM_IN | PCM_MONOTONIC;
3594 unsigned int pcm_open_retry_count = 0;
3595
Zhou Song62ea0282020-03-22 19:53:01 +08003596 if ((in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) ||
3597 (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003598 flags |= PCM_MMAP | PCM_NOIRQ;
3599 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
3600 } else if (in->realtime) {
3601 flags |= PCM_MMAP | PCM_NOIRQ;
3602 }
3603
Garmond Leunge2433c32017-09-28 21:51:22 -07003604 if (audio_extn_ffv_get_stream() == in) {
3605 ALOGD("%s: ffv stream, update pcm config", __func__);
3606 audio_extn_ffv_update_pcm_config(&config);
3607 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003608 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3609 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3610
3611 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003612 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07003613 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07003614 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003615 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303616 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303617 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3618 adev->card_status = CARD_STATUS_OFFLINE;
3619 in->card_status = CARD_STATUS_OFFLINE;
3620 ret = -EIO;
3621 goto error_open;
3622 }
3623
Haynes Mathew George16081042017-05-31 17:16:49 -07003624 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3625 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3626 if (in->pcm != NULL) {
3627 pcm_close(in->pcm);
3628 in->pcm = NULL;
3629 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003630 if (pcm_open_retry_count == 0) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003631 ret = -EIO;
3632 goto error_open;
3633 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003634 pcm_open_retry_count--;
Haynes Mathew George16081042017-05-31 17:16:49 -07003635 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3636 continue;
3637 }
3638 break;
3639 }
3640
3641 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003642 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07003643 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003644 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003645 if (ret < 0) {
3646 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3647 pcm_close(in->pcm);
3648 in->pcm = NULL;
3649 goto error_open;
3650 }
Vaibhav Raut5f3bf222023-02-06 17:45:22 +05303651 if (in->flags & (AUDIO_INPUT_FLAG_FAST | AUDIO_INPUT_FLAG_RAW))
Narsinga Rao Chellaa6e1f702021-10-22 13:57:32 +05303652 register_in_stream(in);
Haynes Mathew George16081042017-05-31 17:16:49 -07003653 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003654 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07003655 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003656 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003657 if (ret < 0) {
3658 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003659 pcm_close(in->pcm);
3660 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003661 goto error_open;
3662 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003663 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003664 }
3665
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003666 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07003667 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
3668 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003669
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003670 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303671 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
3672
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303673done_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003674 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303675 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Manisha Agarwal4c2402e2020-10-21 12:02:57 +05303676 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303677 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003678 return ret;
3679
3680error_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003681 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303682 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003683 stop_input_stream(in);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003684
Eric Laurentc8400632013-02-14 19:04:54 -08003685error_config:
Weiyin Jiang38c0e612020-09-10 16:10:51 +08003686 if (audio_extn_cin_attached_usecase(in))
3687 audio_extn_cin_close_input_stream(in);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303688 /*
3689 * sleep 50ms to allow sufficient time for kernel
3690 * drivers to recover incases like SSR.
3691 */
3692 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003693 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303694 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003695 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003696}
3697
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003698void lock_input_stream(struct stream_in *in)
3699{
3700 pthread_mutex_lock(&in->pre_lock);
3701 pthread_mutex_lock(&in->lock);
3702 pthread_mutex_unlock(&in->pre_lock);
3703}
3704
3705void lock_output_stream(struct stream_out *out)
3706{
3707 pthread_mutex_lock(&out->pre_lock);
3708 pthread_mutex_lock(&out->lock);
3709 pthread_mutex_unlock(&out->pre_lock);
3710}
3711
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003712/* must be called with out->lock locked */
3713static int send_offload_cmd_l(struct stream_out* out, int command)
3714{
3715 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
3716
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003717 if (!cmd) {
3718 ALOGE("failed to allocate mem for command 0x%x", command);
3719 return -ENOMEM;
3720 }
3721
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003722 ALOGVV("%s %d", __func__, command);
3723
3724 cmd->cmd = command;
3725 list_add_tail(&out->offload_cmd_list, &cmd->node);
3726 pthread_cond_signal(&out->offload_cond);
3727 return 0;
3728}
3729
Gautam Manam14c198b2020-12-24 14:08:04 +05303730/* must be called with out->lock */
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003731static void stop_compressed_output_l(struct stream_out *out)
3732{
Gautam Manam14c198b2020-12-24 14:08:04 +05303733 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003734 out->offload_state = OFFLOAD_STATE_IDLE;
Gautam Manam14c198b2020-12-24 14:08:04 +05303735 pthread_mutex_unlock(&out->latch_lock);
Weiyin Jiang906db3c2021-03-02 13:17:04 +08003736
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003737 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003738 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003739 if (out->compr != NULL) {
3740 compress_stop(out->compr);
3741 while (out->offload_thread_blocked) {
3742 pthread_cond_wait(&out->cond, &out->lock);
3743 }
3744 }
3745}
3746
Varun Balaraje49253e2017-07-06 19:48:56 +05303747bool is_interactive_usecase(audio_usecase_t uc_id)
3748{
3749 unsigned int i;
3750 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
3751 if (uc_id == interactive_usecases[i])
3752 return true;
3753 }
3754 return false;
3755}
3756
3757static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
3758{
3759 audio_usecase_t ret_uc = USECASE_INVALID;
3760 unsigned int intract_uc_index;
3761 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3762
3763 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
3764 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
3765 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
3766 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
3767 ret_uc = interactive_usecases[intract_uc_index];
3768 break;
3769 }
3770 }
3771
3772 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
3773 return ret_uc;
3774}
3775
3776static void free_interactive_usecase(struct audio_device *adev,
3777 audio_usecase_t uc_id)
3778{
3779 unsigned int interact_uc_index;
3780 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3781
3782 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
3783 if (interactive_usecases[interact_uc_index] == uc_id) {
3784 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
3785 break;
3786 }
3787 }
3788 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
3789}
3790
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003791bool is_offload_usecase(audio_usecase_t uc_id)
3792{
3793 unsigned int i;
3794 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
3795 if (uc_id == offload_usecases[i])
3796 return true;
3797 }
3798 return false;
3799}
3800
Dhananjay Kumarac341582017-02-23 23:42:25 +05303801static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003802{
vivek mehta446c3962015-09-14 10:57:35 -07003803 audio_usecase_t ret_uc = USECASE_INVALID;
3804 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003805 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003806 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05303807 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07003808 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
3809 else
3810 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003811
vivek mehta446c3962015-09-14 10:57:35 -07003812 pthread_mutex_lock(&adev->lock);
3813 if (get_usecase_from_list(adev, ret_uc) != NULL)
3814 ret_uc = USECASE_INVALID;
3815 pthread_mutex_unlock(&adev->lock);
3816
3817 return ret_uc;
3818 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003819
3820 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003821 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3822 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3823 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3824 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003825 break;
3826 }
3827 }
vivek mehta446c3962015-09-14 10:57:35 -07003828
3829 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3830 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003831}
3832
3833static void free_offload_usecase(struct audio_device *adev,
3834 audio_usecase_t uc_id)
3835{
vivek mehta446c3962015-09-14 10:57:35 -07003836 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003837 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003838
3839 if (!adev->multi_offload_enable)
3840 return;
3841
3842 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3843 if (offload_usecases[offload_uc_index] == uc_id) {
3844 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003845 break;
3846 }
3847 }
3848 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3849}
3850
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003851static void *offload_thread_loop(void *context)
3852{
3853 struct stream_out *out = (struct stream_out *) context;
3854 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003855 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003856
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003857 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08003858 set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003859 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3860
3861 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003862 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003863 out->offload_state = OFFLOAD_STATE_IDLE;
3864 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003865 for (;;) {
3866 struct offload_cmd *cmd = NULL;
3867 stream_callback_event_t event;
3868 bool send_callback = false;
3869
3870 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3871 __func__, list_empty(&out->offload_cmd_list),
3872 out->offload_state);
3873 if (list_empty(&out->offload_cmd_list)) {
3874 ALOGV("%s SLEEPING", __func__);
3875 pthread_cond_wait(&out->offload_cond, &out->lock);
3876 ALOGV("%s RUNNING", __func__);
3877 continue;
3878 }
3879
3880 item = list_head(&out->offload_cmd_list);
3881 cmd = node_to_item(item, struct offload_cmd, node);
3882 list_remove(item);
3883
3884 ALOGVV("%s STATE %d CMD %d out->compr %p",
3885 __func__, out->offload_state, cmd->cmd, out->compr);
3886
3887 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3888 free(cmd);
3889 break;
3890 }
3891
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003892 // allow OFFLOAD_CMD_ERROR reporting during standby
3893 // this is needed to handle failures during compress_open
3894 // Note however that on a pause timeout, the stream is closed
3895 // and no offload usecase will be active. Therefore this
3896 // special case is needed for compress_open failures alone
3897 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3898 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003899 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003900 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003901 pthread_cond_signal(&out->cond);
3902 continue;
3903 }
3904 out->offload_thread_blocked = true;
3905 pthread_mutex_unlock(&out->lock);
3906 send_callback = false;
3907 switch(cmd->cmd) {
3908 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003909 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003910 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003911 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003912 send_callback = true;
3913 event = STREAM_CBK_EVENT_WRITE_READY;
3914 break;
3915 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003916 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303917 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003918 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303919 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003920 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303921 if (ret < 0)
3922 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303923 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303924 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003925 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003926 else
3927 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003928 if (-ENETRESET != ret && !(-EINTR == ret &&
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05003929 (CARD_STATUS_OFFLINE == out->card_status ||
3930 POWER_POLICY_STATUS_OFFLINE == adev->out_power_policy))) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303931 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303932 pthread_mutex_lock(&out->lock);
3933 out->send_new_metadata = 1;
3934 out->send_next_track_params = true;
3935 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303936 event = STREAM_CBK_EVENT_DRAIN_READY;
3937 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3938 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303939 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003940 break;
3941 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003942 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003943 ret = compress_drain(out->compr);
3944 ALOGD("copl(%p):out of compress_drain", out);
3945 // EINTR check avoids drain interruption due to SSR
3946 if (-ENETRESET != ret && !(-EINTR == ret &&
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05003947 (CARD_STATUS_OFFLINE == out->card_status ||
3948 POWER_POLICY_STATUS_OFFLINE == adev->out_power_policy))) {
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003949 send_callback = true;
3950 event = STREAM_CBK_EVENT_DRAIN_READY;
3951 } else
3952 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003953 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303954 case OFFLOAD_CMD_ERROR:
3955 ALOGD("copl(%p): sending error callback to AF", out);
3956 send_callback = true;
3957 event = STREAM_CBK_EVENT_ERROR;
3958 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003959 default:
3960 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3961 break;
3962 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003963 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003964 out->offload_thread_blocked = false;
3965 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003966 if (send_callback && out->client_callback) {
3967 ALOGVV("%s: sending client_callback event %d", __func__, event);
3968 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003969 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003970 free(cmd);
3971 }
3972
3973 pthread_cond_signal(&out->cond);
3974 while (!list_empty(&out->offload_cmd_list)) {
3975 item = list_head(&out->offload_cmd_list);
3976 list_remove(item);
3977 free(node_to_item(item, struct offload_cmd, node));
3978 }
3979 pthread_mutex_unlock(&out->lock);
3980
3981 return NULL;
3982}
3983
3984static int create_offload_callback_thread(struct stream_out *out)
3985{
3986 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3987 list_init(&out->offload_cmd_list);
3988 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3989 offload_thread_loop, out);
3990 return 0;
3991}
3992
3993static int destroy_offload_callback_thread(struct stream_out *out)
3994{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003995 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003996 stop_compressed_output_l(out);
3997 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3998
3999 pthread_mutex_unlock(&out->lock);
4000 pthread_join(out->offload_thread, (void **) NULL);
4001 pthread_cond_destroy(&out->offload_cond);
4002
4003 return 0;
4004}
4005
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004006static int stop_output_stream(struct stream_out *out)
4007{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304008 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004009 struct audio_usecase *uc_info;
4010 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08004011 bool has_voip_usecase =
4012 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004013
Eric Laurent994a6932013-07-17 11:51:42 -07004014 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004015 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004016 uc_info = get_usecase_from_list(adev, out->usecase);
4017 if (uc_info == NULL) {
4018 ALOGE("%s: Could not find the usecase (%d) in the list",
4019 __func__, out->usecase);
4020 return -EINVAL;
4021 }
4022
Zhou Songbaddf9f2020-11-20 13:57:39 +08004023 out->a2dp_muted = false;
4024
Derek Chenea197282019-01-07 17:35:01 -08004025 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
4026 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08004027
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004028 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304029 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004030 if (adev->visualizer_stop_output != NULL)
4031 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004032
4033 audio_extn_dts_remove_state_notifier_node(out->usecase);
4034
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004035 if (adev->offload_effects_stop_output != NULL)
4036 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07004037 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
4038 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4039 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004040 }
Eric Laurentc4aef752013-09-12 17:45:53 -07004041
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004042 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
4043 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07004044 voice_set_device_mute_flag(adev, false);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004045 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07004046
Eric Laurent150dbfe2013-02-27 14:31:02 -08004047 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07004048 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004049
4050 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07004051 disable_snd_device(adev, uc_info->out_snd_device);
Zhou Songd9bd9302020-08-04 16:34:45 +08004052 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
4053 disable_snd_device(adev, SND_DEVICE_OUT_HAPTICS);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004054
Aalique Grahame22e49102018-12-18 14:23:57 -08004055 audio_extn_extspk_update(adev->extspk);
4056
Xiaojun Sang785b5da2017-08-03 15:52:29 +08004057 if (is_offload_usecase(out->usecase)) {
4058 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
4059 adev->dsp_bit_width_enforce_mode,
4060 false);
4061 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004062 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07004063 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
4064 false);
4065
4066 if (ret != 0)
4067 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
4068 /* default service interval was successfully updated,
4069 reopen USB backend with new service interval */
4070 ret = 0;
4071 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08004072
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004073 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304074 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004075 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304076 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004077 ALOGV("Disable passthrough , reset mixer to pcm");
4078 /* NO_PASSTHROUGH */
Meng Wang4c32fb42020-01-16 17:57:11 +08004079#ifdef AUDIO_GKI_ENABLED
4080 /* out->compr_config.codec->reserved[0] is for compr_passthr */
4081 out->compr_config.codec->reserved[0] = 0;
4082#else
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004083 out->compr_config.codec->compr_passthr = 0;
Meng Wang4c32fb42020-01-16 17:57:11 +08004084#endif
Mingming Yin21854652016-04-13 11:54:02 -07004085 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004086 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
4087 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07004088
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304089 /* Must be called after removing the usecase from list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004090 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL))
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05304091 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304092
Manish Dewangan21a850a2017-08-14 12:03:55 +05304093 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07004094 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
4095 if (ret < 0)
4096 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
4097 }
4098
Zhou Song642ec432020-12-23 16:11:10 +08004099 /* trigger voip input to reroute when voip output changes to hearing aid */
Aalique Grahame22e49102018-12-18 14:23:57 -08004100 if (has_voip_usecase ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004101 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08004102 struct listnode *node;
4103 struct audio_usecase *usecase;
4104 list_for_each(node, &adev->usecase_list) {
4105 usecase = node_to_item(node, struct audio_usecase, list);
Zhou Song642ec432020-12-23 16:11:10 +08004106 if (usecase->type == PCM_PLAYBACK || usecase == uc_info ||
4107 (usecase->type == PCM_CAPTURE &&
Revathi Uddarajud9f23d92020-07-27 10:55:06 +05304108 usecase->id != USECASE_AUDIO_RECORD_VOIP &&
Zhou Song642ec432020-12-23 16:11:10 +08004109 usecase->id != USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY))
Aalique Grahame22e49102018-12-18 14:23:57 -08004110 continue;
4111
4112 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
4113 __func__, usecase->id, use_case_table[usecase->id],
4114 out->usecase, use_case_table[out->usecase]);
4115 select_devices(adev, usecase->id);
4116 }
4117 }
4118
Zhenlin Lian4f947842022-05-14 15:50:52 +05304119 clear_devices(&uc_info->device_list);
Garmond Leung5fd0b552018-04-17 11:56:12 -07004120 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07004121 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004122 return ret;
4123}
4124
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004125struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
4126 unsigned int flags, unsigned int pcm_open_retry_count,
4127 struct pcm_config *config)
4128{
4129 struct pcm* pcm = NULL;
4130
4131 while (1) {
4132 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
4133 if (pcm == NULL || !pcm_is_ready(pcm)) {
4134 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
4135 if (pcm != NULL) {
4136 pcm_close(pcm);
4137 pcm = NULL;
4138 }
Weiyin Jiang72197252019-10-09 11:49:32 +08004139 if (pcm_open_retry_count == 0)
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004140 return NULL;
4141
Weiyin Jiang72197252019-10-09 11:49:32 +08004142 pcm_open_retry_count--;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004143 usleep(PROXY_OPEN_WAIT_TIME * 1000);
4144 continue;
4145 }
4146 break;
4147 }
4148
4149 if (pcm_is_ready(pcm)) {
4150 int ret = pcm_prepare(pcm);
4151 if (ret < 0) {
4152 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
4153 pcm_close(pcm);
4154 pcm = NULL;
4155 }
4156 }
4157
4158 return pcm;
4159}
4160
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004161int start_output_stream(struct stream_out *out)
4162{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004163 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004164 struct audio_usecase *uc_info;
4165 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004166 char mixer_ctl_name[128];
4167 struct mixer_ctl *ctl = NULL;
4168 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304169 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004170 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004171
Haynes Mathew George380745d2017-10-04 15:27:45 -07004172 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004173 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
4174 ret = -EINVAL;
4175 goto error_config;
4176 }
4177
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004178 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304179 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004180 get_device_types(&out->device_list), is_haptic_usecase);
4181
4182 bool is_speaker_active = compare_device_type(&out->device_list,
4183 AUDIO_DEVICE_OUT_SPEAKER);
4184 bool is_speaker_safe_active = compare_device_type(&out->device_list,
4185 AUDIO_DEVICE_OUT_SPEAKER_SAFE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304186
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304187 if (CARD_STATUS_OFFLINE == out->card_status ||
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05004188 CARD_STATUS_OFFLINE == adev->card_status ||
4189 POWER_POLICY_STATUS_OFFLINE == adev->out_power_policy) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304190 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05304191 ret = -EIO;
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004192 goto error_fatal;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304193 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05304194
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004195 //Update incall music usecase to reflect correct voice session
4196 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
4197 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
4198 if (ret != 0) {
4199 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
4200 __func__, ret);
4201 goto error_config;
4202 }
4203 }
4204
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004205 if (is_a2dp_out_device_type(&out->device_list)) {
Florian Pfister1a84f312018-07-19 14:38:18 +02004206 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004207 if (is_speaker_active || is_speaker_safe_active) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304208 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304209 } else {
Zhou Songd01e7a22020-09-23 22:49:01 +08004210 if (!is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304211 ALOGE("%s: A2DP profile is not ready, return error", __func__);
4212 ret = -EAGAIN;
4213 goto error_config;
4214 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304215 }
4216 }
4217 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004218 if (is_sco_out_device_type(&out->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304219 if (!adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004220 if (is_speaker_active) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304221 //combo usecase just by pass a2dp
4222 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004223 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304224 } else {
4225 ALOGE("%s: SCO profile is not ready, return error", __func__);
4226 ret = -EAGAIN;
4227 goto error_config;
4228 }
4229 }
4230 }
4231
Eric Laurentb23d5282013-05-14 15:27:20 -07004232 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004233 if (out->pcm_device_id < 0) {
4234 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
4235 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004236 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004237 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004238 }
4239
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004240 if (is_haptic_usecase) {
Meng Wang51d8c2a2020-04-27 15:23:21 +08004241 adev->haptic_pcm_device_id = platform_get_pcm_device_id(
4242 USECASE_AUDIO_PLAYBACK_HAPTICS, PCM_PLAYBACK);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004243 if (adev->haptic_pcm_device_id < 0) {
4244 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
4245 __func__, adev->haptic_pcm_device_id, out->usecase);
4246 ret = -EINVAL;
4247 goto error_config;
4248 }
4249 }
4250
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004251 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004252
4253 if (!uc_info) {
4254 ret = -ENOMEM;
4255 goto error_config;
4256 }
4257
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004258 uc_info->id = out->usecase;
4259 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004260 uc_info->stream.out = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004261 list_init(&uc_info->device_list);
4262 assign_devices(&uc_info->device_list, &out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004263 uc_info->in_snd_device = SND_DEVICE_NONE;
4264 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07004265
4266 /* This must be called before adding this usecase to the list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004267 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07004268 audio_extn_usb_check_and_set_svc_int(uc_info, true);
4269 /* USB backend is not reopened immediately.
4270 This is eventually done as part of select_devices */
4271 }
4272
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004273 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004274
Wei Wangf7ca6c92017-11-21 14:51:20 -08004275 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304276 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4277 adev->perf_lock_opts,
4278 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304279
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004280 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05304281 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304282 if (audio_extn_passthru_is_enabled() &&
4283 audio_extn_passthru_is_passthrough_stream(out)) {
4284 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304285 }
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 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304290 if (!a2dp_combo) {
4291 check_a2dp_restore_l(adev, out, false);
4292 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004293 struct listnode dev;
4294 list_init(&dev);
4295 assign_devices(&dev, &out->device_list);
4296 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4297 reassign_device_list(&out->device_list,
4298 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aalique Grahame22e49102018-12-18 14:23:57 -08004299 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004300 reassign_device_list(&out->device_list,
4301 AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304302 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004303 assign_devices(&out->device_list, &dev);
Zhenlin Lian4f947842022-05-14 15:50:52 +05304304 clear_devices(&dev);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304305 }
4306 } else {
Revathi Uddarajub26e3932020-06-10 14:51:02 +05304307 select_devices(adev, out->usecase);
4308 if (is_a2dp_out_device_type(&out->device_list) &&
4309 !adev->a2dp_started) {
4310 if (is_speaker_active || is_speaker_safe_active) {
4311 struct listnode dev;
4312 list_init(&dev);
4313 assign_devices(&dev, &out->device_list);
4314 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4315 reassign_device_list(&out->device_list,
4316 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
4317 else
4318 reassign_device_list(&out->device_list,
4319 AUDIO_DEVICE_OUT_SPEAKER, "");
4320 select_devices(adev, out->usecase);
4321 assign_devices(&out->device_list, &dev);
Zhenlin Lian4f947842022-05-14 15:50:52 +05304322 clear_devices(&dev);
Revathi Uddarajub26e3932020-06-10 14:51:02 +05304323 } else {
4324 ret = -EINVAL;
4325 goto error_open;
4326 }
4327 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304328 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004329
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004330 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
4331 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07004332 voice_set_device_mute_flag(adev, true);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004333 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07004334
Derek Chenea197282019-01-07 17:35:01 -08004335 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
4336 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08004337
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004338 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
4339 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07004340
4341 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07004342 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07004343 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4344 ALOGE("%s: pcm stream not ready", __func__);
4345 goto error_open;
4346 }
4347 ret = pcm_start(out->pcm);
4348 if (ret < 0) {
4349 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
4350 goto error_open;
4351 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07004352 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07004353 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004354 unsigned int flags = PCM_OUT;
4355 unsigned int pcm_open_retry_count = 0;
4356 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
4357 flags |= PCM_MMAP | PCM_NOIRQ;
4358 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004359 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08004360 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004361 } else
4362 flags |= PCM_MONOTONIC;
4363
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004364 if ((adev->vr_audio_mode_enabled) &&
4365 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
4366 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4367 "PCM_Dev %d Topology", out->pcm_device_id);
4368 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4369 if (!ctl) {
4370 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
4371 __func__, mixer_ctl_name);
4372 } else {
4373 //if success use ULLPP
4374 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
4375 __func__, mixer_ctl_name, out->pcm_device_id);
4376 //There is a still a possibility that some sessions
4377 // that request for FAST|RAW when 3D audio is active
4378 //can go through ULLPP. Ideally we expects apps to
4379 //listen to audio focus and stop concurrent playback
4380 //Also, we will look for mode flag (voice_in_communication)
4381 //before enabling the realtime flag.
4382 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
4383 }
4384 }
4385
Vatsal Bucha3f39f222021-06-29 16:16:55 +05304386 platform_set_stream_channel_map(adev->platform, out->channel_mask,
4387 out->pcm_device_id, -1, &out->channel_map_param.channel_map[0]);
Surendar Karka91fa3682018-07-02 18:12:12 +05304388
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004389 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
4390 flags, pcm_open_retry_count,
4391 &(out->config));
4392 if (out->pcm == NULL) {
4393 ret = -EIO;
4394 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004395 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004396
4397 if (is_haptic_usecase) {
4398 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
4399 adev->haptic_pcm_device_id,
4400 flags, pcm_open_retry_count,
4401 &(adev->haptics_config));
4402 // failure to open haptics pcm shouldnt stop audio,
4403 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07004404
4405 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
4406 ALOGD("%s: enable haptic audio synchronization", __func__);
4407 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
4408 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004409 }
4410
Zhou Song2b8f28f2017-09-11 10:51:38 +08004411 // apply volume for voip playback after path is set up
4412 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
4413 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05304414 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
4415 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304416 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
4417 out->apply_volume = false;
Derek Chenf13dd492018-11-13 14:53:51 -08004418 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
4419 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Krishna Kishor Jha10ad39f2022-02-21 17:02:47 +05304420#ifdef SOFT_VOLUME
4421 out_set_soft_volume_params(&out->stream);
4422#endif
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304423 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004424 } else {
Zhou Song79929fe2020-01-20 17:57:43 +08004425 /*
4426 * set custom channel map if:
4427 * 1. neither mono nor stereo clips i.e. channels > 2 OR
4428 * 2. custom channel map has been set by client
4429 * else default channel map of FC/FR/FL can always be set to DSP
4430 */
4431 if (popcount(out->channel_mask) > 2 || out->channel_map_param.channel_map[0])
4432 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Weiyin Jiang810a80d2021-01-18 16:04:31 +08004433 out->pcm_device_id, -1, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08004434 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
4435 adev->dsp_bit_width_enforce_mode,
4436 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004437 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07004438 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004439 out->compr = compress_open(adev->snd_card,
4440 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004441 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004442 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05304443 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05304444 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
4445 adev->card_status = CARD_STATUS_OFFLINE;
4446 out->card_status = CARD_STATUS_OFFLINE;
4447 ret = -EIO;
4448 goto error_open;
4449 }
4450
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004451 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004452 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004453 compress_close(out->compr);
4454 out->compr = NULL;
4455 ret = -EIO;
4456 goto error_open;
4457 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304458 /* compress_open sends params of the track, so reset the flag here */
4459 out->is_compr_metadata_avail = false;
4460
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004461 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004462 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07004463
Fred Oh3f43e742015-03-04 18:42:34 -08004464 /* Since small bufs uses blocking writes, a write will be blocked
4465 for the default max poll time (20s) in the event of an SSR.
4466 Reduce the poll time to observe and deal with SSR faster.
4467 */
Ashish Jain5106d362016-05-11 19:23:33 +05304468 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08004469 compress_set_max_poll_wait(out->compr, 1000);
4470 }
4471
Manish Dewangan69426c82017-01-30 17:35:36 +05304472 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05304473 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05304474
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004475 audio_extn_dts_create_state_notifier_node(out->usecase);
4476 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4477 popcount(out->channel_mask),
4478 out->playback_started);
4479
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004480#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304481 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004482 audio_extn_dolby_send_ddp_endp_params(adev);
4483#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05304484 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
4485 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004486 if (adev->visualizer_start_output != NULL)
4487 adev->visualizer_start_output(out->handle, out->pcm_device_id);
4488 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05304489 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004490 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004491 }
Derek Chenf13dd492018-11-13 14:53:51 -08004492
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004493 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf13dd492018-11-13 14:53:51 -08004494 /* Update cached volume from media to offload/direct stream */
4495 struct listnode *node = NULL;
4496 list_for_each(node, &adev->active_outputs_list) {
4497 streams_output_ctxt_t *out_ctxt = node_to_item(node,
4498 streams_output_ctxt_t,
4499 list);
4500 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
4501 out->volume_l = out_ctxt->output->volume_l;
4502 out->volume_r = out_ctxt->output->volume_r;
4503 }
4504 }
4505 out_set_compr_volume(&out->stream,
4506 out->volume_l, out->volume_r);
4507 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004508 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004509
4510 if (ret == 0) {
Vaibhav Raut5f3bf222023-02-06 17:45:22 +05304511 if (out->flags & (AUDIO_OUTPUT_FLAG_FAST | AUDIO_OUTPUT_FLAG_RAW))
Narsinga Rao Chellaa6e1f702021-10-22 13:57:32 +05304512 register_out_stream(out);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004513 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07004514 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4515 ALOGE("%s: pcm stream not ready", __func__);
4516 goto error_open;
4517 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004518 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004519 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004520 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004521 if (ret < 0)
4522 goto error_open;
4523 }
4524 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004525 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304526 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Jaideep Sharma0fa53812020-09-17 09:00:11 +05304527 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004528
vivek mehtad15d2bf2019-05-17 13:35:10 -07004529 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
4530 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4531 audio_low_latency_hint_start();
4532 }
4533
Manish Dewangan21a850a2017-08-14 12:03:55 +05304534 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07004535 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07004536 if (ret < 0)
4537 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
4538 }
4539
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004540 // consider a scenario where on pause lower layers are tear down.
4541 // so on resume, swap mixer control need to be sent only when
4542 // backend is active, hence rather than sending from enable device
4543 // sending it from start of streamtream
4544
4545 platform_set_swap_channels(adev, true);
4546
Haynes Mathew George380745d2017-10-04 15:27:45 -07004547 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304548 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004549 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004550error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004551 if (adev->haptic_pcm) {
4552 pcm_close(adev->haptic_pcm);
4553 adev->haptic_pcm = NULL;
4554 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004555 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304556 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004557 stop_output_stream(out);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004558error_fatal:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05304559 /*
4560 * sleep 50ms to allow sufficient time for kernel
4561 * drivers to recover incases like SSR.
4562 */
4563 usleep(50000);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004564error_config:
Haynes Mathew George380745d2017-10-04 15:27:45 -07004565 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304566 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004567 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004568}
4569
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004570static int check_input_parameters(uint32_t sample_rate,
4571 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08004572 int channel_count,
4573 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004574{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004575 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004576
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304577 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
4578 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
4579 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07004580 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02004581 !audio_extn_compr_cap_format_supported(format) &&
4582 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004583 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004584
Aalique Grahame22e49102018-12-18 14:23:57 -08004585 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
4586 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
4587 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
4588 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
4589 return -EINVAL;
4590 }
4591
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004592 switch (channel_count) {
4593 case 1:
4594 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304595 case 3:
4596 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004597 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07004598 case 8:
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05304599 case 10:
4600 case 12:
4601 case 14:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004602 break;
4603 default:
4604 ret = -EINVAL;
4605 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004606
4607 switch (sample_rate) {
4608 case 8000:
4609 case 11025:
4610 case 12000:
4611 case 16000:
4612 case 22050:
4613 case 24000:
4614 case 32000:
4615 case 44100:
4616 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004617 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304618 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004619 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304620 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004621 break;
4622 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004623 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004624 }
4625
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004626 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004627}
4628
Naresh Tanniru04f71882018-06-26 17:46:22 +05304629
4630/** Add a value in a list if not already present.
4631 * @return true if value was successfully inserted or already present,
4632 * false if the list is full and does not contain the value.
4633 */
4634static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
4635 for (size_t i = 0; i < list_length; i++) {
4636 if (list[i] == value) return true; // value is already present
4637 if (list[i] == 0) { // no values in this slot
4638 list[i] = value;
4639 return true; // value inserted
4640 }
4641 }
4642 return false; // could not insert value
4643}
4644
4645/** Add channel_mask in supported_channel_masks if not already present.
4646 * @return true if channel_mask was successfully inserted or already present,
4647 * false if supported_channel_masks is full and does not contain channel_mask.
4648 */
4649static void register_channel_mask(audio_channel_mask_t channel_mask,
4650 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
4651 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
4652 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
4653}
4654
4655/** Add format in supported_formats if not already present.
4656 * @return true if format was successfully inserted or already present,
4657 * false if supported_formats is full and does not contain format.
4658 */
4659static void register_format(audio_format_t format,
4660 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
4661 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
4662 "%s: stream can not declare supporting its format %x", __func__, format);
4663}
4664/** Add sample_rate in supported_sample_rates if not already present.
4665 * @return true if sample_rate was successfully inserted or already present,
4666 * false if supported_sample_rates is full and does not contain sample_rate.
4667 */
4668static void register_sample_rate(uint32_t sample_rate,
4669 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
4670 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
4671 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
4672}
4673
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004674static inline uint32_t lcm(uint32_t num1, uint32_t num2)
4675{
4676 uint32_t high = num1, low = num2, temp = 0;
4677
4678 if (!num1 || !num2)
4679 return 0;
4680
4681 if (num1 < num2) {
4682 high = num2;
4683 low = num1;
4684 }
4685
4686 while (low != 0) {
4687 temp = low;
4688 low = high % low;
4689 high = temp;
4690 }
4691 return (num1 * num2)/high;
4692}
4693
4694static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
4695{
4696 uint32_t remainder = 0;
4697
4698 if (!multiplier)
4699 return num;
4700
4701 remainder = num % multiplier;
4702 if (remainder)
4703 num += (multiplier - remainder);
4704
4705 return num;
4706}
4707
Aalique Grahame22e49102018-12-18 14:23:57 -08004708static size_t get_stream_buffer_size(size_t duration_ms,
4709 uint32_t sample_rate,
4710 audio_format_t format,
4711 int channel_count,
4712 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004713{
4714 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004715 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004716
Aalique Grahame22e49102018-12-18 14:23:57 -08004717 size = (sample_rate * duration_ms) / 1000;
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +05304718 if (is_low_latency){
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +05304719#ifndef PLATFORM_AUTO
4720 size = configured_low_latency_capture_period_size;
4721#else
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +05304722 switch(sample_rate) {
4723 case 48000:
4724 size = 240;
4725 break;
4726 case 32000:
4727 size = 160;
4728 break;
4729 case 24000:
4730 size = 120;
4731 break;
4732 case 16000:
4733 size = 80;
4734 break;
4735 case 8000:
4736 size = 40;
4737 break;
4738 default:
4739 size = 240;
4740 }
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +05304741#endif
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +05304742 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304743
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004744 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08004745 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004746
Ralf Herzbd08d632018-09-28 15:50:49 +02004747 /* make sure the size is multiple of 32 bytes and additionally multiple of
4748 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004749 * At 48 kHz mono 16-bit PCM:
4750 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
4751 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004752 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004753 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004754 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07004755
4756 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004757}
4758
Aalique Grahame22e49102018-12-18 14:23:57 -08004759static size_t get_input_buffer_size(uint32_t sample_rate,
4760 audio_format_t format,
4761 int channel_count,
4762 bool is_low_latency)
4763{
Avinash Chandrad7296d42021-08-04 15:07:47 +05304764 bool is_usb_hifi = IS_USB_HIFI;
Aalique Grahame22e49102018-12-18 14:23:57 -08004765 /* Don't know if USB HIFI in this context so use true to be conservative */
4766 if (check_input_parameters(sample_rate, format, channel_count,
Avinash Chandrad7296d42021-08-04 15:07:47 +05304767 is_usb_hifi) != 0)
Aalique Grahame22e49102018-12-18 14:23:57 -08004768 return 0;
4769
4770 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4771 sample_rate,
4772 format,
4773 channel_count,
4774 is_low_latency);
4775}
4776
Derek Chenf6318be2017-06-12 17:16:24 -04004777size_t get_output_period_size(uint32_t sample_rate,
4778 audio_format_t format,
4779 int channel_count,
4780 int duration /*in millisecs*/)
Ashish Jain058165c2016-09-28 23:18:48 +05304781{
4782 size_t size = 0;
4783 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
4784
4785 if ((duration == 0) || (sample_rate == 0) ||
4786 (bytes_per_sample == 0) || (channel_count == 0)) {
4787 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
4788 bytes_per_sample, channel_count);
4789 return -EINVAL;
4790 }
4791
4792 size = (sample_rate *
4793 duration *
4794 bytes_per_sample *
4795 channel_count) / 1000;
4796 /*
4797 * To have same PCM samples for all channels, the buffer size requires to
4798 * be multiple of (number of channels * bytes per sample)
4799 * For writes to succeed, the buffer must be written at address which is multiple of 32
4800 */
4801 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
4802
4803 return (size/(channel_count * bytes_per_sample));
4804}
4805
Zhou Song48453a02018-01-10 17:50:59 +08004806static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05304807{
4808 uint64_t actual_frames_rendered = 0;
Weiyin Jiang4813da12020-05-28 00:37:28 +08004809 uint64_t written_frames = 0;
4810 uint64_t kernel_frames = 0;
4811 uint64_t dsp_frames = 0;
4812 uint64_t signed_frames = 0;
4813 size_t kernel_buffer_size = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304814
4815 /* This adjustment accounts for buffering after app processor.
4816 * It is based on estimated DSP latency per use case, rather than exact.
4817 */
George Gao9ba8a142020-07-23 14:30:03 -07004818 dsp_frames = platform_render_latency(out) *
Weiyin Jiang4813da12020-05-28 00:37:28 +08004819 out->sample_rate / 1000000LL;
Ashish Jain5106d362016-05-11 19:23:33 +05304820
Zhou Song48453a02018-01-10 17:50:59 +08004821 pthread_mutex_lock(&out->position_query_lock);
Weiyin Jiang4813da12020-05-28 00:37:28 +08004822 written_frames = out->written /
4823 (audio_bytes_per_sample(out->hal_ip_format) * popcount(out->channel_mask));
4824
Ashish Jain5106d362016-05-11 19:23:33 +05304825 /* not querying actual state of buffering in kernel as it would involve an ioctl call
4826 * which then needs protection, this causes delay in TS query for pcm_offload usecase
4827 * hence only estimate.
4828 */
Weiyin Jiang4813da12020-05-28 00:37:28 +08004829 kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
4830 kernel_frames = kernel_buffer_size /
4831 (audio_bytes_per_sample(out->hal_op_format) * popcount(out->channel_mask));
Ashish Jain5106d362016-05-11 19:23:33 +05304832
Weiyin Jiang4813da12020-05-28 00:37:28 +08004833 if (written_frames >= (kernel_frames + dsp_frames))
4834 signed_frames = written_frames - kernel_frames - dsp_frames;
Ashish Jain5106d362016-05-11 19:23:33 +05304835
Zhou Song48453a02018-01-10 17:50:59 +08004836 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05304837 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08004838 if (timestamp != NULL )
4839 *timestamp = out->writeAt;
4840 } else if (timestamp != NULL) {
4841 clock_gettime(CLOCK_MONOTONIC, timestamp);
4842 }
4843 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304844
Weiyin Jiang4813da12020-05-28 00:37:28 +08004845 ALOGVV("%s signed frames %lld written frames %lld kernel frames %lld dsp frames %lld",
4846 __func__, signed_frames, written_frames, kernel_frames, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05304847
4848 return actual_frames_rendered;
4849}
4850
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004851static uint32_t out_get_sample_rate(const struct audio_stream *stream)
4852{
4853 struct stream_out *out = (struct stream_out *)stream;
4854
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004855 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004856}
4857
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004858static int out_set_sample_rate(struct audio_stream *stream __unused,
4859 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004860{
4861 return -ENOSYS;
4862}
4863
4864static size_t out_get_buffer_size(const struct audio_stream *stream)
4865{
4866 struct stream_out *out = (struct stream_out *)stream;
4867
Varun Balaraje49253e2017-07-06 19:48:56 +05304868 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05304869 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05304870 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304871 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4872 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
4873 else
4874 return out->compr_config.fragment_size;
4875 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004876 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304877 else if (is_offload_usecase(out->usecase) &&
4878 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304879 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004880
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004881 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004882 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004883}
4884
4885static uint32_t out_get_channels(const struct audio_stream *stream)
4886{
4887 struct stream_out *out = (struct stream_out *)stream;
4888
4889 return out->channel_mask;
4890}
4891
4892static audio_format_t out_get_format(const struct audio_stream *stream)
4893{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004894 struct stream_out *out = (struct stream_out *)stream;
4895
4896 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004897}
4898
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004899static int out_set_format(struct audio_stream *stream __unused,
4900 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004901{
4902 return -ENOSYS;
4903}
4904
4905static int out_standby(struct audio_stream *stream)
4906{
4907 struct stream_out *out = (struct stream_out *)stream;
4908 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07004909 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004910
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304911 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4912 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004913
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004914 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004915 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004916 if (adev->adm_deregister_stream)
4917 adev->adm_deregister_stream(adev->adm_data, out->handle);
4918
Weiyin Jiang280ea742020-09-08 20:28:22 +08004919 if (is_offload_usecase(out->usecase)) {
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004920 stop_compressed_output_l(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08004921 }
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004922
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004923 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004924 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004925 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4926 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304927 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08004928 pthread_mutex_unlock(&adev->lock);
4929 pthread_mutex_unlock(&out->lock);
4930 ALOGD("VOIP output entered standby");
4931 return 0;
4932 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004933 if (out->pcm) {
4934 pcm_close(out->pcm);
4935 out->pcm = NULL;
4936 }
Meng Wanga09da002020-04-20 12:56:04 +08004937 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4938 if (adev->haptic_pcm) {
4939 pcm_close(adev->haptic_pcm);
4940 adev->haptic_pcm = NULL;
4941 }
4942
4943 if (adev->haptic_buffer != NULL) {
4944 free(adev->haptic_buffer);
4945 adev->haptic_buffer = NULL;
4946 adev->haptic_buffer_size = 0;
4947 }
4948 adev->haptic_pcm_device_id = 0;
4949 }
4950
Haynes Mathew George16081042017-05-31 17:16:49 -07004951 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4952 do_stop = out->playback_started;
4953 out->playback_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07004954
4955 if (out->mmap_shared_memory_fd >= 0) {
4956 ALOGV("%s: closing mmap_shared_memory_fd = %d",
4957 __func__, out->mmap_shared_memory_fd);
4958 close(out->mmap_shared_memory_fd);
4959 out->mmap_shared_memory_fd = -1;
4960 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004961 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004962 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004963 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304964 out->send_next_track_params = false;
4965 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004966 out->gapless_mdata.encoder_delay = 0;
4967 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004968 if (out->compr != NULL) {
4969 compress_close(out->compr);
4970 out->compr = NULL;
4971 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004972 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004973 if (do_stop) {
4974 stop_output_stream(out);
4975 }
Lakshman Chaluvaraju06677b42019-06-24 10:04:52 +05304976 // if fm is active route on selected device in UI
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004977 audio_extn_fm_route_on_selected_device(adev, &out->device_list);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004978 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004979 }
4980 pthread_mutex_unlock(&out->lock);
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07004981 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004982 return 0;
4983}
4984
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304985static int out_on_error(struct audio_stream *stream)
4986{
4987 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004988 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304989
4990 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004991 // always send CMD_ERROR for offload streams, this
4992 // is needed e.g. when SSR happens within compress_open
4993 // since the stream is active, offload_callback_thread is also active.
4994 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
4995 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004996 }
4997 pthread_mutex_unlock(&out->lock);
4998
4999 status = out_standby(&out->stream.common);
5000
5001 lock_output_stream(out);
5002 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08005003 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305004 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05305005
5006 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
5007 ALOGD("Setting previous card status if offline");
5008 out->prev_card_status_offline = true;
5009 }
5010
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305011 pthread_mutex_unlock(&out->lock);
5012
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07005013 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305014}
5015
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305016/*
Weiyin Jiang280ea742020-09-08 20:28:22 +08005017 * standby implementation without locks, assumes that the callee already
5018 * has taken adev and out lock.
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305019 */
5020int out_standby_l(struct audio_stream *stream)
5021{
5022 struct stream_out *out = (struct stream_out *)stream;
5023 struct audio_device *adev = out->dev;
5024
5025 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
5026 stream, out->usecase, use_case_table[out->usecase]);
5027
5028 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07005029 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305030 if (adev->adm_deregister_stream)
5031 adev->adm_deregister_stream(adev->adm_data, out->handle);
5032
Weiyin Jiang280ea742020-09-08 20:28:22 +08005033 if (is_offload_usecase(out->usecase)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305034 stop_compressed_output_l(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08005035 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305036
5037 out->standby = true;
5038 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
5039 voice_extn_compress_voip_close_output_stream(stream);
5040 out->started = 0;
5041 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07005042 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305043 return 0;
5044 } else if (!is_offload_usecase(out->usecase)) {
5045 if (out->pcm) {
5046 pcm_close(out->pcm);
5047 out->pcm = NULL;
5048 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005049 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
5050 if (adev->haptic_pcm) {
5051 pcm_close(adev->haptic_pcm);
5052 adev->haptic_pcm = NULL;
5053 }
5054
5055 if (adev->haptic_buffer != NULL) {
5056 free(adev->haptic_buffer);
5057 adev->haptic_buffer = NULL;
5058 adev->haptic_buffer_size = 0;
5059 }
5060 adev->haptic_pcm_device_id = 0;
5061 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305062 } else {
5063 ALOGD("copl(%p):standby", out);
5064 out->send_next_track_params = false;
5065 out->is_compr_metadata_avail = false;
5066 out->gapless_mdata.encoder_delay = 0;
5067 out->gapless_mdata.encoder_padding = 0;
5068 if (out->compr != NULL) {
5069 compress_close(out->compr);
5070 out->compr = NULL;
5071 }
5072 }
5073 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005074 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305075 }
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07005076 ALOGV("%s: exit", __func__);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305077 return 0;
5078}
5079
Aalique Grahame22e49102018-12-18 14:23:57 -08005080static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005081{
Aalique Grahame22e49102018-12-18 14:23:57 -08005082 struct stream_out *out = (struct stream_out *)stream;
5083
5084 // We try to get the lock for consistency,
5085 // but it isn't necessary for these variables.
5086 // If we're not in standby, we may be blocked on a write.
5087 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
5088 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
5089 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
Dechen Chai22768452021-07-30 09:29:16 +05305090#ifndef LINUX_ENABLED
Andy Hunga1f48fa2019-07-01 18:14:53 -07005091 char buffer[256]; // for statistics formatting
5092 if (!is_offload_usecase(out->usecase)) {
5093 simple_stats_to_string(&out->fifo_underruns, buffer, sizeof(buffer));
5094 dprintf(fd, " Fifo frame underruns: %s\n", buffer);
5095 }
5096
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005097 if (out->start_latency_ms.n > 0) {
5098 simple_stats_to_string(&out->start_latency_ms, buffer, sizeof(buffer));
5099 dprintf(fd, " Start latency ms: %s\n", buffer);
5100 }
Dechen Chai22768452021-07-30 09:29:16 +05305101#endif
Aalique Grahame22e49102018-12-18 14:23:57 -08005102 if (locked) {
5103 pthread_mutex_unlock(&out->lock);
5104 }
5105
Dechen Chai22768452021-07-30 09:29:16 +05305106#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -08005107 // dump error info
5108 (void)error_log_dump(
5109 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Dechen Chai22768452021-07-30 09:29:16 +05305110#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005111 return 0;
5112}
5113
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005114static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
5115{
5116 int ret = 0;
5117 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08005118
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005119 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08005120 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005121 return -EINVAL;
5122 }
5123
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05305124 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08005125
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005126 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
5127 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05305128 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005129 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005130 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
5131 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05305132 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005133 }
5134
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005135 ALOGV("%s new encoder delay %u and padding %u", __func__,
5136 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
5137
5138 return 0;
5139}
5140
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005141static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
5142{
5143 return out == adev->primary_output || out == adev->voice_tx_output;
5144}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005145
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305146// note: this call is safe only if the stream_cb is
5147// removed first in close_output_stream (as is done now).
5148static void out_snd_mon_cb(void * stream, struct str_parms * parms)
5149{
5150 if (!stream || !parms)
5151 return;
5152
5153 struct stream_out *out = (struct stream_out *)stream;
5154 struct audio_device *adev = out->dev;
5155
5156 card_status_t status;
5157 int card;
5158 if (parse_snd_card_status(parms, &card, &status) < 0)
5159 return;
5160
5161 pthread_mutex_lock(&adev->lock);
5162 bool valid_cb = (card == adev->snd_card);
5163 pthread_mutex_unlock(&adev->lock);
5164
5165 if (!valid_cb)
5166 return;
5167
5168 lock_output_stream(out);
5169 if (out->card_status != status)
5170 out->card_status = status;
5171 pthread_mutex_unlock(&out->lock);
5172
5173 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
5174 use_case_table[out->usecase],
5175 status == CARD_STATUS_OFFLINE ? "offline" : "online");
5176
Aditya Bavanari59ebed42019-02-05 17:44:57 +05305177 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305178 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05305179 if (voice_is_call_state_active(adev) &&
5180 out == adev->primary_output) {
5181 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
5182 pthread_mutex_lock(&adev->lock);
5183 voice_stop_call(adev);
5184 adev->mode = AUDIO_MODE_NORMAL;
5185 pthread_mutex_unlock(&adev->lock);
5186 }
5187 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305188 return;
5189}
5190
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005191int route_output_stream(struct stream_out *out,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005192 struct listnode *devices)
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005193{
5194 struct audio_device *adev = out->dev;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005195 int ret = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005196 struct listnode new_devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005197 bool bypass_a2dp = false;
5198 bool reconfig = false;
5199 unsigned long service_interval = 0;
5200
5201 ALOGD("%s: enter: usecase(%d: %s) devices %x",
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005202 __func__, out->usecase, use_case_table[out->usecase], get_device_types(devices));
5203
5204 list_init(&new_devices);
5205 assign_devices(&new_devices, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005206
5207 lock_output_stream(out);
5208 pthread_mutex_lock(&adev->lock);
5209
5210 /*
5211 * When HDMI cable is unplugged the music playback is paused and
5212 * the policy manager sends routing=0. But the audioflinger continues
5213 * to write data until standby time (3sec). As the HDMI core is
5214 * turned off, the write gets blocked.
5215 * Avoid this by routing audio to speaker until standby.
5216 */
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08005217 if (is_single_device_type_equal(&out->device_list,
5218 AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005219 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005220 !audio_extn_passthru_is_passthrough_stream(out) &&
5221 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005222 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005223 }
5224 /*
5225 * When A2DP is disconnected the
5226 * music playback is paused and the policy manager sends routing=0
5227 * But the audioflinger continues to write data until standby time
5228 * (3sec). As BT is turned off, the write gets blocked.
5229 * Avoid this by routing audio to speaker until standby.
5230 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005231 if (is_a2dp_out_device_type(&out->device_list) &&
5232 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005233 !audio_extn_a2dp_source_is_ready() &&
5234 !adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005235 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005236 }
5237 /*
Weiyin Jiangabedea32020-12-09 12:49:19 +08005238 * When USB headset is disconnected the music playback paused
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005239 * and the policy manager send routing=0. But if the USB is connected
5240 * back before the standby time, AFE is not closed and opened
5241 * when USB is connected back. So routing to speker will guarantee
5242 * AFE reconfiguration and AFE will be opend once USB is connected again
5243 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005244 if (is_usb_out_device_type(&out->device_list) &&
5245 list_empty(&new_devices) &&
5246 !audio_extn_usb_connected(NULL)) {
Sujin Panicker84d953a2020-11-16 17:39:54 +05305247 if (adev->mode == AUDIO_MODE_IN_CALL || adev->mode == AUDIO_MODE_IN_COMMUNICATION)
5248 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_EARPIECE, "");
5249 else
5250 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005251 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005252 /* To avoid a2dp to sco overlapping / BT device improper state
5253 * check with BT lib about a2dp streaming support before routing
5254 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005255 if (is_a2dp_out_device_type(&new_devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005256 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005257 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER) ||
5258 compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005259 //combo usecase just by pass a2dp
5260 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
5261 bypass_a2dp = true;
5262 } else {
5263 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
5264 /* update device to a2dp and don't route as BT returned error
5265 * However it is still possible a2dp routing called because
5266 * of current active device disconnection (like wired headset)
5267 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005268 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005269 pthread_mutex_unlock(&adev->lock);
5270 pthread_mutex_unlock(&out->lock);
5271 goto error;
5272 }
5273 }
5274 }
5275
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005276 // Workaround: If routing to an non existing usb device, fail gracefully
5277 // The routing request will otherwise block during 10 second
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005278 if (is_usb_out_device_type(&new_devices)) {
5279 struct str_parms *parms =
5280 str_parms_create_str(get_usb_device_address(&new_devices));
5281 if (!parms)
5282 goto error;
Weiyin Jiangabedea32020-12-09 12:49:19 +08005283 if (!audio_extn_usb_connected(NULL)) {
5284 ALOGW("%s: ignoring rerouting to non existing USB card", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005285 pthread_mutex_unlock(&adev->lock);
5286 pthread_mutex_unlock(&out->lock);
5287 str_parms_destroy(parms);
5288 ret = -ENOSYS;
5289 goto error;
5290 }
5291 str_parms_destroy(parms);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005292 }
5293
Weiyin Jiang80c8f9a2020-01-10 20:42:08 +08005294 // Workaround: If routing to an non existing hdmi device, fail gracefully
5295 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
5296 (platform_get_edid_info_v2(adev->platform,
5297 out->extconn.cs.controller,
5298 out->extconn.cs.stream) != 0)) {
5299 ALOGW("out_set_parameters() ignoring rerouting to non existing HDMI/DP");
5300 pthread_mutex_unlock(&adev->lock);
5301 pthread_mutex_unlock(&out->lock);
5302 ret = -ENOSYS;
5303 goto error;
5304 }
5305
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005306 /*
5307 * select_devices() call below switches all the usecases on the same
5308 * backend to the new device. Refer to check_usecases_codec_backend() in
5309 * the select_devices(). But how do we undo this?
5310 *
5311 * For example, music playback is active on headset (deep-buffer usecase)
5312 * and if we go to ringtones and select a ringtone, low-latency usecase
5313 * will be started on headset+speaker. As we can't enable headset+speaker
5314 * and headset devices at the same time, select_devices() switches the music
5315 * playback to headset+speaker while starting low-lateny usecase for ringtone.
5316 * So when the ringtone playback is completed, how do we undo the same?
5317 *
5318 * We are relying on the out_set_parameters() call on deep-buffer output,
5319 * once the ringtone playback is ended.
5320 * NOTE: We should not check if the current devices are same as new devices.
5321 * Because select_devices() must be called to switch back the music
5322 * playback to headset.
5323 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005324 if (!list_empty(&new_devices)) {
5325 bool same_dev = compare_devices(&out->device_list, &new_devices);
5326 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005327
5328 if (output_drives_call(adev, out)) {
5329 if (!voice_is_call_state_active(adev)) {
5330 if (adev->mode == AUDIO_MODE_IN_CALL) {
5331 adev->current_call_output = out;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005332 ret = voice_start_call(adev);
5333 }
5334 } else {
Kunlei Zhang253ad102020-10-14 16:21:28 +08005335 platform_is_volume_boost_supported_device(adev->platform, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005336 adev->current_call_output = out;
5337 voice_update_devices_for_all_voice_usecases(adev);
5338 }
5339 }
5340
Mingshu Pang971ff702020-09-09 15:28:22 +08005341 if (is_usb_out_device_type(&out->device_list)) {
5342 service_interval = audio_extn_usb_find_service_interval(false, true /*playback*/);
5343 audio_extn_usb_set_service_interval(true /*playback*/,
5344 service_interval,
5345 &reconfig);
5346 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
5347 }
5348
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005349 if (!out->standby) {
5350 if (!same_dev) {
5351 ALOGV("update routing change");
5352 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
5353 adev->perf_lock_opts,
5354 adev->perf_lock_opts_size);
5355 if (adev->adm_on_routing_change)
5356 adev->adm_on_routing_change(adev->adm_data,
5357 out->handle);
5358 }
5359 if (!bypass_a2dp) {
5360 select_devices(adev, out->usecase);
5361 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005362 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
5363 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005364 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005365 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005366 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005367 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005368 }
5369
5370 if (!same_dev) {
5371 // on device switch force swap, lower functions will make sure
5372 // to check if swap is allowed or not.
5373 platform_set_swap_channels(adev, true);
5374 audio_extn_perf_lock_release(&adev->perf_lock_handle);
5375 }
Zhou Songbaddf9f2020-11-20 13:57:39 +08005376 pthread_mutex_lock(&out->latch_lock);
5377 if (!is_a2dp_out_device_type(&out->device_list) || audio_extn_a2dp_source_is_ready()) {
5378 if (out->a2dp_muted) {
5379 out->a2dp_muted = false;
5380 if (is_offload_usecase(out->usecase))
5381 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5382 else if (out->usecase != USECASE_AUDIO_PLAYBACK_VOIP)
5383 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Weiyin Jiang280ea742020-09-08 20:28:22 +08005384 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005385 }
Zhou Songbaddf9f2020-11-20 13:57:39 +08005386 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP && !out->a2dp_muted)
5387 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
5388 pthread_mutex_unlock(&out->latch_lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005389 }
5390 }
5391
5392 pthread_mutex_unlock(&adev->lock);
5393 pthread_mutex_unlock(&out->lock);
5394
5395 /*handles device and call state changes*/
5396 audio_extn_extspk_update(adev->extspk);
5397
Revathi Uddaraju4255a632021-12-02 05:11:13 -08005398 clear_devices(&new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005399error:
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005400 ALOGV("%s: exit: code(%d)", __func__, ret);
5401 return ret;
5402}
5403
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005404static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
5405{
5406 struct stream_out *out = (struct stream_out *)stream;
5407 struct audio_device *adev = out->dev;
5408 struct str_parms *parms;
5409 char value[32];
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005410 int ret = 0, err;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005411 int ext_controller = -1;
5412 int ext_stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005413
sangwoobc677242013-08-08 16:53:43 +09005414 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005415 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005416 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305417 if (!parms)
5418 goto error;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005419
5420 err = platform_get_controller_stream_from_params(parms, &ext_controller,
5421 &ext_stream);
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08005422 if (err == 0) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005423 out->extconn.cs.controller = ext_controller;
5424 out->extconn.cs.stream = ext_stream;
5425 ALOGD("%s: usecase(%s) new controller/stream (%d/%d)", __func__,
5426 use_case_table[out->usecase], out->extconn.cs.controller,
5427 out->extconn.cs.stream);
5428 }
5429
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005430 if (out == adev->primary_output) {
5431 pthread_mutex_lock(&adev->lock);
5432 audio_extn_set_parameters(adev, parms);
5433 pthread_mutex_unlock(&adev->lock);
5434 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005435 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005436 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005437 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005438
5439 audio_extn_dts_create_state_notifier_node(out->usecase);
5440 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5441 popcount(out->channel_mask),
5442 out->playback_started);
5443
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08005444 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005445 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005446
Surendar Karkaf51b5842018-04-26 11:28:38 +05305447 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
5448 sizeof(value));
5449 if (err >= 0) {
5450 if (!strncmp("true", value, sizeof("true")) || atoi(value))
5451 audio_extn_send_dual_mono_mixing_coefficients(out);
5452 }
5453
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305454 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5455 if (err >= 0) {
5456 strlcpy(out->profile, value, sizeof(out->profile));
5457 ALOGV("updating stream profile with value '%s'", out->profile);
5458 lock_output_stream(out);
5459 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
5460 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005461 &out->device_list, out->flags,
5462 out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305463 out->sample_rate, out->bit_width,
5464 out->channel_mask, out->profile,
5465 &out->app_type_cfg);
5466 pthread_mutex_unlock(&out->lock);
5467 }
5468
Alexy Joseph98988832017-01-13 14:56:59 -08005469 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005470 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
5471 // and vendor.audio.hal.output.suspend.supported is set to true
5472 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08005473 //check suspend parameter only for low latency and if the property
5474 //is enabled
5475 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
5476 ALOGI("%s: got suspend_playback %s", __func__, value);
5477 lock_output_stream(out);
5478 if (!strncmp(value, "false", 5)) {
5479 //suspend_playback=false is supposed to set QOS value back to 75%
5480 //the mixer control sent with value Enable will achieve that
5481 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5482 } else if (!strncmp (value, "true", 4)) {
5483 //suspend_playback=true is supposed to remove QOS value
5484 //resetting the mixer control will set the default value
5485 //for the mixer control which is Disable and this removes the QOS vote
5486 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5487 } else {
5488 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
5489 " got %s", __func__, value);
5490 ret = -1;
5491 }
5492
5493 if (ret != 0) {
5494 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
5495 __func__, out->pm_qos_mixer_path, ret);
5496 }
5497
5498 pthread_mutex_unlock(&out->lock);
5499 }
5500 }
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005501
Alexy Joseph98988832017-01-13 14:56:59 -08005502 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005503 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305504error:
Eric Laurent994a6932013-07-17 11:51:42 -07005505 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005506 return ret;
5507}
5508
Paul McLeana50b7332018-12-17 08:24:21 -07005509static int in_set_microphone_direction(const struct audio_stream_in *stream,
5510 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07005511 struct stream_in *in = (struct stream_in *)stream;
5512
5513 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
5514
5515 in->direction = dir;
5516
5517 if (in->standby)
5518 return 0;
5519
5520 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07005521}
5522
5523static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07005524 struct stream_in *in = (struct stream_in *)stream;
5525
5526 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
5527
5528 if (zoom > 1.0 || zoom < -1.0)
5529 return -EINVAL;
5530
5531 in->zoom = zoom;
5532
5533 if (in->standby)
5534 return 0;
5535
5536 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07005537}
5538
5539
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005540static bool stream_get_parameter_channels(struct str_parms *query,
5541 struct str_parms *reply,
5542 audio_channel_mask_t *supported_channel_masks) {
5543 int ret = -1;
5544 char value[512];
5545 bool first = true;
5546 size_t i, j;
5547
5548 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
5549 ret = 0;
5550 value[0] = '\0';
5551 i = 0;
5552 while (supported_channel_masks[i] != 0) {
5553 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5554 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
5555 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305556 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005557
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305558 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005559 first = false;
5560 break;
5561 }
5562 }
5563 i++;
5564 }
5565 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5566 }
5567 return ret == 0;
5568}
5569
5570static bool stream_get_parameter_formats(struct str_parms *query,
5571 struct str_parms *reply,
5572 audio_format_t *supported_formats) {
5573 int ret = -1;
5574 char value[256];
5575 size_t i, j;
5576 bool first = true;
5577
5578 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
5579 ret = 0;
5580 value[0] = '\0';
5581 i = 0;
5582 while (supported_formats[i] != 0) {
5583 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5584 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
5585 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305586 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005587 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305588 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005589 first = false;
5590 break;
5591 }
5592 }
5593 i++;
5594 }
5595 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
5596 }
5597 return ret == 0;
5598}
5599
5600static bool stream_get_parameter_rates(struct str_parms *query,
5601 struct str_parms *reply,
5602 uint32_t *supported_sample_rates) {
5603
5604 int i;
5605 char value[256];
5606 int ret = -1;
5607 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
5608 ret = 0;
5609 value[0] = '\0';
5610 i=0;
5611 int cursor = 0;
5612 while (supported_sample_rates[i]) {
5613 int avail = sizeof(value) - cursor;
5614 ret = snprintf(value + cursor, avail, "%s%d",
5615 cursor > 0 ? "|" : "",
5616 supported_sample_rates[i]);
5617 if (ret < 0 || ret >= avail) {
5618 // if cursor is at the last element of the array
5619 // overwrite with \0 is duplicate work as
5620 // snprintf already put a \0 in place.
5621 // else
5622 // we had space to write the '|' at value[cursor]
5623 // (which will be overwritten) or no space to fill
5624 // the first element (=> cursor == 0)
5625 value[cursor] = '\0';
5626 break;
5627 }
5628 cursor += ret;
5629 ++i;
5630 }
5631 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
5632 value);
5633 }
5634 return ret >= 0;
5635}
5636
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005637static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
5638{
5639 struct stream_out *out = (struct stream_out *)stream;
5640 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005641 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005642 char value[256];
5643 struct str_parms *reply = str_parms_create();
5644 size_t i, j;
5645 int ret;
5646 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005647
5648 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005649 if (reply) {
5650 str_parms_destroy(reply);
5651 }
5652 if (query) {
5653 str_parms_destroy(query);
5654 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005655 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
5656 return NULL;
5657 }
5658
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005659 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005660 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
5661 if (ret >= 0) {
5662 value[0] = '\0';
5663 i = 0;
5664 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005665 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5666 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005667 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005668 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005669 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005670 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005671 first = false;
5672 break;
5673 }
5674 }
5675 i++;
5676 }
5677 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5678 str = str_parms_to_str(reply);
5679 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005680 voice_extn_out_get_parameters(out, query, reply);
5681 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005682 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005683
Alexy Joseph62142aa2015-11-16 15:10:34 -08005684
5685 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
5686 if (ret >= 0) {
5687 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05305688 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
5689 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08005690 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305691 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005692 } else {
5693 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05305694 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005695 }
5696 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005697 if (str)
5698 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08005699 str = str_parms_to_str(reply);
5700 }
5701
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005702 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
5703 if (ret >= 0) {
5704 value[0] = '\0';
5705 i = 0;
5706 first = true;
5707 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005708 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5709 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005710 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005711 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005712 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005713 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005714 first = false;
5715 break;
5716 }
5717 }
5718 i++;
5719 }
5720 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005721 if (str)
5722 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005723 str = str_parms_to_str(reply);
5724 }
Mingming Yin3a941d42016-02-17 18:08:05 -08005725
5726 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
5727 if (ret >= 0) {
5728 value[0] = '\0';
5729 i = 0;
5730 first = true;
5731 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005732 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
5733 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005734 if (!first) {
5735 strlcat(value, "|", sizeof(value));
5736 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005737 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08005738 first = false;
5739 break;
5740 }
5741 }
5742 i++;
5743 }
5744 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
5745 if (str)
5746 free(str);
5747 str = str_parms_to_str(reply);
5748 }
5749
Alexy Joseph98988832017-01-13 14:56:59 -08005750 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
5751 //only low latency track supports suspend_resume
5752 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005753 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08005754 if (str)
5755 free(str);
5756 str = str_parms_to_str(reply);
5757 }
5758
5759
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005760 str_parms_destroy(query);
5761 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07005762 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005763 return str;
5764}
5765
5766static uint32_t out_get_latency(const struct audio_stream_out *stream)
5767{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005768 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005769 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08005770 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005771
Alexy Josephaa54c872014-12-03 02:46:47 -08005772 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05305773 lock_output_stream(out);
5774 latency = audio_extn_utils_compress_get_dsp_latency(out);
5775 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005776 } else if ((out->realtime) ||
5777 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005778 // since the buffer won't be filled up faster than realtime,
5779 // return a smaller number
5780 if (out->config.rate)
5781 period_ms = (out->af_period_multiplier * out->config.period_size *
5782 1000) / (out->config.rate);
5783 else
5784 period_ms = 0;
George Gao9ba8a142020-07-23 14:30:03 -07005785 latency = period_ms + platform_render_latency(out) / 1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005786 } else {
5787 latency = (out->config.period_count * out->config.period_size * 1000) /
Mingshu Pangf69a88d2021-04-30 16:14:39 +08005788 (out->config.rate);
pavanisra2d95d82022-02-09 18:55:58 +05305789 if (out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5790 out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY)
Mingshu Pangf69a88d2021-04-30 16:14:39 +08005791 latency += platform_render_latency(out)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005792 }
5793
Zhou Songd2537a02020-06-11 22:04:46 +08005794 if (!out->standby && is_a2dp_out_device_type(&out->device_list))
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08005795 latency += audio_extn_a2dp_get_encoder_latency();
5796
Anish Kumar50ebcbf2014-12-09 04:01:39 +05305797 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08005798 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005799}
5800
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305801static float AmpToDb(float amplification)
5802{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305803 float db = DSD_VOLUME_MIN_DB;
5804 if (amplification > 0) {
5805 db = 20 * log10(amplification);
5806 if(db < DSD_VOLUME_MIN_DB)
5807 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305808 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305809 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305810}
5811
Krishna Kishor Jha10ad39f2022-02-21 17:02:47 +05305812#ifdef SOFT_VOLUME
5813static int out_set_soft_volume_params(struct audio_stream_out *stream)
5814{
5815 struct stream_out *out = (struct stream_out *)stream;
5816 int ret = 0;
5817 char mixer_ctl_name[128];
5818 struct audio_device *adev = out->dev;
5819 struct mixer_ctl *ctl = NULL;
5820 struct soft_step_volume_params *volume_params = NULL;
5821
5822 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5823 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Soft Vol Params", pcm_device_id);
5824 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5825 if (!ctl) {
5826 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5827 return -EINVAL;
5828 }
5829
5830 volume_params =(struct soft_step_volume_params * ) malloc(sizeof(struct soft_step_volume_params));
5831 if (volume_params == NULL){
5832 ALOGE("%s : malloc is failed for volume params", __func__);
5833 return -EINVAL;
5834 } else {
5835 ret = platform_get_soft_step_volume_params(volume_params,out->usecase);
5836 if (ret < 0) {
5837 ALOGE("%s : platform_get_soft_step_volume_params is fialed", __func__);
Karan Naidu28b335a2022-05-18 23:00:08 +05305838 ret = -EINVAL;
5839 goto ERR_EXIT;
Krishna Kishor Jha10ad39f2022-02-21 17:02:47 +05305840 }
5841
5842 }
5843 ret = mixer_ctl_set_array(ctl, volume_params, sizeof(struct soft_step_volume_params)/sizeof(int));
5844 if (ret < 0) {
5845 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
Karan Naidu28b335a2022-05-18 23:00:08 +05305846 ret = -EINVAL;
5847 goto ERR_EXIT;
5848 }
5849
5850 if (volume_params) {
5851 free(volume_params);
Krishna Kishor Jha10ad39f2022-02-21 17:02:47 +05305852 }
5853 return 0;
Karan Naidu28b335a2022-05-18 23:00:08 +05305854
5855ERR_EXIT:
5856 if (volume_params) {
5857 free(volume_params);
5858 }
5859 return ret;
Krishna Kishor Jha10ad39f2022-02-21 17:02:47 +05305860}
5861#endif
5862
Arun Mirpuri5d170872019-03-26 13:21:31 -07005863static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
5864 float right)
5865{
5866 struct stream_out *out = (struct stream_out *)stream;
5867 long volume = 0;
5868 char mixer_ctl_name[128] = "";
5869 struct audio_device *adev = out->dev;
5870 struct mixer_ctl *ctl = NULL;
5871 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5872 PCM_PLAYBACK);
5873
5874 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5875 "Playback %d Volume", pcm_device_id);
5876 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5877 if (!ctl) {
5878 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5879 __func__, mixer_ctl_name);
5880 return -EINVAL;
5881 }
5882 if (left != right)
5883 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
5884 __func__, left, right);
5885 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
5886 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
5887 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
5888 __func__, mixer_ctl_name, volume);
5889 return -EINVAL;
5890 }
5891 return 0;
5892}
5893
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305894static int out_set_compr_volume(struct audio_stream_out *stream, float left,
5895 float right)
5896{
5897 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305898 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305899 char mixer_ctl_name[128];
5900 struct audio_device *adev = out->dev;
5901 struct mixer_ctl *ctl;
5902 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5903 PCM_PLAYBACK);
5904
5905 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5906 "Compress Playback %d Volume", 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",
5910 __func__, mixer_ctl_name);
5911 return -EINVAL;
5912 }
5913 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
5914 __func__, mixer_ctl_name, left, right);
5915 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
5916 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
5917 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5918
5919 return 0;
5920}
5921
Zhou Song2b8f28f2017-09-11 10:51:38 +08005922static int out_set_voip_volume(struct audio_stream_out *stream, float left,
5923 float right)
5924{
5925 struct stream_out *out = (struct stream_out *)stream;
5926 char mixer_ctl_name[] = "App Type Gain";
5927 struct audio_device *adev = out->dev;
5928 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305929 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08005930
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07005931 if (!is_valid_volume(left, right)) {
5932 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
5933 __func__, left, right);
5934 return -EINVAL;
5935 }
5936
Zhou Song2b8f28f2017-09-11 10:51:38 +08005937 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5938 if (!ctl) {
5939 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5940 __func__, mixer_ctl_name);
5941 return -EINVAL;
5942 }
5943
5944 set_values[0] = 0; //0: Rx Session 1:Tx Session
5945 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305946 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
5947 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005948
5949 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
5950 return 0;
5951}
5952
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305953static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
5954 float right)
5955{
5956 struct stream_out *out = (struct stream_out *)stream;
5957 /* Volume control for pcm playback */
5958 if (left != right) {
5959 return -EINVAL;
5960 } else {
5961 char mixer_ctl_name[128];
5962 struct audio_device *adev = out->dev;
5963 struct mixer_ctl *ctl;
5964 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5965 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
5966 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5967 if (!ctl) {
5968 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5969 return -EINVAL;
5970 }
5971
5972 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
5973 int ret = mixer_ctl_set_value(ctl, 0, volume);
5974 if (ret < 0) {
5975 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
5976 return -EINVAL;
5977 }
5978
5979 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
5980
5981 return 0;
5982 }
5983}
5984
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005985static int out_set_volume(struct audio_stream_out *stream, float left,
5986 float right)
5987{
Eric Laurenta9024de2013-04-04 09:19:12 -07005988 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005989 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305990 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005991
Arun Mirpuri5d170872019-03-26 13:21:31 -07005992 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07005993 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
5994 /* only take left channel into account: the API is for stereo anyway */
5995 out->muted = (left == 0.0f);
5996 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005997 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305998 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005999 /*
6000 * Set mute or umute on HDMI passthrough stream.
6001 * Only take left channel into account.
6002 * Mute is 0 and unmute 1
6003 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306004 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306005 } else if (out->format == AUDIO_FORMAT_DSD){
6006 char mixer_ctl_name[128] = "DSD Volume";
6007 struct audio_device *adev = out->dev;
6008 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
6009
6010 if (!ctl) {
6011 ALOGE("%s: Could not get ctl for mixer cmd - %s",
6012 __func__, mixer_ctl_name);
6013 return -EINVAL;
6014 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05306015 volume[0] = (long)(AmpToDb(left));
6016 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306017 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
6018 return 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006019 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS) &&
Derek Chendf05eea2019-08-01 13:57:49 -07006020 (out->car_audio_stream == CAR_AUDIO_STREAM_MEDIA)) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07006021 ALOGD("%s: Overriding offload set volume for media bus stream", __func__);
6022 struct listnode *node = NULL;
6023 list_for_each(node, &adev->active_outputs_list) {
6024 streams_output_ctxt_t *out_ctxt = node_to_item(node,
6025 streams_output_ctxt_t,
6026 list);
6027 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
6028 out->volume_l = out_ctxt->output->volume_l;
6029 out->volume_r = out_ctxt->output->volume_r;
6030 }
6031 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08006032 pthread_mutex_lock(&out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +08006033 if (!out->a2dp_muted) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07006034 ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
6035 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08006036 pthread_mutex_unlock(&out->latch_lock);
Philippe Gravel1c9ac352019-05-28 16:08:37 -07006037 return ret;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006038 } else {
Weiyin Jiang280ea742020-09-08 20:28:22 +08006039 pthread_mutex_lock(&out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +08006040 ALOGV("%s: compress mute %d", __func__, out->a2dp_muted);
6041 if (!out->a2dp_muted)
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306042 ret = out_set_compr_volume(stream, left, right);
6043 out->volume_l = left;
6044 out->volume_r = right;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006045 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306046 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006047 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07006048 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08006049 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
6050 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Songbaddf9f2020-11-20 13:57:39 +08006051 pthread_mutex_lock(&out->latch_lock);
Aalique Grahame22e49102018-12-18 14:23:57 -08006052 if (!out->standby) {
6053 audio_extn_utils_send_app_type_gain(out->dev,
6054 out->app_type_cfg.app_type,
6055 &out->app_type_cfg.gain[0]);
Zhou Songbaddf9f2020-11-20 13:57:39 +08006056 if (!out->a2dp_muted)
6057 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08006058 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08006059 out->volume_l = left;
6060 out->volume_r = right;
Zhou Songbaddf9f2020-11-20 13:57:39 +08006061 pthread_mutex_unlock(&out->latch_lock);
Zhou Song2b8f28f2017-09-11 10:51:38 +08006062 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006063 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
6064 ALOGV("%s: MMAP set volume called", __func__);
6065 if (!out->standby)
6066 ret = out_set_mmap_volume(stream, left, right);
6067 out->volume_l = left;
6068 out->volume_r = right;
6069 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05306070 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05306071 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
6072 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Zhou Songbaddf9f2020-11-20 13:57:39 +08006073 pthread_mutex_lock(&out->latch_lock);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05306074 /* Volume control for pcm playback */
Zhou Songbaddf9f2020-11-20 13:57:39 +08006075 if (!out->standby && !out->a2dp_muted)
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05306076 ret = out_set_pcm_volume(stream, left, right);
6077 else
6078 out->apply_volume = true;
6079
6080 out->volume_l = left;
6081 out->volume_r = right;
Zhou Songbaddf9f2020-11-20 13:57:39 +08006082 pthread_mutex_unlock(&out->latch_lock);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05306083 return ret;
Derek Chenf13dd492018-11-13 14:53:51 -08006084 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
6085 ALOGV("%s: bus device set volume called", __func__);
Zhou Songbaddf9f2020-11-20 13:57:39 +08006086 pthread_mutex_lock(&out->latch_lock);
6087 if (!out->standby && !out->a2dp_muted)
Derek Chenf13dd492018-11-13 14:53:51 -08006088 ret = out_set_pcm_volume(stream, left, right);
6089 out->volume_l = left;
6090 out->volume_r = right;
Zhou Songbaddf9f2020-11-20 13:57:39 +08006091 pthread_mutex_unlock(&out->latch_lock);
Derek Chenf13dd492018-11-13 14:53:51 -08006092 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07006093 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006094
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006095 return -ENOSYS;
6096}
6097
Zhou Songc9672822017-08-16 16:01:39 +08006098static void update_frames_written(struct stream_out *out, size_t bytes)
6099{
6100 size_t bpf = 0;
6101
6102 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
6103 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
6104 bpf = 1;
6105 else if (!is_offload_usecase(out->usecase))
6106 bpf = audio_bytes_per_sample(out->format) *
6107 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08006108
6109 pthread_mutex_lock(&out->position_query_lock);
6110 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08006111 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08006112 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
6113 }
6114 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08006115}
6116
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006117int split_and_write_audio_haptic_data(struct stream_out *out,
6118 const void *buffer, size_t bytes_to_write)
6119{
6120 struct audio_device *adev = out->dev;
6121
6122 int ret = 0;
6123 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
6124 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
6125 size_t frame_size = channel_count * bytes_per_sample;
6126 size_t frame_count = bytes_to_write / frame_size;
6127
6128 bool force_haptic_path =
6129 property_get_bool("vendor.audio.test_haptic", false);
6130
6131 // extract Haptics data from Audio buffer
6132 bool alloc_haptic_buffer = false;
6133 int haptic_channel_count = adev->haptics_config.channels;
6134 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
6135 size_t audio_frame_size = frame_size - haptic_frame_size;
6136 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
6137
6138 if (adev->haptic_buffer == NULL) {
6139 alloc_haptic_buffer = true;
6140 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
6141 free(adev->haptic_buffer);
6142 adev->haptic_buffer_size = 0;
6143 alloc_haptic_buffer = true;
6144 }
6145
6146 if (alloc_haptic_buffer) {
6147 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08006148 if(adev->haptic_buffer == NULL) {
6149 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
6150 return -ENOMEM;
6151 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006152 adev->haptic_buffer_size = total_haptic_buffer_size;
6153 }
6154
6155 size_t src_index = 0, aud_index = 0, hap_index = 0;
6156 uint8_t *audio_buffer = (uint8_t *)buffer;
6157 uint8_t *haptic_buffer = adev->haptic_buffer;
6158
6159 // This is required for testing only. This works for stereo data only.
6160 // One channel is fed to audio stream and other to haptic stream for testing.
6161 if (force_haptic_path)
6162 audio_frame_size = haptic_frame_size = bytes_per_sample;
6163
6164 for (size_t i = 0; i < frame_count; i++) {
6165 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
6166 audio_frame_size);
6167 aud_index += audio_frame_size;
6168 src_index += audio_frame_size;
6169
6170 if (adev->haptic_pcm)
6171 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
6172 haptic_frame_size);
6173 hap_index += haptic_frame_size;
6174 src_index += haptic_frame_size;
6175
6176 // This is required for testing only.
6177 // Discard haptic channel data.
6178 if (force_haptic_path)
6179 src_index += haptic_frame_size;
6180 }
6181
6182 // write to audio pipeline
6183 ret = pcm_write(out->pcm, (void *)audio_buffer,
6184 frame_count * audio_frame_size);
6185
6186 // write to haptics pipeline
6187 if (adev->haptic_pcm)
6188 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
6189 frame_count * haptic_frame_size);
6190
6191 return ret;
6192}
6193
Aalique Grahame22e49102018-12-18 14:23:57 -08006194#ifdef NO_AUDIO_OUT
6195static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
6196 const void *buffer __unused, size_t bytes)
6197{
6198 struct stream_out *out = (struct stream_out *)stream;
6199
6200 /* No Output device supported other than BT for playback.
6201 * Sleep for the amount of buffer duration
6202 */
6203 lock_output_stream(out);
6204 usleep(bytes * 1000000 / audio_stream_out_frame_size(
6205 (const struct audio_stream_out *)&out->stream) /
6206 out_get_sample_rate(&out->stream.common));
6207 pthread_mutex_unlock(&out->lock);
6208 return bytes;
6209}
6210#endif
6211
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006212static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
6213 size_t bytes)
6214{
6215 struct stream_out *out = (struct stream_out *)stream;
6216 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07006217 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05306218 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006219 const size_t frame_size = audio_stream_out_frame_size(stream);
6220 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05306221 struct audio_usecase *usecase = NULL;
Meng Wang4c32fb42020-01-16 17:57:11 +08006222 uint32_t compr_passthr = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006223
Haynes Mathew George380745d2017-10-04 15:27:45 -07006224 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006225 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306226
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05006227 if (CARD_STATUS_OFFLINE == out->card_status ||
6228 POWER_POLICY_STATUS_OFFLINE == adev->out_power_policy) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08006229
Dhananjay Kumarac341582017-02-23 23:42:25 +05306230 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306231 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05306232 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
6233 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006234 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05306235 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05306236 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05306237 ALOGD(" %s: sound card is not active/SSR state", __func__);
6238 ret= -EIO;
6239 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306240 }
6241 }
6242
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306243 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05306244 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05306245 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306246 goto exit;
6247 }
6248
Haynes Mathew George16081042017-05-31 17:16:49 -07006249 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
6250 ret = -EINVAL;
6251 goto exit;
6252 }
6253
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006254 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306255 !out->is_iec61937_info_available) {
6256
6257 if (!audio_extn_passthru_is_passthrough_stream(out)) {
6258 out->is_iec61937_info_available = true;
6259 } else if (audio_extn_passthru_is_enabled()) {
6260 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05306261 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05306262
6263 if((out->format == AUDIO_FORMAT_DTS) ||
6264 (out->format == AUDIO_FORMAT_DTS_HD)) {
6265 ret = audio_extn_passthru_update_dts_stream_configuration(out,
6266 buffer, bytes);
6267 if (ret) {
6268 if (ret != -ENOSYS) {
6269 out->is_iec61937_info_available = false;
6270 ALOGD("iec61937 transmission info not yet updated retry");
6271 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306272 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05306273 /* if stream has started and after that there is
6274 * stream config change (iec transmission config)
6275 * then trigger select_device to update backend configuration.
6276 */
6277 out->stream_config_changed = true;
6278 pthread_mutex_lock(&adev->lock);
6279 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306280 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08006281 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306282 ret = -EINVAL;
6283 goto exit;
6284 }
Manish Dewangan671a4202017-08-18 17:30:46 +05306285 pthread_mutex_unlock(&adev->lock);
6286 out->stream_config_changed = false;
6287 out->is_iec61937_info_available = true;
6288 }
6289 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05306290
Meng Wang4c32fb42020-01-16 17:57:11 +08006291#ifdef AUDIO_GKI_ENABLED
6292 /* out->compr_config.codec->reserved[0] is for compr_passthr */
6293 compr_passthr = out->compr_config.codec->reserved[0];
6294#else
6295 compr_passthr = out->compr_config.codec->compr_passthr;
6296#endif
6297
Garmond Leung317cbf12017-09-13 16:20:50 -07006298 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Meng Wang4c32fb42020-01-16 17:57:11 +08006299 (compr_passthr == PASSTHROUGH) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05306300 (out->is_iec61937_info_available == true)) {
6301 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
6302 ret = -EINVAL;
6303 goto exit;
6304 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05306305 }
6306 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306307
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006308 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02006309 (audio_extn_a2dp_source_is_suspended())) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006310 if (!(compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER) ||
6311 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Zhou Songd01e7a22020-09-23 22:49:01 +08006312 if (!is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306313 ret = -EIO;
6314 goto exit;
6315 }
6316 }
6317 }
6318
Weiyin Jiangabedea32020-12-09 12:49:19 +08006319 if (is_usb_out_device_type(&out->device_list) &&
6320 !audio_extn_usb_connected(NULL)) {
6321 ret = -EIO;
6322 goto exit;
6323 }
6324
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006325 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07006326 out->standby = false;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006327 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
6328
Eric Laurent150dbfe2013-02-27 14:31:02 -08006329 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006330 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
6331 ret = voice_extn_compress_voip_start_output_stream(out);
6332 else
6333 ret = start_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006334 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006335 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07006336 out->standby = true;
Weiyin Jiangac2bae82020-07-29 17:23:53 +08006337 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006338 goto exit;
6339 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306340 out->started = 1;
Andy Hunga1f48fa2019-07-01 18:14:53 -07006341 out->last_fifo_valid = false; // we're coming out of standby, last_fifo isn't valid.
Weiyin Jiangac2bae82020-07-29 17:23:53 +08006342
6343 if ((last_known_cal_step != -1) && (adev->platform != NULL)) {
vivek mehtab72d08d2016-04-29 03:16:47 -07006344 ALOGD("%s: retry previous failed cal level set", __func__);
Weiyin Jiangac2bae82020-07-29 17:23:53 +08006345 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05306346 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07006347 }
Weiyin Jiangac2bae82020-07-29 17:23:53 +08006348 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306349
6350 if ((out->is_iec61937_info_available == true) &&
6351 (audio_extn_passthru_is_passthrough_stream(out))&&
6352 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
6353 ret = -EINVAL;
6354 goto exit;
6355 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05306356 if (out->set_dual_mono)
6357 audio_extn_send_dual_mono_mixing_coefficients(out);
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006358
Dechen Chai22768452021-07-30 09:29:16 +05306359#ifndef LINUX_ENABLED
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006360 // log startup time in ms.
6361 simple_stats_log(
6362 &out->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Dechen Chai22768452021-07-30 09:29:16 +05306363#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006364 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006365
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006366 if (adev->is_channel_status_set == false &&
6367 compare_device_type(&out->device_list,
6368 AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Alexy Josephb1379942016-01-29 15:49:38 -08006369 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05306370 adev->is_channel_status_set = true;
6371 }
6372
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05306373 if ((adev->use_old_pspd_mix_ctrl == true) &&
6374 (out->pspd_coeff_sent == false)) {
6375 /*
6376 * Need to resend pspd coefficients after stream started for
6377 * older kernel version as it does not save the coefficients
6378 * and also stream has to be started for coeff to apply.
6379 */
6380 usecase = get_usecase_from_list(adev, out->usecase);
6381 if (usecase != NULL) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05306382 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05306383 out->pspd_coeff_sent = true;
6384 }
6385 }
6386
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006387 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08006388 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006389 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006390 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006391 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
6392 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05306393 if (out->send_next_track_params && out->is_compr_metadata_avail) {
6394 ALOGD("copl(%p):send next track params in gapless", out);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08006395 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05306396 out->send_next_track_params = false;
6397 out->is_compr_metadata_avail = false;
6398 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006399 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05306400 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306401 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006402
Ashish Jain83a6cc22016-06-28 14:34:17 +05306403 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05306404 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05306405 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05306406 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006407 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05306408 return -EINVAL;
6409 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05306410 audio_format_t dst_format = out->hal_op_format;
6411 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306412
Dieter Luecking5d57def2018-09-07 14:23:37 +02006413 /* prevent division-by-zero */
6414 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
6415 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
6416 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
6417 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05306418 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006419 ATRACE_END();
6420 return -EINVAL;
6421 }
6422
Ashish Jainf1eaa582016-05-23 20:54:24 +05306423 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
6424 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
6425
Ashish Jain83a6cc22016-06-28 14:34:17 +05306426 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05306427 dst_format,
6428 buffer,
6429 src_format,
6430 frames);
6431
Ashish Jain83a6cc22016-06-28 14:34:17 +05306432 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05306433 bytes_to_write);
6434
6435 /*Convert written bytes in audio flinger format*/
6436 if (ret > 0)
6437 ret = ((ret * format_to_bitwidth_table[out->format]) /
6438 format_to_bitwidth_table[dst_format]);
6439 }
6440 } else
6441 ret = compress_write(out->compr, buffer, bytes);
6442
Zhou Songc9672822017-08-16 16:01:39 +08006443 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
6444 update_frames_written(out, bytes);
6445
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306446 if (ret < 0)
6447 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08006448 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05306449 /*msg to cb thread only if non blocking write is enabled*/
6450 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05306451 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006452 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05306453 } else if (-ENETRESET == ret) {
6454 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306455 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05306456 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05306457 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006458 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05306459 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006460 }
Ashish Jain5106d362016-05-11 19:23:33 +05306461
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05306462 /* Call compr start only when non-zero bytes of data is there to be rendered */
6463 if (!out->playback_started && ret > 0) {
6464 int status = compress_start(out->compr);
6465 if (status < 0) {
6466 ret = status;
6467 ALOGE("%s: compr start failed with err %d", __func__, errno);
6468 goto exit;
6469 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07006470 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006471 out->playback_started = 1;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006472 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006473 out->offload_state = OFFLOAD_STATE_PLAYING;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006474 pthread_mutex_unlock(&out->latch_lock);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006475
6476 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6477 popcount(out->channel_mask),
6478 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006479 }
6480 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006481 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006482 return ret;
6483 } else {
6484 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006485 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006486 if (out->muted)
6487 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006488 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
6489 __func__, frames, frame_size, bytes_to_write);
6490
Aalique Grahame22e49102018-12-18 14:23:57 -08006491 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07006492 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
6493 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
6494 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006495 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
6496 int16_t *src = (int16_t *)buffer;
6497 int16_t *dst = (int16_t *)buffer;
6498
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006499 LOG_ALWAYS_FATAL_IF(channel_count > 2 ||
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006500 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08006501 "out_write called for %s use case with wrong properties",
6502 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006503
6504 /*
6505 * FIXME: this can be removed once audio flinger mixer supports
6506 * mono output
6507 */
6508
6509 /*
6510 * Code below goes over each frame in the buffer and adds both
6511 * L and R samples and then divides by 2 to convert to mono
6512 */
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006513 if (channel_count == 2) {
6514 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
6515 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
6516 }
6517 bytes_to_write /= 2;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006518 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006519 }
Andy Hunga1f48fa2019-07-01 18:14:53 -07006520
6521 // Note: since out_get_presentation_position() is called alternating with out_write()
6522 // by AudioFlinger, we can check underruns using the prior timestamp read.
6523 // (Alternately we could check if the buffer is empty using pcm_get_htimestamp().
6524 if (out->last_fifo_valid) {
6525 // compute drain to see if there is an underrun.
6526 const int64_t current_ns = systemTime(SYSTEM_TIME_MONOTONIC); // sys call
Dhananjay Kumara4429632020-07-11 02:53:37 +05306527 int64_t time_diff_ns = current_ns - out->last_fifo_time_ns;
6528 int64_t frames_by_time =
6529 ((time_diff_ns > 0) && (time_diff_ns < (INT64_MAX / out->config.rate))) ?
6530 (time_diff_ns * out->config.rate / NANOS_PER_SECOND) : 0;
Andy Hunga1f48fa2019-07-01 18:14:53 -07006531 const int64_t underrun = frames_by_time - out->last_fifo_frames_remaining;
6532
6533 if (underrun > 0) {
Dechen Chai22768452021-07-30 09:29:16 +05306534#ifndef LINUX_ENABLED
Andy Hunga1f48fa2019-07-01 18:14:53 -07006535 simple_stats_log(&out->fifo_underruns, underrun);
Dechen Chai22768452021-07-30 09:29:16 +05306536#endif
Andy Hunga1f48fa2019-07-01 18:14:53 -07006537
6538 ALOGW("%s: underrun(%lld) "
6539 "frames_by_time(%lld) > out->last_fifo_frames_remaining(%lld)",
6540 __func__,
6541 (long long)out->fifo_underruns.n,
6542 (long long)frames_by_time,
6543 (long long)out->last_fifo_frames_remaining);
6544 }
6545 out->last_fifo_valid = false; // we're writing below, mark fifo info as stale.
6546 }
6547
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306548 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006549
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006550 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006551
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006552 if (out->config.rate)
6553 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
6554 out->config.rate;
6555
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006556 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006557 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
6558
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006559 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006560 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006561 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306562 out->convert_buffer != NULL) {
6563
6564 memcpy_by_audio_format(out->convert_buffer,
6565 out->hal_op_format,
6566 buffer,
6567 out->hal_ip_format,
6568 out->config.period_size * out->config.channels);
6569
6570 ret = pcm_write(out->pcm, out->convert_buffer,
6571 (out->config.period_size *
6572 out->config.channels *
6573 format_to_bitwidth_table[out->hal_op_format]));
6574 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05306575 /*
6576 * To avoid underrun in DSP when the application is not pumping
6577 * data at required rate, check for the no. of bytes and ignore
6578 * pcm_write if it is less than actual buffer size.
6579 * It is a work around to a change in compress VOIP driver.
6580 */
6581 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
6582 bytes < (out->config.period_size * out->config.channels *
6583 audio_bytes_per_sample(out->format))) {
6584 size_t voip_buf_size =
6585 out->config.period_size * out->config.channels *
6586 audio_bytes_per_sample(out->format);
6587 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
6588 __func__, bytes, voip_buf_size);
6589 usleep(((uint64_t)voip_buf_size - bytes) *
6590 1000000 / audio_stream_out_frame_size(stream) /
6591 out_get_sample_rate(&out->stream.common));
6592 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006593 } else {
6594 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
6595 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
6596 else
6597 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
6598 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306599 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006600
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006601 release_out_focus(out);
6602
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306603 if (ret < 0)
6604 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08006605 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05306606 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006607 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006608 }
6609
6610exit:
Zhou Songc9672822017-08-16 16:01:39 +08006611 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306612 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306613 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306614 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006615 pthread_mutex_unlock(&out->lock);
6616
6617 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006618 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08006619 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306620 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306621 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306622 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306623 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306624 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306625 out->standby = true;
6626 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306627 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006628 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
6629 /* prevent division-by-zero */
6630 uint32_t stream_size = audio_stream_out_frame_size(stream);
6631 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006632
Dieter Luecking5d57def2018-09-07 14:23:37 +02006633 if ((stream_size == 0) || (srate == 0)) {
6634 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
6635 ATRACE_END();
6636 return -EINVAL;
6637 }
6638 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
6639 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006640 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05306641 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006642 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006643 return ret;
6644 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006645 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07006646 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006647 return bytes;
6648}
6649
6650static int out_get_render_position(const struct audio_stream_out *stream,
6651 uint32_t *dsp_frames)
6652{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006653 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08006654
6655 if (dsp_frames == NULL)
6656 return -EINVAL;
6657
6658 *dsp_frames = 0;
6659 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08006660 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05306661
6662 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
6663 * this operation and adev_close_output_stream(where out gets reset).
6664 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05306665 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006666 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05306667 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006668 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05306669 return 0;
6670 }
6671
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006672 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05306673 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306674 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006675 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306676 if (ret < 0)
6677 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006678 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05306679 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006680 }
Naresh Tanniru80659832014-06-04 18:17:56 +05306681 if (-ENETRESET == ret) {
6682 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306683 out->card_status = CARD_STATUS_OFFLINE;
6684 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306685 } else if(ret < 0) {
6686 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306687 ret = -EINVAL;
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05006688 } else if (out->card_status == CARD_STATUS_OFFLINE ||
6689 adev->out_power_policy == POWER_POLICY_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05306690 /*
6691 * Handle corner case where compress session is closed during SSR
6692 * and timestamp is queried
6693 */
6694 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306695 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306696 } else if (out->prev_card_status_offline) {
6697 ALOGE("ERROR: previously sound card was offline,return error");
6698 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306699 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306700 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006701 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05306702 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306703 pthread_mutex_unlock(&out->lock);
6704 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08006705 } else if (audio_is_linear_pcm(out->format)) {
6706 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006707 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08006708 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006709 } else
6710 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006711}
6712
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006713static int out_add_audio_effect(const struct audio_stream *stream __unused,
6714 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006715{
6716 return 0;
6717}
6718
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006719static int out_remove_audio_effect(const struct audio_stream *stream __unused,
6720 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006721{
6722 return 0;
6723}
6724
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006725static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
6726 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006727{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05306728 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006729}
6730
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006731static int out_get_presentation_position(const struct audio_stream_out *stream,
6732 uint64_t *frames, struct timespec *timestamp)
6733{
6734 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05306735 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07006736 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006737
Ashish Jain5106d362016-05-11 19:23:33 +05306738 /* below piece of code is not guarded against any lock because audioFliner serializes
6739 * this operation and adev_close_output_stream( where out gets reset).
6740 */
6741 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05306742 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006743 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05306744 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
6745 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
6746 return 0;
6747 }
6748
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006749 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006750
Ashish Jain5106d362016-05-11 19:23:33 +05306751 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
6752 ret = compress_get_tstamp(out->compr, &dsp_frames,
6753 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08006754 // Adjustment accounts for A2dp encoder latency with offload usecases
6755 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006756 if (is_a2dp_out_device_type(&out->device_list)) {
yidongh0515e042017-07-06 15:00:34 +08006757 unsigned long offset =
6758 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
6759 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
6760 }
Ashish Jain5106d362016-05-11 19:23:33 +05306761 ALOGVV("%s rendered frames %ld sample_rate %d",
6762 __func__, dsp_frames, out->sample_rate);
6763 *frames = dsp_frames;
6764 if (ret < 0)
6765 ret = -errno;
6766 if (-ENETRESET == ret) {
6767 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306768 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05306769 ret = -EINVAL;
6770 } else
6771 ret = 0;
6772 /* this is the best we can do */
6773 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07006774 } else {
6775 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08006776 unsigned int avail;
6777 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
George Gao62ebc722019-07-29 16:29:44 -07006778 uint64_t signed_frames = 0;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006779 uint64_t frames_temp = 0;
George Gao62ebc722019-07-29 16:29:44 -07006780
Andy Hunga1f48fa2019-07-01 18:14:53 -07006781 if (out->kernel_buffer_size > avail) {
6782 frames_temp = out->last_fifo_frames_remaining = out->kernel_buffer_size - avail;
6783 } else {
6784 ALOGW("%s: avail:%u > kernel_buffer_size:%zu clamping!",
6785 __func__, avail, out->kernel_buffer_size);
6786 avail = out->kernel_buffer_size;
6787 frames_temp = out->last_fifo_frames_remaining = 0;
6788 }
6789 out->last_fifo_valid = true;
6790 out->last_fifo_time_ns = audio_utils_ns_from_timespec(timestamp);
6791
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006792 if (out->written >= frames_temp)
6793 signed_frames = out->written - frames_temp;
George Gao62ebc722019-07-29 16:29:44 -07006794
Andy Hunga1f48fa2019-07-01 18:14:53 -07006795 ALOGVV("%s: frames:%lld avail:%u kernel_buffer_size:%zu",
6796 __func__, (long long)signed_frames, avail, out->kernel_buffer_size);
6797
Weiyin Jiangd4633762018-03-16 12:05:03 +08006798 // This adjustment accounts for buffering after app processor.
6799 // It is based on estimated DSP latency per use case, rather than exact.
George Gao9ba8a142020-07-23 14:30:03 -07006800 frames_temp = platform_render_latency(out) *
Robert Lee58215542019-07-15 20:55:12 +08006801 out->sample_rate / 1000000LL;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006802 if (signed_frames >= frames_temp)
6803 signed_frames -= frames_temp;
Aniket Kumar Lataff613152017-07-18 18:19:21 -07006804
Weiyin Jiangd4633762018-03-16 12:05:03 +08006805 // Adjustment accounts for A2dp encoder latency with non offload usecases
6806 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006807 if (is_a2dp_out_device_type(&out->device_list)) {
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006808 frames_temp = audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000;
6809 if (signed_frames >= frames_temp)
6810 signed_frames -= frames_temp;
Weiyin Jiangd4633762018-03-16 12:05:03 +08006811 }
6812
6813 // It would be unusual for this value to be negative, but check just in case ...
George Gao62ebc722019-07-29 16:29:44 -07006814 *frames = signed_frames;
6815 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006816 }
Eric Laurenta7a33042019-07-10 16:20:22 -07006817 } else if (out->card_status == CARD_STATUS_OFFLINE ||
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05006818 adev->out_power_policy == POWER_POLICY_STATUS_OFFLINE ||
Eric Laurenta7a33042019-07-10 16:20:22 -07006819 // audioflinger still needs position updates when A2DP is suspended
Jasmine Cha5c2517f2019-09-09 11:07:28 +08006820 (is_a2dp_out_device_type(&out->device_list) && audio_extn_a2dp_source_is_suspended())) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306821 *frames = out->written;
6822 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306823 if (is_offload_usecase(out->usecase))
6824 ret = -EINVAL;
6825 else
6826 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006827 }
6828 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006829 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006830 return ret;
6831}
6832
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006833static int out_set_callback(struct audio_stream_out *stream,
6834 stream_callback_t callback, void *cookie)
6835{
6836 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006837 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006838
6839 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006840 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006841 out->client_callback = callback;
6842 out->client_cookie = cookie;
6843 if (out->adsp_hdlr_stream_handle) {
6844 ret = audio_extn_adsp_hdlr_stream_set_callback(
6845 out->adsp_hdlr_stream_handle,
6846 callback,
6847 cookie);
6848 if (ret)
6849 ALOGW("%s:adsp hdlr callback registration failed %d",
6850 __func__, ret);
6851 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006852 pthread_mutex_unlock(&out->lock);
6853 return 0;
6854}
6855
6856static int out_pause(struct audio_stream_out* stream)
6857{
6858 struct stream_out *out = (struct stream_out *)stream;
6859 int status = -ENOSYS;
6860 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006861 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006862 ALOGD("copl(%p):pause compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306863 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006864 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006865 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006866 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306867 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05306868 status = compress_pause(out->compr);
6869
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006870 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006871
Mingming Yin21854652016-04-13 11:54:02 -07006872 if (audio_extn_passthru_is_active()) {
6873 ALOGV("offload use case, pause passthru");
6874 audio_extn_passthru_on_pause(out);
6875 }
6876
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306877 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006878 audio_extn_dts_notify_playback_state(out->usecase, 0,
6879 out->sample_rate, popcount(out->channel_mask),
6880 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006881 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08006882 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006883 pthread_mutex_unlock(&out->lock);
6884 }
6885 return status;
6886}
6887
6888static int out_resume(struct audio_stream_out* stream)
6889{
6890 struct stream_out *out = (struct stream_out *)stream;
6891 int status = -ENOSYS;
6892 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006893 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006894 ALOGD("copl(%p):resume compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306895 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006896 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006897 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006898 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306899 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306900 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07006901 }
6902 if (!status) {
6903 out->offload_state = OFFLOAD_STATE_PLAYING;
6904 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306905 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006906 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6907 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006908 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08006909 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006910 pthread_mutex_unlock(&out->lock);
6911 }
6912 return status;
6913}
6914
6915static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
6916{
6917 struct stream_out *out = (struct stream_out *)stream;
6918 int status = -ENOSYS;
6919 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006920 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006921 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006922 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
6923 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
6924 else
6925 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
6926 pthread_mutex_unlock(&out->lock);
6927 }
6928 return status;
6929}
6930
6931static int out_flush(struct audio_stream_out* stream)
6932{
6933 struct stream_out *out = (struct stream_out *)stream;
6934 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006935 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006936 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006937 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006938 pthread_mutex_lock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006939 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
Gautam Manam14c198b2020-12-24 14:08:04 +05306940 pthread_mutex_unlock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006941 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006942 } else {
6943 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
Gautam Manam14c198b2020-12-24 14:08:04 +05306944 pthread_mutex_unlock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006945 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08006946 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006947 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006948 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006949 return 0;
6950 }
6951 return -ENOSYS;
6952}
6953
Haynes Mathew George16081042017-05-31 17:16:49 -07006954static int out_stop(const struct audio_stream_out* stream)
6955{
6956 struct stream_out *out = (struct stream_out *)stream;
6957 struct audio_device *adev = out->dev;
6958 int ret = -ENOSYS;
6959
6960 ALOGV("%s", __func__);
6961 pthread_mutex_lock(&adev->lock);
6962 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6963 out->playback_started && out->pcm != NULL) {
6964 pcm_stop(out->pcm);
6965 ret = stop_output_stream(out);
6966 out->playback_started = false;
6967 }
6968 pthread_mutex_unlock(&adev->lock);
6969 return ret;
6970}
6971
6972static int out_start(const struct audio_stream_out* stream)
6973{
6974 struct stream_out *out = (struct stream_out *)stream;
6975 struct audio_device *adev = out->dev;
6976 int ret = -ENOSYS;
6977
6978 ALOGV("%s", __func__);
6979 pthread_mutex_lock(&adev->lock);
6980 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6981 !out->playback_started && out->pcm != NULL) {
6982 ret = start_output_stream(out);
6983 if (ret == 0) {
6984 out->playback_started = true;
6985 }
6986 }
6987 pthread_mutex_unlock(&adev->lock);
6988 return ret;
6989}
6990
6991/*
6992 * Modify config->period_count based on min_size_frames
6993 */
6994static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
6995{
6996 int periodCountRequested = (min_size_frames + config->period_size - 1)
6997 / config->period_size;
6998 int periodCount = MMAP_PERIOD_COUNT_MIN;
6999
7000 ALOGV("%s original config.period_size = %d config.period_count = %d",
7001 __func__, config->period_size, config->period_count);
7002
7003 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
7004 periodCount *= 2;
7005 }
7006 config->period_count = periodCount;
7007
7008 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
7009}
7010
Phil Burkfe17efd2019-03-25 10:23:35 -07007011// Read offset for the positional timestamp from a persistent vendor property.
7012// This is to workaround apparent inaccuracies in the timing information that
7013// is used by the AAudio timing model. The inaccuracies can cause glitches.
7014static int64_t get_mmap_out_time_offset() {
7015 const int32_t kDefaultOffsetMicros = 0;
7016 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08007017 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07007018 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
7019 return mmap_time_offset_micros * (int64_t)1000;
7020}
7021
Haynes Mathew George16081042017-05-31 17:16:49 -07007022static int out_create_mmap_buffer(const struct audio_stream_out *stream,
7023 int32_t min_size_frames,
7024 struct audio_mmap_buffer_info *info)
7025{
7026 struct stream_out *out = (struct stream_out *)stream;
7027 struct audio_device *adev = out->dev;
7028 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07007029 unsigned int offset1 = 0;
7030 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007031 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07007032 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007033 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07007034
Arun Mirpuri5d170872019-03-26 13:21:31 -07007035 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05307036 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07007037 pthread_mutex_lock(&adev->lock);
7038
Sharad Sanglec6f32552018-05-04 16:15:38 +05307039 if (CARD_STATUS_OFFLINE == out->card_status ||
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05007040 CARD_STATUS_OFFLINE == adev->card_status ||
7041 POWER_POLICY_STATUS_OFFLINE == adev->out_power_policy) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307042 ALOGW("out->card_status or adev->card_status offline, try again");
7043 ret = -EIO;
7044 goto exit;
7045 }
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307046 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07007047 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
7048 ret = -EINVAL;
7049 goto exit;
7050 }
7051 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
7052 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
7053 ret = -ENOSYS;
7054 goto exit;
7055 }
7056 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
7057 if (out->pcm_device_id < 0) {
7058 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
7059 __func__, out->pcm_device_id, out->usecase);
7060 ret = -EINVAL;
7061 goto exit;
7062 }
7063
7064 adjust_mmap_period_count(&out->config, min_size_frames);
7065
Arun Mirpuri5d170872019-03-26 13:21:31 -07007066 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07007067 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
7068 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
7069 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307070 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307071 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7072 out->card_status = CARD_STATUS_OFFLINE;
7073 adev->card_status = CARD_STATUS_OFFLINE;
7074 ret = -EIO;
7075 goto exit;
7076 }
7077
Haynes Mathew George16081042017-05-31 17:16:49 -07007078 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
7079 step = "open";
7080 ret = -ENODEV;
7081 goto exit;
7082 }
7083 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
7084 if (ret < 0) {
7085 step = "begin";
7086 goto exit;
7087 }
juyuchen626833d2019-06-04 16:48:02 +08007088
7089 info->flags = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007090 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07007091 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07007092 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07007093 ret = platform_get_mmap_data_fd(adev->platform,
7094 out->pcm_device_id, 0 /*playback*/,
7095 &info->shared_memory_fd,
7096 &mmap_size);
7097 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07007098 // Fall back to non exclusive mode
7099 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
7100 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07007101 out->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
7102 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, out->mmap_shared_memory_fd);
7103
Arun Mirpuri5d170872019-03-26 13:21:31 -07007104 if (mmap_size < buffer_size) {
7105 step = "mmap";
7106 goto exit;
7107 }
juyuchen626833d2019-06-04 16:48:02 +08007108 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07007109 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007110 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07007111 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07007112
7113 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
7114 if (ret < 0) {
7115 step = "commit";
7116 goto exit;
7117 }
7118
Phil Burkfe17efd2019-03-25 10:23:35 -07007119 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
7120
Haynes Mathew George16081042017-05-31 17:16:49 -07007121 out->standby = false;
7122 ret = 0;
7123
Arun Mirpuri5d170872019-03-26 13:21:31 -07007124 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07007125 __func__, info->shared_memory_address, info->buffer_size_frames);
7126
7127exit:
7128 if (ret != 0) {
7129 if (out->pcm == NULL) {
7130 ALOGE("%s: %s - %d", __func__, step, ret);
7131 } else {
7132 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
7133 pcm_close(out->pcm);
7134 out->pcm = NULL;
7135 }
7136 }
7137 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05307138 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07007139 return ret;
7140}
7141
7142static int out_get_mmap_position(const struct audio_stream_out *stream,
7143 struct audio_mmap_position *position)
7144{
7145 struct stream_out *out = (struct stream_out *)stream;
7146 ALOGVV("%s", __func__);
7147 if (position == NULL) {
7148 return -EINVAL;
7149 }
7150 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08007151 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07007152 return -ENOSYS;
7153 }
7154 if (out->pcm == NULL) {
7155 return -ENOSYS;
7156 }
7157
7158 struct timespec ts = { 0, 0 };
7159 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
7160 if (ret < 0) {
7161 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
7162 return ret;
7163 }
Phil Burkfe17efd2019-03-25 10:23:35 -07007164 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7165 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07007166 return 0;
7167}
7168
7169
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007170/** audio_stream_in implementation **/
7171static uint32_t in_get_sample_rate(const struct audio_stream *stream)
7172{
7173 struct stream_in *in = (struct stream_in *)stream;
7174
7175 return in->config.rate;
7176}
7177
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007178static int in_set_sample_rate(struct audio_stream *stream __unused,
7179 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007180{
7181 return -ENOSYS;
7182}
7183
7184static size_t in_get_buffer_size(const struct audio_stream *stream)
7185{
7186 struct stream_in *in = (struct stream_in *)stream;
7187
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007188 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
7189 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07007190 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
Raghu Bankapur37cbf382022-12-01 09:30:00 +05307191 return audio_extn_compr_cap_get_buffer_size(pcm_format_to_audio_format(in->config.format));
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307192 else if(audio_extn_cin_attached_usecase(in))
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307193 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007194
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007195 return in->config.period_size * in->af_period_multiplier *
7196 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007197}
7198
7199static uint32_t in_get_channels(const struct audio_stream *stream)
7200{
7201 struct stream_in *in = (struct stream_in *)stream;
7202
7203 return in->channel_mask;
7204}
7205
7206static audio_format_t in_get_format(const struct audio_stream *stream)
7207{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007208 struct stream_in *in = (struct stream_in *)stream;
7209
7210 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007211}
7212
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007213static int in_set_format(struct audio_stream *stream __unused,
7214 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007215{
7216 return -ENOSYS;
7217}
7218
7219static int in_standby(struct audio_stream *stream)
7220{
7221 struct stream_in *in = (struct stream_in *)stream;
7222 struct audio_device *adev = in->dev;
7223 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307224 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
7225 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07007226 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307227
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007228 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007229 if (!in->standby && in->is_st_session) {
7230 ALOGD("%s: sound trigger pcm stop lab", __func__);
7231 audio_extn_sound_trigger_stop_lab(in);
George Gao3018ede2019-10-23 13:23:00 -07007232 if (adev->num_va_sessions > 0)
7233 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007234 in->standby = 1;
7235 }
7236
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007237 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007238 if (adev->adm_deregister_stream)
7239 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
7240
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08007241 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007242 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08007243 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08007244 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08007245 voice_extn_compress_voip_close_input_stream(stream);
7246 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07007247 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
7248 do_stop = in->capture_started;
7249 in->capture_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07007250 if (in->mmap_shared_memory_fd >= 0) {
7251 ALOGV("%s: closing mmap_shared_memory_fd = %d",
7252 __func__, in->mmap_shared_memory_fd);
7253 close(in->mmap_shared_memory_fd);
7254 in->mmap_shared_memory_fd = -1;
7255 }
Zhou Songa8895042016-07-05 17:54:22 +08007256 } else {
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307257 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05307258 audio_extn_cin_close_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08007259 }
7260
Arun Mirpuri5d170872019-03-26 13:21:31 -07007261 if (in->pcm) {
7262 ATRACE_BEGIN("pcm_in_close");
7263 pcm_close(in->pcm);
7264 ATRACE_END();
7265 in->pcm = NULL;
7266 }
7267
Carter Hsu2e429db2019-05-14 18:50:52 +08007268 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08007269 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08007270
George Gao3018ede2019-10-23 13:23:00 -07007271 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
7272 if (adev->num_va_sessions > 0)
7273 adev->num_va_sessions--;
7274 }
Quinn Malef6050362019-01-30 15:55:40 -08007275
Eric Laurent150dbfe2013-02-27 14:31:02 -08007276 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007277 }
7278 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07007279 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007280 return status;
7281}
7282
Aalique Grahame22e49102018-12-18 14:23:57 -08007283static int in_dump(const struct audio_stream *stream,
7284 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007285{
Aalique Grahame22e49102018-12-18 14:23:57 -08007286 struct stream_in *in = (struct stream_in *)stream;
7287
7288 // We try to get the lock for consistency,
7289 // but it isn't necessary for these variables.
7290 // If we're not in standby, we may be blocked on a read.
7291 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
7292 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
7293 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
7294 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
Dechen Chai22768452021-07-30 09:29:16 +05307295#ifndef LINUX_ENABLED
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007296 char buffer[256]; // for statistics formatting
7297 if (in->start_latency_ms.n > 0) {
7298 simple_stats_to_string(&in->start_latency_ms, buffer, sizeof(buffer));
7299 dprintf(fd, " Start latency ms: %s\n", buffer);
7300 }
Dechen Chai22768452021-07-30 09:29:16 +05307301#endif
Aalique Grahame22e49102018-12-18 14:23:57 -08007302 if (locked) {
7303 pthread_mutex_unlock(&in->lock);
7304 }
Dechen Chai22768452021-07-30 09:29:16 +05307305#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -08007306 // dump error info
7307 (void)error_log_dump(
7308 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Dechen Chai22768452021-07-30 09:29:16 +05307309#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007310 return 0;
7311}
7312
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307313static void in_snd_mon_cb(void * stream, struct str_parms * parms)
7314{
7315 if (!stream || !parms)
7316 return;
7317
7318 struct stream_in *in = (struct stream_in *)stream;
7319 struct audio_device *adev = in->dev;
7320
7321 card_status_t status;
7322 int card;
7323 if (parse_snd_card_status(parms, &card, &status) < 0)
7324 return;
7325
7326 pthread_mutex_lock(&adev->lock);
7327 bool valid_cb = (card == adev->snd_card);
7328 pthread_mutex_unlock(&adev->lock);
7329
7330 if (!valid_cb)
7331 return;
7332
7333 lock_input_stream(in);
7334 if (in->card_status != status)
7335 in->card_status = status;
7336 pthread_mutex_unlock(&in->lock);
7337
7338 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
7339 use_case_table[in->usecase],
7340 status == CARD_STATUS_OFFLINE ? "offline" : "online");
7341
7342 // a better solution would be to report error back to AF and let
7343 // it put the stream to standby
7344 if (status == CARD_STATUS_OFFLINE)
7345 in_standby(&in->stream.common);
7346
7347 return;
7348}
7349
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007350int route_input_stream(struct stream_in *in,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007351 struct listnode *devices,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007352 audio_source_t source)
7353{
7354 struct audio_device *adev = in->dev;
7355 int ret = 0;
7356
7357 lock_input_stream(in);
7358 pthread_mutex_lock(&adev->lock);
7359
7360 /* no audio source uses val == 0 */
7361 if ((in->source != source) && (source != AUDIO_SOURCE_DEFAULT)) {
7362 in->source = source;
7363 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
7364 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
7365 (voice_extn_compress_voip_is_format_supported(in->format)) &&
7366 (in->config.rate == 8000 || in->config.rate == 16000 ||
7367 in->config.rate == 32000 || in->config.rate == 48000 ) &&
7368 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
7369 ret = voice_extn_compress_voip_open_input_stream(in);
7370 if (ret != 0) {
7371 ALOGE("%s: Compress voip input cannot be opened, error:%d",
7372 __func__, ret);
7373 }
7374 }
7375 }
7376
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007377 if (!compare_devices(&in->device_list, devices) && !list_empty(devices) &&
7378 is_audio_in_device_type(devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007379 // Workaround: If routing to an non existing usb device, fail gracefully
7380 // The routing request will otherwise block during 10 second
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007381 struct str_parms *usb_addr =
7382 str_parms_create_str(get_usb_device_address(devices));
7383 if (is_usb_in_device_type(devices) && usb_addr &&
Weiyin Jiangabedea32020-12-09 12:49:19 +08007384 !audio_extn_usb_connected(NULL)) {
7385 ALOGW("%s: ignoring rerouting to non existing USB", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007386 ret = -ENOSYS;
7387 } else {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007388 /* If recording is in progress, change the tx device to new device */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007389 assign_devices(&in->device_list, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007390 if (!in->standby && !in->is_st_session) {
7391 ALOGV("update input routing change");
7392 // inform adm before actual routing to prevent glitches.
7393 if (adev->adm_on_routing_change) {
7394 adev->adm_on_routing_change(adev->adm_data,
7395 in->capture_handle);
7396 ret = select_devices(adev, in->usecase);
7397 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7398 adev->adm_routing_changed = true;
7399 }
7400 }
7401 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007402 if (usb_addr)
7403 str_parms_destroy(usb_addr);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007404 }
7405 pthread_mutex_unlock(&adev->lock);
7406 pthread_mutex_unlock(&in->lock);
7407
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07007408 ALOGV("%s: exit: status(%d)", __func__, ret);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007409 return ret;
7410}
7411
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007412static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
7413{
7414 struct stream_in *in = (struct stream_in *)stream;
7415 struct audio_device *adev = in->dev;
7416 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007417 char value[32];
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307418 int err = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007419
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307420 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007421 parms = str_parms_create_str(kvpairs);
7422
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307423 if (!parms)
7424 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007425 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08007426 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007427
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307428 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
7429 if (err >= 0) {
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307430 strlcpy(in->profile, value, sizeof(in->profile));
7431 ALOGV("updating stream profile with value '%s'", in->profile);
7432 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
7433 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007434 &in->device_list, in->flags, in->format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307435 in->sample_rate, in->bit_width,
7436 in->profile, &in->app_type_cfg);
7437 }
7438
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007439 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08007440 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007441
7442 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307443error:
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307444 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007445}
7446
7447static char* in_get_parameters(const struct audio_stream *stream,
7448 const char *keys)
7449{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007450 struct stream_in *in = (struct stream_in *)stream;
7451 struct str_parms *query = str_parms_create_str(keys);
7452 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007453 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007454
7455 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08007456 if (reply) {
7457 str_parms_destroy(reply);
7458 }
7459 if (query) {
7460 str_parms_destroy(query);
7461 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007462 ALOGE("in_get_parameters: failed to create query or reply");
7463 return NULL;
7464 }
7465
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007466 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007467
7468 voice_extn_in_get_parameters(in, query, reply);
7469
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007470 stream_get_parameter_channels(query, reply,
7471 &in->supported_channel_masks[0]);
7472 stream_get_parameter_formats(query, reply,
7473 &in->supported_formats[0]);
7474 stream_get_parameter_rates(query, reply,
7475 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007476 str = str_parms_to_str(reply);
7477 str_parms_destroy(query);
7478 str_parms_destroy(reply);
7479
7480 ALOGV("%s: exit: returns - %s", __func__, str);
7481 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007482}
7483
Aalique Grahame22e49102018-12-18 14:23:57 -08007484static int in_set_gain(struct audio_stream_in *stream,
7485 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007486{
Aalique Grahame22e49102018-12-18 14:23:57 -08007487 struct stream_in *in = (struct stream_in *)stream;
7488 char mixer_ctl_name[128];
7489 struct mixer_ctl *ctl;
7490 int ctl_value;
7491
7492 ALOGV("%s: gain %f", __func__, gain);
7493
7494 if (stream == NULL)
7495 return -EINVAL;
7496
7497 /* in_set_gain() only used to silence MMAP capture for now */
7498 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
7499 return -ENOSYS;
7500
7501 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
7502
7503 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
7504 if (!ctl) {
7505 ALOGW("%s: Could not get ctl for mixer cmd - %s",
7506 __func__, mixer_ctl_name);
7507 return -ENOSYS;
7508 }
7509
7510 if (gain < RECORD_GAIN_MIN)
7511 gain = RECORD_GAIN_MIN;
7512 else if (gain > RECORD_GAIN_MAX)
7513 gain = RECORD_GAIN_MAX;
7514 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
7515
7516 mixer_ctl_set_value(ctl, 0, ctl_value);
7517
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007518 return 0;
7519}
7520
7521static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
7522 size_t bytes)
7523{
7524 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05307525
7526 if (in == NULL) {
7527 ALOGE("%s: stream_in ptr is NULL", __func__);
7528 return -EINVAL;
7529 }
7530
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007531 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05307532 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307533 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007534
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007535 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05307536
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007537 if (in->is_st_session) {
7538 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
7539 /* Read from sound trigger HAL */
7540 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08007541 if (in->standby) {
George Gao3018ede2019-10-23 13:23:00 -07007542 if (adev->num_va_sessions < UINT_MAX)
7543 adev->num_va_sessions++;
Quinn Malef6050362019-01-30 15:55:40 -08007544 in->standby = 0;
7545 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007546 pthread_mutex_unlock(&in->lock);
7547 return bytes;
7548 }
7549
Haynes Mathew George16081042017-05-31 17:16:49 -07007550 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
7551 ret = -ENOSYS;
7552 goto exit;
7553 }
7554
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007555 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
7556 !in->standby && adev->adm_routing_changed) {
7557 ret = -ENOSYS;
7558 goto exit;
7559 }
7560
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007561 if (in->standby) {
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007562 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
7563
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007564 pthread_mutex_lock(&adev->lock);
7565 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
7566 ret = voice_extn_compress_voip_start_input_stream(in);
7567 else
7568 ret = start_input_stream(in);
George Gao3018ede2019-10-23 13:23:00 -07007569 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
7570 if (adev->num_va_sessions < UINT_MAX)
7571 adev->num_va_sessions++;
7572 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007573 pthread_mutex_unlock(&adev->lock);
7574 if (ret != 0) {
7575 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007576 }
7577 in->standby = 0;
Dechen Chai22768452021-07-30 09:29:16 +05307578#ifndef LINUX_ENABLED
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007579 // log startup time in ms.
7580 simple_stats_log(
7581 &in->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Dechen Chai22768452021-07-30 09:29:16 +05307582#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007583 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007584
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05307585 /* Avoid read if capture_stopped is set */
7586 if (android_atomic_acquire_load(&(in->capture_stopped)) > 0) {
7587 ALOGD("%s: force stopped catpure session, ignoring read request", __func__);
7588 ret = -EINVAL;
7589 goto exit;
7590 }
7591
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007592 // what's the duration requested by the client?
7593 long ns = 0;
7594
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307595 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007596 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
7597 in->config.rate;
7598
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007599 ret = request_in_focus(in, ns);
7600 if (ret != 0)
7601 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007602 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007603
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307604 if (audio_extn_cin_attached_usecase(in)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307605 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
7606 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307607 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007608 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307609 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07007610 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007611 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007612 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07007613 } else if (audio_extn_ffv_get_stream() == in) {
7614 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307615 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007616 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307617 /* data from DSP comes in 24_8 format, convert it to 8_24 */
7618 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
7619 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
7620 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307621 ret = -EINVAL;
7622 goto exit;
7623 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307624 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307625 ret = -errno;
7626 }
7627 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307628 /* bytes read is always set to bytes for non compress usecases */
7629 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007630 }
7631
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007632 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007633
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007634 /*
Quinn Malef6050362019-01-30 15:55:40 -08007635 * Instead of writing zeroes here, we could trust the hardware to always
7636 * provide zeroes when muted. This is also muted with voice recognition
7637 * usecases so that other clients do not have access to voice recognition
7638 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007639 */
Quinn Malef6050362019-01-30 15:55:40 -08007640 if ((ret == 0 && voice_get_mic_mute(adev) &&
7641 !voice_is_in_call_rec_stream(in) &&
Zhou Song62ea0282020-03-22 19:53:01 +08007642 (in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY &&
Manoj Kumar N D54cab152023-01-27 16:41:55 +05307643 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY2 &&
7644 in->source != AUDIO_SOURCE_FM_TUNER &&
7645 !is_single_device_type_equal(&in->device_list, AUDIO_DEVICE_IN_FM_TUNER))) ||
Quinn Malef6050362019-01-30 15:55:40 -08007646 (adev->num_va_sessions &&
7647 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
7648 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
7649 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007650 memset(buffer, 0, bytes);
7651
7652exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307653 frame_size = audio_stream_in_frame_size(stream);
7654 if (frame_size > 0)
7655 in->frames_read += bytes_read/frame_size;
7656
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007657 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307658 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007659 pthread_mutex_unlock(&in->lock);
7660
7661 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307662 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307663 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307664 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307665 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307666 in->standby = true;
7667 }
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307668 if (!audio_extn_cin_attached_usecase(in)) {
Sharad Sangled17c9122017-03-20 15:58:52 +05307669 bytes_read = bytes;
7670 memset(buffer, 0, bytes);
7671 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007672 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007673 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7674 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007675 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05307676 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05307677 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007678 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307679 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007680}
7681
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007682static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007683{
7684 return 0;
7685}
7686
Aalique Grahame22e49102018-12-18 14:23:57 -08007687static int in_get_capture_position(const struct audio_stream_in *stream,
7688 int64_t *frames, int64_t *time)
7689{
7690 if (stream == NULL || frames == NULL || time == NULL) {
7691 return -EINVAL;
7692 }
7693 struct stream_in *in = (struct stream_in *)stream;
7694 int ret = -ENOSYS;
7695
7696 lock_input_stream(in);
7697 // note: ST sessions do not close the alsa pcm driver synchronously
7698 // on standby. Therefore, we may return an error even though the
7699 // pcm stream is still opened.
7700 if (in->standby) {
7701 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
7702 "%s stream in standby but pcm not NULL for non ST session", __func__);
7703 goto exit;
7704 }
7705 if (in->pcm) {
7706 struct timespec timestamp;
7707 unsigned int avail;
7708 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
7709 *frames = in->frames_read + avail;
Robert Lee58215542019-07-15 20:55:12 +08007710 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec
George Gao9ba8a142020-07-23 14:30:03 -07007711 - platform_capture_latency(in) * 1000LL;
Kakanaboina Ramanjaneyulu8cedb092021-03-15 15:55:29 +05307712 //Adjustment accounts for A2dp decoder latency for recording usecase
7713 // Note: decoder latency is returned in ms, while platform_capture_latency in ns.
7714 if (is_a2dp_in_device_type(&in->device_list))
7715 *time -= audio_extn_a2dp_get_decoder_latency() * 1000000LL;
Aalique Grahame22e49102018-12-18 14:23:57 -08007716 ret = 0;
7717 }
7718 }
7719exit:
7720 pthread_mutex_unlock(&in->lock);
7721 return ret;
7722}
7723
Carter Hsu2e429db2019-05-14 18:50:52 +08007724static int in_update_effect_list(bool add, effect_handle_t effect,
7725 struct listnode *head)
7726{
7727 struct listnode *node;
7728 struct in_effect_list *elist = NULL;
7729 struct in_effect_list *target = NULL;
7730 int ret = 0;
7731
7732 if (!head)
7733 return ret;
7734
7735 list_for_each(node, head) {
7736 elist = node_to_item(node, struct in_effect_list, list);
7737 if (elist->handle == effect) {
7738 target = elist;
7739 break;
7740 }
7741 }
7742
7743 if (add) {
7744 if (target) {
7745 ALOGD("effect %p already exist", effect);
7746 return ret;
7747 }
7748
7749 target = (struct in_effect_list *)
7750 calloc(1, sizeof(struct in_effect_list));
7751
7752 if (!target) {
7753 ALOGE("%s:fail to allocate memory", __func__);
7754 return -ENOMEM;
7755 }
7756
7757 target->handle = effect;
7758 list_add_tail(head, &target->list);
7759 } else {
7760 if (target) {
7761 list_remove(&target->list);
7762 free(target);
7763 }
7764 }
7765
7766 return ret;
7767}
7768
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007769static int add_remove_audio_effect(const struct audio_stream *stream,
7770 effect_handle_t effect,
7771 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007772{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007773 struct stream_in *in = (struct stream_in *)stream;
7774 int status = 0;
7775 effect_descriptor_t desc;
7776
7777 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007778 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
7779
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007780 if (status != 0)
7781 return status;
7782
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007783 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007784 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08007785 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08007786 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
7787 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007788 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08007789
7790 in_update_effect_list(enable, effect, &in->aec_list);
7791 enable = !list_empty(&in->aec_list);
7792 if (enable == in->enable_aec)
7793 goto exit;
7794
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007795 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007796 ALOGD("AEC enable %d", enable);
7797
Aalique Grahame22e49102018-12-18 14:23:57 -08007798 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7799 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
7800 in->dev->enable_voicerx = enable;
7801 struct audio_usecase *usecase;
7802 struct listnode *node;
7803 list_for_each(node, &in->dev->usecase_list) {
7804 usecase = node_to_item(node, struct audio_usecase, list);
7805 if (usecase->type == PCM_PLAYBACK)
7806 select_devices(in->dev, usecase->id);
7807 }
7808 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007809 if (!in->standby) {
7810 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
7811 select_devices(in->dev, in->usecase);
7812 }
7813
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007814 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007815 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
7816
7817 in_update_effect_list(enable, effect, &in->ns_list);
7818 enable = !list_empty(&in->ns_list);
7819 if (enable == in->enable_ns)
7820 goto exit;
7821
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007822 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007823 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007824 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08007825 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Ramu Gottipatifa5be522021-12-28 19:18:21 +05307826 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
kunleizd96526c2018-04-09 11:12:32 +08007827 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007828 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
7829 select_devices(in->dev, in->usecase);
7830 } else
7831 select_devices(in->dev, in->usecase);
7832 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007833 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007834exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007835 pthread_mutex_unlock(&in->dev->lock);
7836 pthread_mutex_unlock(&in->lock);
7837
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007838 return 0;
7839}
7840
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007841static int in_add_audio_effect(const struct audio_stream *stream,
7842 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007843{
Eric Laurent994a6932013-07-17 11:51:42 -07007844 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007845 return add_remove_audio_effect(stream, effect, true);
7846}
7847
7848static int in_remove_audio_effect(const struct audio_stream *stream,
7849 effect_handle_t effect)
7850{
Eric Laurent994a6932013-07-17 11:51:42 -07007851 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007852 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007853}
7854
Haynes Mathew George16081042017-05-31 17:16:49 -07007855static int in_stop(const struct audio_stream_in* stream)
7856{
7857 struct stream_in *in = (struct stream_in *)stream;
7858 struct audio_device *adev = in->dev;
7859
7860 int ret = -ENOSYS;
7861 ALOGV("%s", __func__);
7862 pthread_mutex_lock(&adev->lock);
7863 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7864 in->capture_started && in->pcm != NULL) {
7865 pcm_stop(in->pcm);
7866 ret = stop_input_stream(in);
7867 in->capture_started = false;
7868 }
7869 pthread_mutex_unlock(&adev->lock);
7870 return ret;
7871}
7872
7873static int in_start(const struct audio_stream_in* stream)
7874{
7875 struct stream_in *in = (struct stream_in *)stream;
7876 struct audio_device *adev = in->dev;
7877 int ret = -ENOSYS;
7878
7879 ALOGV("%s in %p", __func__, in);
7880 pthread_mutex_lock(&adev->lock);
7881 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7882 !in->capture_started && in->pcm != NULL) {
7883 if (!in->capture_started) {
7884 ret = start_input_stream(in);
7885 if (ret == 0) {
7886 in->capture_started = true;
7887 }
7888 }
7889 }
7890 pthread_mutex_unlock(&adev->lock);
7891 return ret;
7892}
7893
Phil Burke0a86d12019-02-16 22:28:11 -08007894// Read offset for the positional timestamp from a persistent vendor property.
7895// This is to workaround apparent inaccuracies in the timing information that
7896// is used by the AAudio timing model. The inaccuracies can cause glitches.
7897static int64_t in_get_mmap_time_offset() {
7898 const int32_t kDefaultOffsetMicros = 0;
7899 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08007900 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08007901 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
7902 return mmap_time_offset_micros * (int64_t)1000;
7903}
7904
Haynes Mathew George16081042017-05-31 17:16:49 -07007905static int in_create_mmap_buffer(const struct audio_stream_in *stream,
7906 int32_t min_size_frames,
7907 struct audio_mmap_buffer_info *info)
7908{
7909 struct stream_in *in = (struct stream_in *)stream;
7910 struct audio_device *adev = in->dev;
7911 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07007912 unsigned int offset1 = 0;
7913 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007914 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07007915 uint32_t mmap_size = 0;
7916 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007917
7918 pthread_mutex_lock(&adev->lock);
7919 ALOGV("%s in %p", __func__, in);
7920
Sharad Sanglec6f32552018-05-04 16:15:38 +05307921 if (CARD_STATUS_OFFLINE == in->card_status||
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05007922 CARD_STATUS_OFFLINE == adev->card_status ||
7923 POWER_POLICY_STATUS_OFFLINE == adev->in_power_policy) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307924 ALOGW("in->card_status or adev->card_status offline, try again");
7925 ret = -EIO;
7926 goto exit;
7927 }
7928
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307929 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07007930 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
7931 ret = -EINVAL;
7932 goto exit;
7933 }
7934 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
7935 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
7936 ALOGV("%s in %p", __func__, in);
7937 ret = -ENOSYS;
7938 goto exit;
7939 }
7940 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
7941 if (in->pcm_device_id < 0) {
7942 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
7943 __func__, in->pcm_device_id, in->usecase);
7944 ret = -EINVAL;
7945 goto exit;
7946 }
7947
7948 adjust_mmap_period_count(&in->config, min_size_frames);
7949
7950 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
7951 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
7952 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
7953 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307954 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307955 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7956 in->card_status = CARD_STATUS_OFFLINE;
7957 adev->card_status = CARD_STATUS_OFFLINE;
7958 ret = -EIO;
7959 goto exit;
7960 }
7961
Haynes Mathew George16081042017-05-31 17:16:49 -07007962 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
7963 step = "open";
7964 ret = -ENODEV;
7965 goto exit;
7966 }
7967
7968 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
7969 if (ret < 0) {
7970 step = "begin";
7971 goto exit;
7972 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007973
juyuchen626833d2019-06-04 16:48:02 +08007974 info->flags = 0;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007975 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
7976 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
7977 info->burst_size_frames = in->config.period_size;
7978 ret = platform_get_mmap_data_fd(adev->platform,
7979 in->pcm_device_id, 1 /*capture*/,
7980 &info->shared_memory_fd,
7981 &mmap_size);
7982 if (ret < 0) {
7983 // Fall back to non exclusive mode
7984 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
7985 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07007986 in->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
7987 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, in->mmap_shared_memory_fd);
7988
Arun Mirpuri5d170872019-03-26 13:21:31 -07007989 if (mmap_size < buffer_size) {
7990 step = "mmap";
7991 goto exit;
7992 }
juyuchen626833d2019-06-04 16:48:02 +08007993 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007994 }
7995
7996 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07007997
7998 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
7999 if (ret < 0) {
8000 step = "commit";
8001 goto exit;
8002 }
8003
Phil Burke0a86d12019-02-16 22:28:11 -08008004 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
8005
Haynes Mathew George16081042017-05-31 17:16:49 -07008006 in->standby = false;
8007 ret = 0;
8008
8009 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
8010 __func__, info->shared_memory_address, info->buffer_size_frames);
8011
8012exit:
8013 if (ret != 0) {
8014 if (in->pcm == NULL) {
8015 ALOGE("%s: %s - %d", __func__, step, ret);
8016 } else {
8017 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
8018 pcm_close(in->pcm);
8019 in->pcm = NULL;
8020 }
8021 }
8022 pthread_mutex_unlock(&adev->lock);
8023 return ret;
8024}
8025
8026static int in_get_mmap_position(const struct audio_stream_in *stream,
8027 struct audio_mmap_position *position)
8028{
8029 struct stream_in *in = (struct stream_in *)stream;
8030 ALOGVV("%s", __func__);
8031 if (position == NULL) {
8032 return -EINVAL;
8033 }
Gautam Manam34d1f542021-01-05 20:24:37 +05308034 lock_input_stream(in);
Haynes Mathew George16081042017-05-31 17:16:49 -07008035 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
Gautam Manam34d1f542021-01-05 20:24:37 +05308036 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07008037 return -ENOSYS;
8038 }
8039 if (in->pcm == NULL) {
Gautam Manam34d1f542021-01-05 20:24:37 +05308040 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07008041 return -ENOSYS;
8042 }
8043 struct timespec ts = { 0, 0 };
8044 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
8045 if (ret < 0) {
8046 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
Gautam Manam34d1f542021-01-05 20:24:37 +05308047 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07008048 return ret;
8049 }
Phil Burke0a86d12019-02-16 22:28:11 -08008050 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
8051 + in->mmap_time_offset_nanos;
Gautam Manam34d1f542021-01-05 20:24:37 +05308052 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07008053 return 0;
8054}
8055
Naresh Tannirudcb47c52018-06-25 16:23:32 +05308056static int in_get_active_microphones(const struct audio_stream_in *stream,
8057 struct audio_microphone_characteristic_t *mic_array,
8058 size_t *mic_count) {
8059 struct stream_in *in = (struct stream_in *)stream;
8060 struct audio_device *adev = in->dev;
8061 ALOGVV("%s", __func__);
8062
8063 lock_input_stream(in);
8064 pthread_mutex_lock(&adev->lock);
8065 int ret = platform_get_active_microphones(adev->platform,
8066 audio_channel_count_from_in_mask(in->channel_mask),
8067 in->usecase, mic_array, mic_count);
8068 pthread_mutex_unlock(&adev->lock);
8069 pthread_mutex_unlock(&in->lock);
8070
8071 return ret;
8072}
8073
8074static int adev_get_microphones(const struct audio_hw_device *dev,
8075 struct audio_microphone_characteristic_t *mic_array,
8076 size_t *mic_count) {
8077 struct audio_device *adev = (struct audio_device *)dev;
8078 ALOGVV("%s", __func__);
8079
8080 pthread_mutex_lock(&adev->lock);
8081 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
8082 pthread_mutex_unlock(&adev->lock);
8083
8084 return ret;
8085}
juyuchendb308c22019-01-21 11:57:17 -07008086
8087static void in_update_sink_metadata(struct audio_stream_in *stream,
8088 const struct sink_metadata *sink_metadata) {
8089
8090 if (stream == NULL
8091 || sink_metadata == NULL
8092 || sink_metadata->tracks == NULL) {
8093 return;
8094 }
8095
8096 int error = 0;
8097 struct stream_in *in = (struct stream_in *)stream;
8098 struct audio_device *adev = in->dev;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008099 struct listnode devices;
8100
8101 list_init(&devices);
juyuchendb308c22019-01-21 11:57:17 -07008102
8103 if (sink_metadata->track_count != 0)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008104 reassign_device_list(&devices, sink_metadata->tracks->dest_device, "");
juyuchendb308c22019-01-21 11:57:17 -07008105
8106 lock_input_stream(in);
8107 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008108 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, get_device_types(&devices));
juyuchendb308c22019-01-21 11:57:17 -07008109
Zhou Song503196b2021-07-23 17:31:05 +08008110 if ((in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY ||
8111 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2) &&
8112 !list_empty(&devices) &&
8113 adev->voice_tx_output != NULL) {
juyuchendb308c22019-01-21 11:57:17 -07008114 /* Use the rx device from afe-proxy record to route voice call because
8115 there is no routing if tx device is on primary hal and rx device
8116 is on other hal during voice call. */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008117 assign_devices(&adev->voice_tx_output->device_list, &devices);
juyuchendb308c22019-01-21 11:57:17 -07008118
8119 if (!voice_is_call_state_active(adev)) {
8120 if (adev->mode == AUDIO_MODE_IN_CALL) {
8121 adev->current_call_output = adev->voice_tx_output;
8122 error = voice_start_call(adev);
8123 if (error != 0)
8124 ALOGE("%s: start voice call failed %d", __func__, error);
8125 }
8126 } else {
8127 adev->current_call_output = adev->voice_tx_output;
8128 voice_update_devices_for_all_voice_usecases(adev);
8129 }
8130 }
8131
Zhenlin Lian4f947842022-05-14 15:50:52 +05308132 clear_devices(&devices);
juyuchendb308c22019-01-21 11:57:17 -07008133 pthread_mutex_unlock(&adev->lock);
8134 pthread_mutex_unlock(&in->lock);
8135}
8136
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308137int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07008138 audio_io_handle_t handle,
8139 audio_devices_t devices,
8140 audio_output_flags_t flags,
8141 struct audio_config *config,
8142 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04008143 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008144{
8145 struct audio_device *adev = (struct audio_device *)dev;
8146 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05308147 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008148 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008149 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05308150 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008151 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
8152 bool is_usb_dev = audio_is_usb_out_device(devices) &&
8153 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
8154 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008155 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07008156 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
8157 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008158 bool force_haptic_path =
8159 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07008160 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008161#ifdef AUDIO_GKI_ENABLED
8162 __s32 *generic_dec;
8163#endif
Weiyin Jiang906db3c2021-03-02 13:17:04 +08008164 pthread_mutexattr_t latch_attr;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008165
kunleizdff872d2018-08-20 14:40:33 +08008166 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08008167 is_usb_dev = false;
8168 devices = AUDIO_DEVICE_OUT_SPEAKER;
8169 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
8170 __func__, devices);
Mingshu Pangdbd20562019-11-25 18:04:39 +08008171 if (config->format == AUDIO_FORMAT_DEFAULT)
8172 config->format = AUDIO_FORMAT_PCM_16_BIT;
8173 if (config->sample_rate == 0)
8174 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8175 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8176 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
kunleizd6a9e0c2018-07-30 15:38:52 +08008177 }
8178
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008179 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05308180
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008181 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
8182
Mingming Yin3a941d42016-02-17 18:08:05 -08008183 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04008184 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
8185 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308186
8187
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008188 if (!out) {
8189 return -ENOMEM;
8190 }
8191
Haynes Mathew George204045b2015-02-25 20:32:03 -08008192 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07008193 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Weiyin Jiang906db3c2021-03-02 13:17:04 +08008194 pthread_mutexattr_init(&latch_attr);
8195 pthread_mutexattr_settype(&latch_attr, PTHREAD_MUTEX_RECURSIVE);
8196 pthread_mutex_init(&out->latch_lock, &latch_attr);
8197 pthread_mutexattr_destroy(&latch_attr);
Zhou Song48453a02018-01-10 17:50:59 +08008198 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08008199 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
8200
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008201 if (devices == AUDIO_DEVICE_NONE)
8202 devices = AUDIO_DEVICE_OUT_SPEAKER;
8203
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008204 out->flags = flags;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008205 list_init(&out->device_list);
8206 update_device_list(&out->device_list, devices, address, true /* add devices */);
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07008207 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07008208 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008209 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05308210 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05308211 if (out->channel_mask == AUDIO_CHANNEL_NONE)
8212 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
8213 else
8214 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07008215 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07008216 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08008217 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308218 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308219 out->started = 0;
Zhou Songbaddf9f2020-11-20 13:57:39 +08008220 out->a2dp_muted = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008221 out->hal_output_suspend_supported = 0;
8222 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05308223 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05308224 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05308225 out->pspd_coeff_sent = false;
Phil Burkd898ba62019-06-20 12:49:01 -07008226 out->mmap_shared_memory_fd = -1; // not open
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008227
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05308228 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05308229 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07008230 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
8231
Aalique Grahame22e49102018-12-18 14:23:57 -08008232 if (direct_dev &&
8233 (audio_is_linear_pcm(out->format) ||
8234 config->format == AUDIO_FORMAT_DEFAULT) &&
8235 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
8236 audio_format_t req_format = config->format;
8237 audio_channel_mask_t req_channel_mask = config->channel_mask;
8238 uint32_t req_sample_rate = config->sample_rate;
8239
8240 pthread_mutex_lock(&adev->lock);
8241 if (is_hdmi) {
8242 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
8243 ret = read_hdmi_sink_caps(out);
8244 if (config->sample_rate == 0)
8245 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8246 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8247 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
8248 if (config->format == AUDIO_FORMAT_DEFAULT)
8249 config->format = AUDIO_FORMAT_PCM_16_BIT;
8250 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008251 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
8252 &config->format,
8253 &out->supported_formats[0],
8254 MAX_SUPPORTED_FORMATS,
8255 &config->channel_mask,
8256 &out->supported_channel_masks[0],
8257 MAX_SUPPORTED_CHANNEL_MASKS,
8258 &config->sample_rate,
8259 &out->supported_sample_rates[0],
8260 MAX_SUPPORTED_SAMPLE_RATES);
8261 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008262 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008263
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008264 pthread_mutex_unlock(&adev->lock);
8265 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08008266 if (ret == -ENOSYS) {
8267 /* ignore and go with default */
8268 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08008269 }
8270 // For MMAP NO IRQ, allow conversions in ADSP
8271 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
8272 goto error_open;
8273 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008274 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08008275 goto error_open;
8276 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008277
8278 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
8279 config->sample_rate = req_sample_rate;
8280 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
8281 config->channel_mask = req_channel_mask;
8282 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
8283 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08008284 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008285
8286 out->sample_rate = config->sample_rate;
8287 out->channel_mask = config->channel_mask;
8288 out->format = config->format;
8289 if (is_hdmi) {
8290 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
8291 out->config = pcm_config_hdmi_multi;
8292 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8293 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8294 out->config = pcm_config_mmap_playback;
8295 out->stream.start = out_start;
8296 out->stream.stop = out_stop;
8297 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8298 out->stream.get_mmap_position = out_get_mmap_position;
8299 } else {
8300 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
8301 out->config = pcm_config_hifi;
8302 }
8303
8304 out->config.rate = out->sample_rate;
8305 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
8306 if (is_hdmi) {
8307 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
8308 audio_bytes_per_sample(out->format));
8309 }
8310 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08008311 }
8312
Derek Chenf6318be2017-06-12 17:16:24 -04008313 /* validate bus device address */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008314 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008315 /* extract car audio stream index */
8316 out->car_audio_stream =
8317 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
8318 if (out->car_audio_stream < 0) {
8319 ALOGE("%s: invalid car audio stream %x",
8320 __func__, out->car_audio_stream);
8321 ret = -EINVAL;
8322 goto error_open;
8323 }
Derek Chen5f67a942020-02-24 23:08:13 -08008324 ALOGV("%s: car_audio_stream %x", __func__, out->car_audio_stream);
Derek Chenf6318be2017-06-12 17:16:24 -04008325 }
8326
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008327 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07008328 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008329 if (!voice_extn_is_compress_voip_supported()) {
8330 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
8331 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07008332 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
Lakshman Chaluvarajue7fc9482020-05-30 14:29:29 +05308333 config->channel_mask : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008334 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
8335 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07008336 out->volume_l = INVALID_OUT_VOLUME;
8337 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07008338
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008339 out->config = default_pcm_config_voip_copp;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008340 out->config.rate = out->sample_rate;
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07008341 uint32_t channel_count =
8342 audio_channel_count_from_out_mask(out->channel_mask);
Ramjee Singh968858a2020-08-06 16:30:48 +05308343 out->config.channels = channel_count;
8344
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07008345 uint32_t buffer_size = get_stream_buffer_size(DEFAULT_VOIP_BUF_DURATION_MS,
8346 out->sample_rate, out->format,
8347 channel_count, false);
8348 uint32_t frame_size = audio_bytes_per_sample(out->format) * channel_count;
8349 if (frame_size != 0)
8350 out->config.period_size = buffer_size / frame_size;
8351 else
8352 ALOGW("%s: frame size is 0 for format %#x", __func__, out->format);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008353 }
8354 } else {
8355 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
8356 voice_extn_compress_voip_is_active(out->dev)) &&
8357 (voice_extn_compress_voip_is_config_supported(config))) {
8358 ret = voice_extn_compress_voip_open_output_stream(out);
8359 if (ret != 0) {
8360 ALOGE("%s: Compress voip output cannot be opened, error:%d",
8361 __func__, ret);
8362 goto error_open;
8363 }
Sujin Panicker19027262019-09-16 18:28:06 +05308364 } else {
8365 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8366 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008367 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008368 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008369 } else if (audio_is_linear_pcm(out->format) &&
8370 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
8371 out->channel_mask = config->channel_mask;
8372 out->sample_rate = config->sample_rate;
8373 out->format = config->format;
8374 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
8375 // does this change?
8376 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
8377 out->config.rate = config->sample_rate;
8378 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
8379 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
8380 audio_bytes_per_sample(config->format));
8381 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07008382 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308383 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308384 pthread_mutex_lock(&adev->lock);
8385 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
8386 pthread_mutex_unlock(&adev->lock);
8387
8388 // reject offload during card offline to allow
8389 // fallback to s/w paths
8390 if (offline) {
8391 ret = -ENODEV;
8392 goto error_open;
8393 }
vivek mehta0ea887a2015-08-26 14:01:20 -07008394
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008395 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
8396 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
8397 ALOGE("%s: Unsupported Offload information", __func__);
8398 ret = -EINVAL;
8399 goto error_open;
8400 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008401
Atul Khare3fa6e542017-08-09 00:56:17 +05308402 if (config->offload_info.format == 0)
8403 config->offload_info.format = config->format;
8404 if (config->offload_info.sample_rate == 0)
8405 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008406
Mingming Yin90310102013-11-13 16:57:00 -08008407 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308408 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07008409 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008410 ret = -EINVAL;
8411 goto error_open;
8412 }
8413
Ben Romberger0f8c87b2017-05-24 17:41:11 -07008414 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
8415 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
8416 (audio_extn_passthru_is_passthrough_stream(out)) &&
8417 !((config->sample_rate == 48000) ||
8418 (config->sample_rate == 96000) ||
8419 (config->sample_rate == 192000))) {
8420 ALOGE("%s: Unsupported sample rate %d for audio format %x",
8421 __func__, config->sample_rate, config->offload_info.format);
8422 ret = -EINVAL;
8423 goto error_open;
8424 }
8425
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008426 out->compr_config.codec = (struct snd_codec *)
8427 calloc(1, sizeof(struct snd_codec));
8428
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008429 if (!out->compr_config.codec) {
8430 ret = -ENOMEM;
8431 goto error_open;
8432 }
8433
Dhananjay Kumarac341582017-02-23 23:42:25 +05308434 out->stream.pause = out_pause;
8435 out->stream.resume = out_resume;
8436 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05308437 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05308438 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07008439 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05308440 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07008441 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05308442 } else {
8443 out->usecase = get_offload_usecase(adev, false /* is_compress */);
8444 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07008445 }
vivek mehta446c3962015-09-14 10:57:35 -07008446
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308447 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8448 ALOGD("%s: Setting latency mode to true", __func__);
Meng Wang4c32fb42020-01-16 17:57:11 +08008449#ifdef AUDIO_GKI_ENABLED
8450 /* out->compr_config.codec->reserved[1] is for flags */
8451 out->compr_config.codec->reserved[1] |= audio_extn_utils_get_perf_mode_flag();
8452#else
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308453 out->compr_config.codec->flags |= audio_extn_utils_get_perf_mode_flag();
Meng Wang4c32fb42020-01-16 17:57:11 +08008454#endif
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308455 }
8456
vivek mehta446c3962015-09-14 10:57:35 -07008457 if (out->usecase == USECASE_INVALID) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008458 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Mingming Yin3a941d42016-02-17 18:08:05 -08008459 config->format == 0 && config->sample_rate == 0 &&
8460 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07008461 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08008462 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
8463 } else {
8464 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
8465 ret = -EEXIST;
8466 goto error_open;
8467 }
vivek mehta446c3962015-09-14 10:57:35 -07008468 }
8469
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008470 if (config->offload_info.channel_mask)
8471 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008472 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008473 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008474 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008475 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05308476 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008477 ret = -EINVAL;
8478 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008479 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008480
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008481 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008482 out->sample_rate = config->offload_info.sample_rate;
8483
Mingming Yin3ee55c62014-08-04 14:23:35 -07008484 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008485
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308486 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05308487 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308488 audio_extn_dolby_send_ddp_endp_params(adev);
8489 audio_extn_dolby_set_dmid(adev);
8490 }
vivek mehta0ea887a2015-08-26 14:01:20 -07008491
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008492 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08008493 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008494 out->compr_config.codec->bit_rate =
8495 config->offload_info.bit_rate;
8496 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05308497 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008498 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05308499 /* Update bit width only for non passthrough usecases.
8500 * For passthrough usecases, the output will always be opened @16 bit
8501 */
8502 if (!audio_extn_passthru_is_passthrough_stream(out))
8503 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308504
8505 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
Meng Wang4c32fb42020-01-16 17:57:11 +08008506#ifdef AUDIO_GKI_ENABLED
8507 /* out->compr_config.codec->reserved[1] is for flags */
8508 out->compr_config.codec->reserved[1] |= COMPRESSED_TIMESTAMP_FLAG;
8509 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->reserved[1]);
8510#else
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308511 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
8512 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
Meng Wang4c32fb42020-01-16 17:57:11 +08008513#endif
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308514
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008515 /*TODO: Do we need to change it for passthrough */
8516 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008517
Manish Dewangana6fc5442015-08-24 20:30:31 +05308518 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
8519 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308520 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05308521 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308522 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
8523 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308524
8525 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
8526 AUDIO_FORMAT_PCM) {
8527
8528 /*Based on platform support, configure appropriate alsa format for corresponding
8529 *hal input format.
8530 */
8531 out->compr_config.codec->format = hal_format_to_alsa(
8532 config->offload_info.format);
8533
Ashish Jain83a6cc22016-06-28 14:34:17 +05308534 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05308535 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308536 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308537
Dhananjay Kumarac341582017-02-23 23:42:25 +05308538 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05308539 *hal input format and alsa format might differ based on platform support.
8540 */
8541 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05308542 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308543
8544 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
8545
Deeraj Soman93155a62019-09-30 19:00:37 +05308546 if (property_get_bool("vendor.audio.offload.buffer.duration.enabled", false)) {
8547 if ((config->offload_info.duration_us >= MIN_OFFLOAD_BUFFER_DURATION_MS * 1000) &&
8548 (config->offload_info.duration_us <= MAX_OFFLOAD_BUFFER_DURATION_MS * 1000))
8549 out->info.duration_us = (int64_t)config->offload_info.duration_us;
8550 }
Deeraj Soman65358ab2019-02-07 15:40:49 +05308551
Ashish Jainf1eaa582016-05-23 20:54:24 +05308552 /* Check if alsa session is configured with the same format as HAL input format,
8553 * if not then derive correct fragment size needed to accomodate the
8554 * conversion of HAL input format to alsa format.
8555 */
8556 audio_extn_utils_update_direct_pcm_fragment_size(out);
8557
8558 /*if hal input and output fragment size is different this indicates HAL input format is
8559 *not same as the alsa format
8560 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308561 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05308562 /*Allocate a buffer to convert input data to the alsa configured format.
8563 *size of convert buffer is equal to the size required to hold one fragment size
8564 *worth of pcm data, this is because flinger does not write more than fragment_size
8565 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308566 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
8567 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05308568 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
8569 ret = -ENOMEM;
8570 goto error_open;
8571 }
8572 }
8573 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
8574 out->compr_config.fragment_size =
8575 audio_extn_passthru_get_buffer_size(&config->offload_info);
8576 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8577 } else {
8578 out->compr_config.fragment_size =
8579 platform_get_compress_offload_buffer_size(&config->offload_info);
8580 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8581 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008582
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308583 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8584 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
8585 }
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008586 if (config->offload_info.format == AUDIO_FORMAT_FLAC) {
8587#ifdef AUDIO_GKI_ENABLED
8588 generic_dec =
8589 &(out->compr_config.codec->options.generic.reserved[1]);
8590 ((struct snd_generic_dec_flac *)generic_dec)->sample_size =
8591 AUDIO_OUTPUT_BIT_WIDTH;
8592#else
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05308593 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008594#endif
8595 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008596
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05308597 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
8598 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
8599 }
8600
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008601 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
8602 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008603
Manish Dewangan69426c82017-01-30 17:35:36 +05308604 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
8605 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
8606 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
8607 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8608 out->render_mode = RENDER_MODE_AUDIO_MASTER;
8609 } else {
8610 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
8611 }
Alexy Josephaa54c872014-12-03 02:46:47 -08008612
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05308613 memset(&out->channel_map_param, 0,
8614 sizeof(struct audio_out_channel_map_param));
8615
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008616 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05308617 out->send_next_track_params = false;
8618 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008619 out->offload_state = OFFLOAD_STATE_IDLE;
8620 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08008621 out->writeAt.tv_sec = 0;
8622 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008623
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008624 audio_extn_dts_create_state_notifier_node(out->usecase);
8625
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008626 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
8627 __func__, config->offload_info.version,
8628 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05308629
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308630 /* Check if DSD audio format is supported in codec
8631 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308632 */
8633
8634 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308635 (!platform_check_codec_dsd_support(adev->platform) ||
8636 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308637 ret = -EINVAL;
8638 goto error_open;
8639 }
8640
Ashish Jain5106d362016-05-11 19:23:33 +05308641 /* Disable gapless if any of the following is true
8642 * passthrough playback
8643 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05308644 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05308645 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308646 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308647 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07008648 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308649 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308650 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05308651 check_and_set_gapless_mode(adev, false);
8652 } else
8653 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07008654
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308655 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07008656 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
8657 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308658 if (config->format == AUDIO_FORMAT_DSD) {
8659 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
Meng Wang4c32fb42020-01-16 17:57:11 +08008660#ifdef AUDIO_GKI_ENABLED
8661 /* out->compr_config.codec->reserved[0] is for compr_passthr */
8662 out->compr_config.codec->reserved[0] = PASSTHROUGH_DSD;
8663#else
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308664 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
Meng Wang4c32fb42020-01-16 17:57:11 +08008665#endif
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308666 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07008667
8668 create_offload_callback_thread(out);
8669
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008670 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008671 switch (config->sample_rate) {
8672 case 0:
8673 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8674 break;
8675 case 8000:
8676 case 16000:
8677 case 48000:
8678 out->sample_rate = config->sample_rate;
8679 break;
8680 default:
8681 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
8682 config->sample_rate);
8683 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8684 ret = -EINVAL;
8685 goto error_open;
8686 }
8687 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8688 switch (config->channel_mask) {
8689 case AUDIO_CHANNEL_NONE:
8690 case AUDIO_CHANNEL_OUT_STEREO:
8691 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8692 break;
8693 default:
8694 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
8695 config->channel_mask);
8696 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8697 ret = -EINVAL;
8698 goto error_open;
8699 }
8700 switch (config->format) {
8701 case AUDIO_FORMAT_DEFAULT:
8702 case AUDIO_FORMAT_PCM_16_BIT:
8703 out->format = AUDIO_FORMAT_PCM_16_BIT;
8704 break;
8705 default:
8706 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
8707 config->format);
8708 config->format = AUDIO_FORMAT_PCM_16_BIT;
8709 ret = -EINVAL;
8710 goto error_open;
8711 }
8712
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05308713 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008714 if (ret != 0) {
8715 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008716 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008717 goto error_open;
8718 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008719 } else if (is_single_device_type_equal(&out->device_list,
8720 AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08008721 switch (config->sample_rate) {
8722 case 0:
8723 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
8724 break;
8725 case 8000:
8726 case 16000:
8727 case 48000:
8728 out->sample_rate = config->sample_rate;
8729 break;
8730 default:
8731 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
8732 config->sample_rate);
8733 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8734 ret = -EINVAL;
8735 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008736 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008737 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8738 switch (config->channel_mask) {
8739 case AUDIO_CHANNEL_NONE:
8740 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8741 break;
8742 case AUDIO_CHANNEL_OUT_STEREO:
8743 out->channel_mask = config->channel_mask;
8744 break;
8745 default:
8746 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
8747 config->channel_mask);
8748 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8749 ret = -EINVAL;
8750 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008751 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008752 switch (config->format) {
8753 case AUDIO_FORMAT_DEFAULT:
8754 out->format = AUDIO_FORMAT_PCM_16_BIT;
8755 break;
8756 case AUDIO_FORMAT_PCM_16_BIT:
8757 out->format = config->format;
8758 break;
8759 default:
8760 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
8761 config->format);
8762 config->format = AUDIO_FORMAT_PCM_16_BIT;
8763 ret = -EINVAL;
8764 break;
8765 }
8766 if (ret != 0)
8767 goto error_open;
8768
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008769 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
8770 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08008771 out->config.rate = out->sample_rate;
8772 out->config.channels =
8773 audio_channel_count_from_out_mask(out->channel_mask);
8774 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008775 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008776 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05308777 unsigned int channels = 0;
8778 /*Update config params to default if not set by the caller*/
8779 if (config->sample_rate == 0)
8780 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8781 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8782 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8783 if (config->format == AUDIO_FORMAT_DEFAULT)
8784 config->format = AUDIO_FORMAT_PCM_16_BIT;
8785
8786 channels = audio_channel_count_from_out_mask(out->channel_mask);
8787
Varun Balaraje49253e2017-07-06 19:48:56 +05308788 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
8789 out->usecase = get_interactive_usecase(adev);
8790 out->config = pcm_config_low_latency;
8791 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05308792 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008793 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
8794 out->flags);
8795 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07008796 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8797 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8798 out->config = pcm_config_mmap_playback;
8799 out->stream.start = out_start;
8800 out->stream.stop = out_stop;
8801 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8802 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308803 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8804 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008805 out->hal_output_suspend_supported =
8806 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
8807 out->dynamic_pm_qos_config_supported =
8808 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
8809 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08008810 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
8811 } else {
8812 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
8813 //the mixer path will be a string similar to "low-latency-playback resume"
8814 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
8815 strlcat(out->pm_qos_mixer_path,
8816 " resume", MAX_MIXER_PATH_LEN);
8817 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
8818 out->pm_qos_mixer_path);
8819 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308820 out->config = pcm_config_low_latency;
8821 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
8822 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
8823 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05308824 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
8825 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
8826 if (out->config.period_size <= 0) {
8827 ALOGE("Invalid configuration period size is not valid");
8828 ret = -EINVAL;
8829 goto error_open;
8830 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008831 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
8832 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
8833 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008834 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
8835 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
8836 out->config = pcm_config_haptics_audio;
8837 if (force_haptic_path)
8838 adev->haptics_config = pcm_config_haptics_audio;
8839 else
8840 adev->haptics_config = pcm_config_haptics;
8841
Meng Wangd08ce322020-04-02 08:59:20 +08008842 channels =
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008843 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
8844
8845 if (force_haptic_path) {
8846 out->config.channels = 1;
8847 adev->haptics_config.channels = 1;
8848 } else
8849 adev->haptics_config.channels = audio_channel_count_from_out_mask(out->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008850 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008851 ret = audio_extn_auto_hal_open_output_stream(out);
8852 if (ret) {
8853 ALOGE("%s: Failed to open output stream for bus device", __func__);
8854 ret = -EINVAL;
8855 goto error_open;
8856 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308857 } else {
8858 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008859 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8860 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308861 }
8862 out->hal_ip_format = format = out->format;
8863 out->config.format = hal_format_to_pcm(out->hal_ip_format);
8864 out->hal_op_format = pcm_format_to_hal(out->config.format);
8865 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
8866 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008867 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05308868 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308869 if (out->hal_ip_format != out->hal_op_format) {
8870 uint32_t buffer_size = out->config.period_size *
8871 format_to_bitwidth_table[out->hal_op_format] *
8872 out->config.channels;
8873 out->convert_buffer = calloc(1, buffer_size);
8874 if (out->convert_buffer == NULL){
8875 ALOGE("Allocation failed for convert buffer for size %d",
8876 out->compr_config.fragment_size);
8877 ret = -ENOMEM;
8878 goto error_open;
8879 }
8880 ALOGD("Convert buffer allocated of size %d", buffer_size);
8881 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008882 }
8883
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008884 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
8885 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308886
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008887 /* TODO remove this hardcoding and check why width is zero*/
8888 if (out->bit_width == 0)
8889 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308890 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008891 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008892 &out->device_list, out->flags,
8893 out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05308894 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05308895 &out->app_type_cfg);
Kogara Naveen Kumar65828fe2022-10-14 16:41:04 +05308896 if (((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
8897 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) && (!compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS))) {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08008898 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008899 if(adev->primary_output == NULL)
8900 adev->primary_output = out;
8901 else {
8902 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008903 ret = -EEXIST;
8904 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008905 }
8906 }
8907
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008908 /* Check if this usecase is already existing */
8909 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07008910 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
8911 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008912 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008913 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008914 ret = -EEXIST;
8915 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008916 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008917
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008918 pthread_mutex_unlock(&adev->lock);
8919
8920 out->stream.common.get_sample_rate = out_get_sample_rate;
8921 out->stream.common.set_sample_rate = out_set_sample_rate;
8922 out->stream.common.get_buffer_size = out_get_buffer_size;
8923 out->stream.common.get_channels = out_get_channels;
8924 out->stream.common.get_format = out_get_format;
8925 out->stream.common.set_format = out_set_format;
8926 out->stream.common.standby = out_standby;
8927 out->stream.common.dump = out_dump;
8928 out->stream.common.set_parameters = out_set_parameters;
8929 out->stream.common.get_parameters = out_get_parameters;
8930 out->stream.common.add_audio_effect = out_add_audio_effect;
8931 out->stream.common.remove_audio_effect = out_remove_audio_effect;
8932 out->stream.get_latency = out_get_latency;
8933 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08008934#ifdef NO_AUDIO_OUT
8935 out->stream.write = out_write_for_no_output;
8936#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008937 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08008938#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008939 out->stream.get_render_position = out_get_render_position;
8940 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008941 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008942
Haynes Mathew George16081042017-05-31 17:16:49 -07008943 if (out->realtime)
8944 out->af_period_multiplier = af_period_multiplier;
8945 else
8946 out->af_period_multiplier = 1;
8947
Andy Hunga1f48fa2019-07-01 18:14:53 -07008948 out->kernel_buffer_size = out->config.period_size * out->config.period_count;
8949
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008950 out->standby = 1;
Zhou Songbaddf9f2020-11-20 13:57:39 +08008951 out->volume_l = PLAYBACK_GAIN_MAX;
8952 out->volume_r = PLAYBACK_GAIN_MAX;
Eric Laurenta9024de2013-04-04 09:19:12 -07008953 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008954 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008955
8956 config->format = out->stream.common.get_format(&out->stream.common);
8957 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
8958 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308959 register_format(out->format, out->supported_formats);
8960 register_channel_mask(out->channel_mask, out->supported_channel_masks);
8961 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008962
Dechen Chai22768452021-07-30 09:29:16 +05308963#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -08008964 out->error_log = error_log_create(
8965 ERROR_LOG_ENTRIES,
8966 1000000000 /* aggregate consecutive identical errors within one second in ns */);
Dechen Chai22768452021-07-30 09:29:16 +05308967#endif
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308968 /*
8969 By locking output stream before registering, we allow the callback
8970 to update stream's state only after stream's initial state is set to
8971 adev state.
8972 */
8973 lock_output_stream(out);
8974 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
8975 pthread_mutex_lock(&adev->lock);
8976 out->card_status = adev->card_status;
8977 pthread_mutex_unlock(&adev->lock);
8978 pthread_mutex_unlock(&out->lock);
8979
Aalique Grahame22e49102018-12-18 14:23:57 -08008980 stream_app_type_cfg_init(&out->app_type_cfg);
8981
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008982 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308983 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07008984 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008985
8986 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
8987 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
8988 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008989 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05308990 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008991 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07008992 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05308993 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
8994 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008995 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
8996 out->usecase, PCM_PLAYBACK);
8997 hdlr_stream_cfg.flags = out->flags;
8998 hdlr_stream_cfg.type = PCM_PLAYBACK;
8999 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
9000 &hdlr_stream_cfg);
9001 if (ret) {
9002 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
9003 out->adsp_hdlr_stream_handle = NULL;
9004 }
9005 }
Gangadhar Sb0210342019-02-22 17:39:41 +05309006 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
9007 is_direct_passthough, false);
9008 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
9009 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07009010 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07009011 if (ret < 0) {
9012 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
9013 out->ip_hdlr_handle = NULL;
9014 }
9015 }
Derek Chenf939fb72018-11-13 13:34:41 -08009016
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009017 ret = io_streams_map_insert(adev, &out->stream.common,
9018 out->handle, AUDIO_PATCH_HANDLE_NONE);
9019 if (ret != 0)
9020 goto error_open;
9021
Susan Wang6dd13092021-01-25 10:27:11 -05009022 out->out_ctxt.output = out;
Derek Chenf939fb72018-11-13 13:34:41 -08009023
9024 pthread_mutex_lock(&adev->lock);
Susan Wang6dd13092021-01-25 10:27:11 -05009025 list_add_tail(&adev->active_outputs_list, &out->out_ctxt.list);
Derek Chenf939fb72018-11-13 13:34:41 -08009026 pthread_mutex_unlock(&adev->lock);
9027
Eric Laurent994a6932013-07-17 11:51:42 -07009028 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009029 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07009030
9031error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05309032 if (out->convert_buffer)
9033 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07009034 free(out);
9035 *stream_out = NULL;
9036 ALOGD("%s: exit: ret %d", __func__, ret);
9037 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009038}
9039
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309040void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009041 struct audio_stream_out *stream)
9042{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07009043 struct stream_out *out = (struct stream_out *)stream;
9044 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009045 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07009046
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009047 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309048
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009049 io_streams_map_remove(adev, out->handle);
9050
Susan Wang6dd13092021-01-25 10:27:11 -05009051 // remove out_ctxt early to prevent the stream
9052 // being opened in a race condition
9053 pthread_mutex_lock(&adev->lock);
9054 list_remove(&out->out_ctxt.list);
9055 pthread_mutex_unlock(&adev->lock);
9056
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309057 // must deregister from sndmonitor first to prevent races
9058 // between the callback and close_stream
9059 audio_extn_snd_mon_unregister_listener(out);
9060
Ben Rombergerd771a7c2017-02-22 18:05:17 -08009061 /* close adsp hdrl session before standby */
9062 if (out->adsp_hdlr_stream_handle) {
9063 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
9064 if (ret)
9065 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
9066 out->adsp_hdlr_stream_handle = NULL;
9067 }
9068
Manish Dewangan21a850a2017-08-14 12:03:55 +05309069 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07009070 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
9071 out->ip_hdlr_handle = NULL;
9072 }
9073
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009074 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309075 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009076 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05309077 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309078 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009079 if(ret != 0)
9080 ALOGE("%s: Compress voip output cannot be closed, error:%d",
9081 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009082 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009083 out_standby(&stream->common);
9084
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07009085 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08009086 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07009087 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07009088 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07009089 if (out->compr_config.codec != NULL)
9090 free(out->compr_config.codec);
9091 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009092
Zhou Songbaddf9f2020-11-20 13:57:39 +08009093 out->a2dp_muted = false;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05309094
Varun Balaraje49253e2017-07-06 19:48:56 +05309095 if (is_interactive_usecase(out->usecase))
9096 free_interactive_usecase(adev, out->usecase);
9097
Ashish Jain83a6cc22016-06-28 14:34:17 +05309098 if (out->convert_buffer != NULL) {
9099 free(out->convert_buffer);
9100 out->convert_buffer = NULL;
9101 }
9102
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009103 if (adev->voice_tx_output == out)
9104 adev->voice_tx_output = NULL;
9105
Dechen Chai22768452021-07-30 09:29:16 +05309106#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -08009107 error_log_destroy(out->error_log);
9108 out->error_log = NULL;
Dechen Chai22768452021-07-30 09:29:16 +05309109#endif
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05309110 if (adev->primary_output == out)
9111 adev->primary_output = NULL;
9112
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07009113 pthread_cond_destroy(&out->cond);
9114 pthread_mutex_destroy(&out->lock);
Weiyin Jiang280ea742020-09-08 20:28:22 +08009115 pthread_mutex_destroy(&out->pre_lock);
9116 pthread_mutex_destroy(&out->latch_lock);
9117 pthread_mutex_destroy(&out->position_query_lock);
Derek Chenf939fb72018-11-13 13:34:41 -08009118
9119 pthread_mutex_lock(&adev->lock);
Zhenlin Lian4f947842022-05-14 15:50:52 +05309120 clear_devices(&out->device_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009121 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08009122 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07009123 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009124}
9125
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05009126void in_set_power_policy(uint8_t enable)
9127{
9128 struct listnode *node;
9129
9130 ALOGD("%s: Enter, state %d", __func__, enable);
9131
9132 pthread_mutex_lock(&adev->lock);
9133 adev->in_power_policy = enable ? POWER_POLICY_STATUS_ONLINE : POWER_POLICY_STATUS_OFFLINE;
9134 pthread_mutex_unlock(&adev->lock);
9135
9136 if (!enable) {
9137 list_for_each(node, &adev->active_inputs_list) {
9138 streams_input_ctxt_t *in_ctxt = node_to_item(node,
9139 streams_input_ctxt_t,
9140 list);
9141 struct stream_in *in = in_ctxt->input;
9142 in_standby(&in->stream.common);
9143 }
9144 }
9145
9146 ALOGD("%s: Exit", __func__);
9147}
9148
9149void out_set_power_policy(uint8_t enable)
9150{
9151 struct listnode *node;
9152
9153 ALOGD("%s: Enter, state %d", __func__, enable);
9154
9155 pthread_mutex_lock(&adev->lock);
E V Ravi317be872022-02-23 19:08:15 +05309156 adev->out_power_policy = enable ? POWER_POLICY_STATUS_ONLINE : POWER_POLICY_STATUS_OFFLINE;
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05009157 pthread_mutex_unlock(&adev->lock);
9158
9159 if (!enable) {
9160 list_for_each(node, &adev->active_outputs_list) {
9161 streams_output_ctxt_t *out_ctxt = node_to_item(node,
9162 streams_output_ctxt_t,
9163 list);
9164 struct stream_out *out = out_ctxt->output;
9165 out_on_error(&out->stream.common);
9166 }
9167 }
9168
9169 ALOGD("%s: Exit", __func__);
9170}
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009171static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
9172{
9173 struct audio_device *adev = (struct audio_device *)dev;
9174 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009175 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07009176 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009177 int ret;
9178 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08009179 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08009180 struct listnode *node;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07009181 int controller = -1, stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009182
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009183 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009184 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009185
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05309186 if (!parms)
9187 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05309188
Derek Chen6f293672019-04-01 01:40:24 -07009189 /* notify adev and input/output streams on the snd card status */
9190 adev_snd_mon_cb((void *)adev, parms);
9191
Weiyin Jiang24f55292020-12-22 14:35:46 +08009192 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
9193 if (ret >= 0) {
9194 list_for_each(node, &adev->active_outputs_list) {
9195 streams_output_ctxt_t *out_ctxt = node_to_item(node,
9196 streams_output_ctxt_t,
9197 list);
9198 out_snd_mon_cb((void *)out_ctxt->output, parms);
9199 }
Derek Chen6f293672019-04-01 01:40:24 -07009200
Weiyin Jiang24f55292020-12-22 14:35:46 +08009201 list_for_each(node, &adev->active_inputs_list) {
9202 streams_input_ctxt_t *in_ctxt = node_to_item(node,
9203 streams_input_ctxt_t,
9204 list);
9205 in_snd_mon_cb((void *)in_ctxt->input, parms);
9206 }
Derek Chen6f293672019-04-01 01:40:24 -07009207 }
9208
Zhou Songd6d71752019-05-21 18:08:51 +08009209 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05309210 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
9211 if (ret >= 0) {
9212 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08009213 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05309214 adev->bt_sco_on = true;
Shalini Manjunatha3a2e06e2021-02-01 12:23:49 +05309215 /*
9216 * When ever BT_SCO=ON arrives, make sure to route
9217 * all use cases to SCO device, otherwise due to delay in
9218 * BT_SCO=ON and lack of synchronization with create audio patch
9219 * request for SCO device, some times use case not routed properly to
9220 * SCO device
9221 */
9222 struct audio_usecase *usecase;
9223 struct listnode *node;
9224 list_for_each(node, &adev->usecase_list) {
9225 usecase = node_to_item(node, struct audio_usecase, list);
Anver sadhiquef0efca32021-09-03 15:25:44 +05309226 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
Anver sadhique93f3c912021-08-11 11:19:45 +05309227 (!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 +05309228 ALOGD("BT_SCO ON, switch all in use case to it");
9229 select_devices(adev, usecase->id);
9230 }
Mingshu Pangef517202021-04-22 10:35:00 +08009231 if (usecase->stream.out && (usecase->type == PCM_PLAYBACK ||
9232 usecase->type == VOICE_CALL) &&
Anver sadhique93f3c912021-08-11 11:19:45 +05309233 (!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 +05309234 ALOGD("BT_SCO ON, switch all out use case to it");
9235 select_devices(adev, usecase->id);
9236 }
9237 }
9238 }
9239 else {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05309240 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08009241 audio_extn_sco_reset_configuration();
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08009242 }
9243 }
9244
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009245 status = voice_set_parameters(adev, parms);
9246 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08009247 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009248
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009249 status = platform_set_parameters(adev->platform, parms);
9250 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08009251 goto done;
9252
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009253 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
9254 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07009255 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009256 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
9257 adev->bluetooth_nrec = true;
9258 else
9259 adev->bluetooth_nrec = false;
9260 }
9261
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009262 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
9263 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009264 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
9265 adev->screen_off = false;
9266 else
9267 adev->screen_off = true;
Quinn Male70f20f32019-06-26 16:50:26 -07009268 audio_extn_sound_trigger_update_screen_status(adev->screen_off);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009269 }
9270
Eric Laurent4b084132018-10-19 17:33:43 -07009271 ret = str_parms_get_int(parms, "rotation", &val);
9272 if (ret >= 0) {
9273 bool reverse_speakers = false;
9274 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
9275 switch (val) {
9276 // FIXME: note that the code below assumes that the speakers are in the correct placement
9277 // relative to the user when the device is rotated 90deg from its default rotation. This
9278 // assumption is device-specific, not platform-specific like this code.
9279 case 270:
9280 reverse_speakers = true;
9281 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
9282 break;
9283 case 0:
9284 case 180:
9285 camera_rotation = CAMERA_ROTATION_PORTRAIT;
9286 break;
9287 case 90:
9288 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
9289 break;
9290 default:
9291 ALOGE("%s: unexpected rotation of %d", __func__, val);
9292 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07009293 }
Eric Laurent4b084132018-10-19 17:33:43 -07009294 if (status == 0) {
9295 // check and set swap
9296 // - check if orientation changed and speaker active
9297 // - set rotation and cache the rotation value
9298 adev->camera_orientation =
9299 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
9300 if (!audio_extn_is_maxx_audio_enabled())
9301 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
9302 }
9303 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07009304
Mingming Yin514a8bc2014-07-29 15:22:21 -07009305 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
9306 if (ret >= 0) {
9307 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
9308 adev->bt_wb_speech_enabled = true;
9309 else
9310 adev->bt_wb_speech_enabled = false;
9311 }
9312
Zhou Song12c29502019-03-16 10:37:18 +08009313 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
9314 if (ret >= 0) {
9315 val = atoi(value);
9316 adev->swb_speech_mode = val;
9317 }
9318
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07009319 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
9320 if (ret >= 0) {
9321 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309322 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08009323 if (audio_is_output_device(val) &&
9324 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07009325 ALOGV("cache new ext disp type and edid");
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07009326 platform_get_controller_stream_from_params(parms, &controller, &stream);
9327 platform_set_ext_display_device_v2(adev->platform, controller, stream);
9328 ret = platform_get_ext_disp_type_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07009329 if (ret < 0) {
9330 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05309331 } else {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07009332 platform_cache_edid_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07009333 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309334 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07009335 /*
9336 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
9337 * Per AudioPolicyManager, USB device is higher priority than WFD.
9338 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
9339 * If WFD use case occupies AFE proxy, it may result unintended behavior while
9340 * starting voice call on USB
9341 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08009342 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309343 if (ret >= 0)
9344 audio_extn_usb_add_device(device, atoi(value));
9345
Zhou Song6f862822017-11-06 17:27:57 +08009346 if (!audio_extn_usb_is_tunnel_supported()) {
9347 ALOGV("detected USB connect .. disable proxy");
9348 adev->allow_afe_proxy_usage = false;
9349 }
Zhou Song503196b2021-07-23 17:31:05 +08009350 } else if (audio_is_hearing_aid_out_device(device) &&
9351 property_get_bool("persist.vendor.audio.ha_proxy.enabled", false)) {
9352 adev->ha_proxy_enable = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07009353 }
9354 }
9355
9356 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
9357 if (ret >= 0) {
9358 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309359 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07009360 /*
9361 * The HDMI / Displayport disconnect handling has been moved to
9362 * audio extension to ensure that its parameters are not
9363 * invalidated prior to updating sysfs of the disconnect event
9364 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
9365 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309366 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08009367 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309368 if (ret >= 0)
9369 audio_extn_usb_remove_device(device, atoi(value));
9370
Zhou Song6f862822017-11-06 17:27:57 +08009371 if (!audio_extn_usb_is_tunnel_supported()) {
9372 ALOGV("detected USB disconnect .. enable proxy");
9373 adev->allow_afe_proxy_usage = true;
9374 }
Zhou Song503196b2021-07-23 17:31:05 +08009375 } else if (audio_is_hearing_aid_out_device(device)) {
9376 adev->ha_proxy_enable = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07009377 }
9378 }
9379
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009380 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08009381
9382 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08009383 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309384 struct audio_usecase *usecase;
9385 struct listnode *node;
9386 list_for_each(node, &adev->usecase_list) {
9387 usecase = node_to_item(node, struct audio_usecase, list);
Weiyin Jiangff56ff32020-05-08 14:32:21 +08009388 if ((usecase->stream.out == NULL) || (usecase->type != PCM_PLAYBACK))
9389 continue;
9390
9391 if (is_a2dp_out_device_type(&usecase->device_list)) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309392 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05309393 audio_extn_a2dp_set_handoff_mode(true);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05309394 ALOGD("Switching to speaker and muting the stream before select_devices");
9395 check_a2dp_restore_l(adev, usecase->stream.out, false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309396 //force device switch to re configure encoder
9397 select_devices(adev, usecase->id);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05309398 ALOGD("Unmuting the stream after select_devices");
Zhou Songbaddf9f2020-11-20 13:57:39 +08009399 check_a2dp_restore_l(adev, usecase->stream.out, true);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05309400 audio_extn_a2dp_set_handoff_mode(false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309401 break;
Zhou Songd01e7a22020-09-23 22:49:01 +08009402 } else if (is_offload_usecase(usecase->stream.out->usecase)) {
Weiyin Jiang280ea742020-09-08 20:28:22 +08009403 pthread_mutex_lock(&usecase->stream.out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +08009404 if (usecase->stream.out->a2dp_muted) {
Weiyin Jiang280ea742020-09-08 20:28:22 +08009405 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
9406 reassign_device_list(&usecase->stream.out->device_list,
9407 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, "");
9408 check_a2dp_restore_l(adev, usecase->stream.out, true);
9409 break;
9410 }
9411 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309412 }
9413 }
9414 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009415
9416 //handle vr audio setparam
9417 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9418 value, sizeof(value));
9419 if (ret >= 0) {
9420 ALOGI("Setting vr mode to be %s", value);
9421 if (!strncmp(value, "true", 4)) {
9422 adev->vr_audio_mode_enabled = true;
9423 ALOGI("Setting vr mode to true");
9424 } else if (!strncmp(value, "false", 5)) {
9425 adev->vr_audio_mode_enabled = false;
9426 ALOGI("Setting vr mode to false");
9427 } else {
9428 ALOGI("wrong vr mode set");
9429 }
9430 }
9431
Eric Laurent4b084132018-10-19 17:33:43 -07009432 //FIXME: to be replaced by proper video capture properties API
9433 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
9434 if (ret >= 0) {
9435 int camera_facing = CAMERA_FACING_BACK;
9436 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
9437 camera_facing = CAMERA_FACING_FRONT;
9438 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
9439 camera_facing = CAMERA_FACING_BACK;
9440 else {
9441 ALOGW("%s: invalid camera facing value: %s", __func__, value);
9442 goto done;
9443 }
9444 adev->camera_orientation =
9445 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
9446 struct audio_usecase *usecase;
9447 struct listnode *node;
9448 list_for_each(node, &adev->usecase_list) {
9449 usecase = node_to_item(node, struct audio_usecase, list);
9450 struct stream_in *in = usecase->stream.in;
9451 if (usecase->type == PCM_CAPTURE && in != NULL &&
9452 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
9453 select_devices(adev, in->usecase);
9454 }
9455 }
9456 }
9457
Tahir Dawson7fabad42022-06-21 12:37:55 -04009458 audio_extn_auto_hal_set_parameters(adev, parms);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05309459 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08009460done:
9461 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009462 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05309463error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009464 ALOGV("%s: exit with code(%d)", __func__, status);
9465 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009466}
9467
9468static char* adev_get_parameters(const struct audio_hw_device *dev,
9469 const char *keys)
9470{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05309471 ALOGD("%s:%s", __func__, keys);
9472
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009473 struct audio_device *adev = (struct audio_device *)dev;
9474 struct str_parms *reply = str_parms_create();
9475 struct str_parms *query = str_parms_create_str(keys);
9476 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05309477 char value[256] = {0};
9478 int ret = 0;
9479
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009480 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08009481 if (reply) {
9482 str_parms_destroy(reply);
9483 }
9484 if (query) {
9485 str_parms_destroy(query);
9486 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009487 ALOGE("adev_get_parameters: failed to create query or reply");
9488 return NULL;
9489 }
9490
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009491 //handle vr audio getparam
9492
9493 ret = str_parms_get_str(query,
9494 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9495 value, sizeof(value));
9496
9497 if (ret >= 0) {
9498 bool vr_audio_enabled = false;
9499 pthread_mutex_lock(&adev->lock);
9500 vr_audio_enabled = adev->vr_audio_mode_enabled;
9501 pthread_mutex_unlock(&adev->lock);
9502
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07009503 ALOGV("getting vr mode to %d", vr_audio_enabled);
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009504
9505 if (vr_audio_enabled) {
9506 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9507 "true");
9508 goto exit;
9509 } else {
9510 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9511 "false");
9512 goto exit;
9513 }
9514 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009515
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009516 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009517 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08009518 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08009519 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009520 platform_get_parameters(adev->platform, query, reply);
justinwengd5395152019-11-04 12:23:09 +08009521 audio_extn_ma_get_parameters(adev, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05309522 pthread_mutex_unlock(&adev->lock);
9523
Naresh Tannirud7205b62014-06-20 02:54:48 +05309524exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009525 str = str_parms_to_str(reply);
9526 str_parms_destroy(query);
9527 str_parms_destroy(reply);
9528
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07009529 ALOGV("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009530 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009531}
9532
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009533static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009534{
9535 return 0;
9536}
9537
9538static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
9539{
Haynes Mathew George5191a852013-09-11 14:19:36 -07009540 int ret;
9541 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08009542
9543 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
9544
Haynes Mathew George5191a852013-09-11 14:19:36 -07009545 pthread_mutex_lock(&adev->lock);
9546 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07009547 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07009548 pthread_mutex_unlock(&adev->lock);
9549 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009550}
9551
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009552static int adev_set_master_volume(struct audio_hw_device *dev __unused,
9553 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009554{
9555 return -ENOSYS;
9556}
9557
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009558static int adev_get_master_volume(struct audio_hw_device *dev __unused,
9559 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009560{
9561 return -ENOSYS;
9562}
9563
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009564static int adev_set_master_mute(struct audio_hw_device *dev __unused,
9565 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009566{
9567 return -ENOSYS;
9568}
9569
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009570static int adev_get_master_mute(struct audio_hw_device *dev __unused,
9571 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009572{
9573 return -ENOSYS;
9574}
9575
9576static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
9577{
9578 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07009579 struct listnode *node;
9580 struct audio_usecase *usecase = NULL;
9581 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08009582
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009583 pthread_mutex_lock(&adev->lock);
9584 if (adev->mode != mode) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309585 ALOGD("%s: mode %d , prev_mode %d \n", __func__, mode , adev->mode);
9586 adev->prev_mode = adev->mode; /* prev_mode is kept to handle voip concurrency*/
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009587 adev->mode = mode;
Weiyin Jiang96b96f72020-09-22 16:48:19 +08009588 if (mode == AUDIO_MODE_CALL_SCREEN) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309589 adev->current_call_output = adev->primary_output;
9590 voice_start_call(adev);
9591 } else if (voice_is_in_call_or_call_screen(adev) &&
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08009592 (mode == AUDIO_MODE_NORMAL ||
9593 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07009594 list_for_each(node, &adev->usecase_list) {
9595 usecase = node_to_item(node, struct audio_usecase, list);
9596 if (usecase->type == VOICE_CALL)
9597 break;
9598 }
9599 if (usecase &&
9600 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
9601 ret = audio_extn_usb_check_and_set_svc_int(usecase,
9602 true);
9603 if (ret != 0) {
9604 /* default service interval was successfully updated,
9605 reopen USB backend with new service interval */
9606 check_usecases_codec_backend(adev,
9607 usecase,
9608 usecase->out_snd_device);
9609 }
9610 }
9611
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009612 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07009613 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009614 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08009615 // restore device for other active usecases after stop call
9616 list_for_each(node, &adev->usecase_list) {
9617 usecase = node_to_item(node, struct audio_usecase, list);
9618 select_devices(adev, usecase->id);
9619 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009620 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009621 }
9622 pthread_mutex_unlock(&adev->lock);
9623 return 0;
9624}
9625
9626static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
9627{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009628 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08009629 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009630
9631 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08009632 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009633 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009634
Derek Chend2530072014-11-24 12:39:14 -08009635 if (adev->ext_hw_plugin)
9636 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009637
9638 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009639 pthread_mutex_unlock(&adev->lock);
9640
9641 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009642}
9643
9644static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
9645{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009646 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009647 return 0;
9648}
9649
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009650static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009651 const struct audio_config *config)
9652{
Avinash Chandrad7296d42021-08-04 15:07:47 +05309653 bool is_usb_hifi = IS_USB_HIFI;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009654 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009655
Aalique Grahame22e49102018-12-18 14:23:57 -08009656 /* Don't know if USB HIFI in this context so use true to be conservative */
9657 if (check_input_parameters(config->sample_rate, config->format, channel_count,
Avinash Chandrad7296d42021-08-04 15:07:47 +05309658 is_usb_hifi) != 0)
Aalique Grahame22e49102018-12-18 14:23:57 -08009659 return 0;
9660
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009661 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
9662 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009663}
9664
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009665static bool adev_input_allow_hifi_record(struct audio_device *adev,
9666 audio_devices_t devices,
9667 audio_input_flags_t flags,
9668 audio_source_t source) {
9669 const bool allowed = true;
9670
9671 if (!audio_is_usb_in_device(devices))
9672 return !allowed;
9673
9674 switch (flags) {
9675 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009676 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07009677 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
9678 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009679 default:
9680 return !allowed;
9681 }
9682
9683 switch (source) {
9684 case AUDIO_SOURCE_DEFAULT:
9685 case AUDIO_SOURCE_MIC:
9686 case AUDIO_SOURCE_UNPROCESSED:
9687 break;
9688 default:
9689 return !allowed;
9690 }
9691
9692 switch (adev->mode) {
9693 case 0:
9694 break;
9695 default:
9696 return !allowed;
9697 }
9698
9699 return allowed;
9700}
9701
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009702static int adev_update_voice_comm_input_stream(struct stream_in *in,
9703 struct audio_config *config)
9704{
9705 bool valid_rate = (config->sample_rate == 8000 ||
9706 config->sample_rate == 16000 ||
9707 config->sample_rate == 32000 ||
9708 config->sample_rate == 48000);
9709 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
9710
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009711 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08009712 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009713 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9714 in->config = default_pcm_config_voip_copp;
9715 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
9716 DEFAULT_VOIP_BUF_DURATION_MS,
9717 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009718 } else {
9719 ALOGW("%s No valid input in voip, use defaults"
9720 "sample rate %u, channel mask 0x%X",
9721 __func__, config->sample_rate, in->channel_mask);
9722 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009723 in->config.rate = config->sample_rate;
9724 in->sample_rate = config->sample_rate;
9725 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009726 //XXX needed for voice_extn_compress_voip_open_input_stream
9727 in->config.rate = config->sample_rate;
9728 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
Shalini Manjunathaa763cc42019-08-23 15:13:46 +05309729 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009730 voice_extn_compress_voip_is_active(in->dev)) &&
9731 (voice_extn_compress_voip_is_format_supported(in->format)) &&
9732 valid_rate && valid_ch) {
9733 voice_extn_compress_voip_open_input_stream(in);
9734 // update rate entries to match config from AF
9735 in->config.rate = config->sample_rate;
9736 in->sample_rate = config->sample_rate;
9737 } else {
9738 ALOGW("%s compress voip not active, use defaults", __func__);
9739 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009740 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009741 return 0;
9742}
9743
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009744static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07009745 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009746 audio_devices_t devices,
9747 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009748 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309749 audio_input_flags_t flags,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009750 const char *address,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009751 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009752{
9753 struct audio_device *adev = (struct audio_device *)dev;
9754 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009755 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009756 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009757 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05309758 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009759 bool is_usb_dev = audio_is_usb_in_device(devices);
9760 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
9761 devices,
9762 flags,
9763 source);
Andy Hung94320602018-10-29 18:31:12 -07009764 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
9765 " sample_rate %u, channel_mask %#x, format %#x",
9766 __func__, flags, is_usb_dev, may_use_hifi_record,
9767 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309768
kunleizdff872d2018-08-20 14:40:33 +08009769 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08009770 is_usb_dev = false;
9771 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
9772 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
9773 __func__, devices);
9774 }
9775
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009776 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009777
9778 if (!(is_usb_dev && may_use_hifi_record)) {
9779 if (config->sample_rate == 0)
9780 config->sample_rate = 48000;
9781 if (config->channel_mask == AUDIO_CHANNEL_NONE)
9782 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9783 if (config->format == AUDIO_FORMAT_DEFAULT)
9784 config->format = AUDIO_FORMAT_PCM_16_BIT;
9785
9786 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
9787
Aalique Grahame22e49102018-12-18 14:23:57 -08009788 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9789 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009790 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05309791 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009792
9793 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009794
9795 if (!in) {
9796 ALOGE("failed to allocate input stream");
9797 return -ENOMEM;
9798 }
9799
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309800 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05309801 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
9802 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009803 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07009804 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009805
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009806 in->stream.common.get_sample_rate = in_get_sample_rate;
9807 in->stream.common.set_sample_rate = in_set_sample_rate;
9808 in->stream.common.get_buffer_size = in_get_buffer_size;
9809 in->stream.common.get_channels = in_get_channels;
9810 in->stream.common.get_format = in_get_format;
9811 in->stream.common.set_format = in_set_format;
9812 in->stream.common.standby = in_standby;
9813 in->stream.common.dump = in_dump;
9814 in->stream.common.set_parameters = in_set_parameters;
9815 in->stream.common.get_parameters = in_get_parameters;
9816 in->stream.common.add_audio_effect = in_add_audio_effect;
9817 in->stream.common.remove_audio_effect = in_remove_audio_effect;
9818 in->stream.set_gain = in_set_gain;
9819 in->stream.read = in_read;
9820 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08009821 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309822 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07009823 in->stream.set_microphone_direction = in_set_microphone_direction;
9824 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07009825 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009826
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009827 list_init(&in->device_list);
9828 update_device_list(&in->device_list, devices, address, true);
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009829 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009830 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009831 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009832 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009833 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07009834 in->bit_width = 16;
9835 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07009836 in->direction = MIC_DIRECTION_UNSPECIFIED;
9837 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08009838 list_init(&in->aec_list);
9839 list_init(&in->ns_list);
Phil Burkd898ba62019-06-20 12:49:01 -07009840 in->mmap_shared_memory_fd = -1; // not open
Haynes Mathew George46740472017-10-27 18:40:12 -07009841
Andy Hung94320602018-10-29 18:31:12 -07009842 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08009843 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
9844 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
9845 /* Force channel config requested to mono if incall
9846 record is being requested for only uplink/downlink */
9847 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
9848 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9849 ret = -EINVAL;
9850 goto err_open;
9851 }
9852 }
9853
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009854 if (is_usb_dev && may_use_hifi_record) {
9855 /* HiFi record selects an appropriate format, channel, rate combo
9856 depending on sink capabilities*/
9857 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
9858 &config->format,
9859 &in->supported_formats[0],
9860 MAX_SUPPORTED_FORMATS,
9861 &config->channel_mask,
9862 &in->supported_channel_masks[0],
9863 MAX_SUPPORTED_CHANNEL_MASKS,
9864 &config->sample_rate,
9865 &in->supported_sample_rates[0],
9866 MAX_SUPPORTED_SAMPLE_RATES);
9867 if (ret != 0) {
9868 ret = -EINVAL;
9869 goto err_open;
9870 }
9871 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009872 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309873 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05309874 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
9875 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
9876 in->config.format = PCM_FORMAT_S32_LE;
9877 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309878 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
9879 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
9880 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
9881 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
9882 bool ret_error = false;
9883 in->bit_width = 24;
9884 /* 24 bit is restricted to UNPROCESSED source only,also format supported
9885 from HAL is 24_packed and 8_24
9886 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
9887 24_packed return error indicating supported format is 24_packed
9888 *> In case of any other source requesting 24 bit or float return error
9889 indicating format supported is 16 bit only.
9890
9891 on error flinger will retry with supported format passed
9892 */
9893 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
9894 (source != AUDIO_SOURCE_CAMCORDER)) {
9895 config->format = AUDIO_FORMAT_PCM_16_BIT;
9896 if (config->sample_rate > 48000)
9897 config->sample_rate = 48000;
9898 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07009899 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
9900 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309901 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
9902 ret_error = true;
9903 }
9904
9905 if (ret_error) {
9906 ret = -EINVAL;
9907 goto err_open;
9908 }
9909 }
9910
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009911 in->channel_mask = config->channel_mask;
9912 in->format = config->format;
9913
9914 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309915
Huicheng Liu1404ba12020-09-11 01:03:25 -04009916 /* validate bus device address */
9917 if (compare_device_type(&in->device_list, AUDIO_DEVICE_IN_BUS)) {
9918 /* extract car audio stream index */
9919 in->car_audio_stream =
9920 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
9921 if (in->car_audio_stream < 0) {
9922 ALOGE("%s: invalid car audio stream %x",
9923 __func__, in->car_audio_stream);
9924 ret = -EINVAL;
9925 goto err_open;
9926 }
9927 ALOGV("%s: car_audio_stream 0x%x", __func__, in->car_audio_stream);
Huicheng Liuea4fd422021-01-12 18:34:50 -05009928 ret = audio_extn_auto_hal_open_input_stream(in);
9929 if (ret) {
9930 ALOGE("%s: Failed to open input stream for bus device", __func__);
9931 ret = -EINVAL;
9932 goto err_open;
9933 }
Huicheng Liu1404ba12020-09-11 01:03:25 -04009934 }
9935
Susan Wange3959562021-03-11 11:50:26 -05009936 /* reassign use case for echo reference stream on automotive platforms */
9937 if (in->source == AUDIO_SOURCE_ECHO_REFERENCE) {
9938 ret = audio_extn_auto_hal_open_echo_reference_stream(in);
9939 }
9940
Kogara Naveen Kumar379ff692022-01-31 11:56:51 +05309941 if ((in->source == AUDIO_SOURCE_FM_TUNER) || (devices == AUDIO_DEVICE_IN_FM_TUNER)) {
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309942 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
9943 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
9944 else {
9945 ret = -EINVAL;
9946 goto err_open;
9947 }
9948 }
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +05309949#ifdef PLATFORM_AUTO
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +05309950 if ((config->sample_rate == 48000 ||
9951 config->sample_rate == 32000 ||
9952 config->sample_rate == 24000 ||
9953 config->sample_rate == 16000 ||
9954 config->sample_rate == 8000)&&
Deeraj Somanfa377bf2019-02-06 12:57:59 +05309955 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
9956 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +05309957 (flags & AUDIO_INPUT_FLAG_FAST) != 0)
9958#else
9959 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
9960 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
9961 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
9962 (flags & AUDIO_INPUT_FLAG_FAST) != 0)
9963#endif
9964{
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009965 is_low_latency = true;
9966#if LOW_LATENCY_CAPTURE_USE_CASE
Revathi Uddarajud9f23d92020-07-27 10:55:06 +05309967 if ((flags & AUDIO_INPUT_FLAG_VOIP_TX) != 0)
9968 in->usecase = USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY;
9969 else
9970 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009971#endif
9972 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08009973 if (!in->realtime) {
9974 in->config = pcm_config_audio_capture;
9975 frame_size = audio_stream_in_frame_size(&in->stream);
9976 buffer_size = get_input_buffer_size(config->sample_rate,
9977 config->format,
9978 channel_count,
9979 is_low_latency);
9980 in->config.period_size = buffer_size / frame_size;
9981 in->config.rate = config->sample_rate;
9982 in->af_period_multiplier = 1;
9983 } else {
9984 // period size is left untouched for rt mode playback
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +05309985#ifdef PLATFORM_AUTO
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +05309986 switch(config->sample_rate)
9987 {
9988 case 48000:
9989 in->config = pcm_config_audio_capture_rt_48KHz;
9990 break;
9991 case 32000:
9992 in->config = pcm_config_audio_capture_rt_32KHz;
9993 break;
9994 case 24000:
9995 in->config = pcm_config_audio_capture_rt_24KHz;
9996 break;
9997 case 16000:
9998 in->config = pcm_config_audio_capture_rt_16KHz;
9999 break;
10000 case 8000:
10001 in->config = pcm_config_audio_capture_rt_8KHz;
10002 break;
10003 default:
10004 in->config = pcm_config_audio_capture_rt_48KHz;
10005 }
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +053010006#else
10007 in->config = pcm_config_audio_capture_rt_48KHz;
10008#endif
Aalique Grahame22e49102018-12-18 14:23:57 -080010009 in->af_period_multiplier = af_period_multiplier;
10010 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -070010011 }
10012
Susan Wangb803cb52021-10-14 12:03:36 -040010013 /* Additional sample rates added below must also be present
10014 in audio_policy_configuration.xml for mmap_no_irq_in */
10015 bool valid_mmap_record_rate = (config->sample_rate == 8000 ||
10016 config->sample_rate == 16000 ||
Susan Wang89da9042021-10-14 12:03:36 -040010017 config->sample_rate == 24000 ||
Susan Wangb803cb52021-10-14 12:03:36 -040010018 config->sample_rate == 32000 ||
10019 config->sample_rate == 48000);
10020 if (valid_mmap_record_rate &&
10021 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -070010022 in->realtime = 0;
10023 in->usecase = USECASE_AUDIO_RECORD_MMAP;
10024 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -070010025 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -070010026 in->stream.start = in_start;
10027 in->stream.stop = in_stop;
10028 in->stream.create_mmap_buffer = in_create_mmap_buffer;
10029 in->stream.get_mmap_position = in_get_mmap_position;
Ramjee Singhbcb3b6c2021-11-17 13:19:16 +053010030 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -070010031 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
Haynes Mathew George46740472017-10-27 18:40:12 -070010032 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -070010033 in->usecase = USECASE_AUDIO_RECORD_HIFI;
10034 in->config = pcm_config_audio_capture;
10035 frame_size = audio_stream_in_frame_size(&in->stream);
10036 buffer_size = get_input_buffer_size(config->sample_rate,
10037 config->format,
10038 channel_count,
10039 false /*is_low_latency*/);
10040 in->config.period_size = buffer_size / frame_size;
10041 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -070010042 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -070010043 switch (config->format) {
10044 case AUDIO_FORMAT_PCM_32_BIT:
10045 in->bit_width = 32;
10046 break;
10047 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
10048 case AUDIO_FORMAT_PCM_8_24_BIT:
10049 in->bit_width = 24;
10050 break;
10051 default:
10052 in->bit_width = 16;
10053 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010054 } else if (is_single_device_type_equal(&in->device_list,
10055 AUDIO_DEVICE_IN_TELEPHONY_RX) ||
10056 is_single_device_type_equal(&in->device_list,
10057 AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070010058 if (config->sample_rate == 0)
10059 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
10060 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
10061 config->sample_rate != 8000) {
10062 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
10063 ret = -EINVAL;
10064 goto err_open;
10065 }
10066 if (config->format == AUDIO_FORMAT_DEFAULT)
10067 config->format = AUDIO_FORMAT_PCM_16_BIT;
10068 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
10069 config->format = AUDIO_FORMAT_PCM_16_BIT;
10070 ret = -EINVAL;
10071 goto err_open;
10072 }
10073
10074 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
Zhou Song62ea0282020-03-22 19:53:01 +080010075 if (adev->ha_proxy_enable &&
10076 is_single_device_type_equal(&in->device_list,
10077 AUDIO_DEVICE_IN_TELEPHONY_RX))
10078 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY2;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070010079 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070010080 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -080010081 in->af_period_multiplier = 1;
10082 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
Shalini Manjunathaac412b32020-01-03 15:00:14 +053010083 (!voice_extn_is_compress_voip_supported()) &&
Aalique Grahame22e49102018-12-18 14:23:57 -080010084 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
10085 (config->sample_rate == 8000 ||
10086 config->sample_rate == 16000 ||
10087 config->sample_rate == 32000 ||
10088 config->sample_rate == 48000) &&
10089 channel_count == 1) {
10090 in->usecase = USECASE_AUDIO_RECORD_VOIP;
10091 in->config = pcm_config_audio_capture;
10092 frame_size = audio_stream_in_frame_size(&in->stream);
10093 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
10094 config->sample_rate,
10095 config->format,
10096 channel_count, false /*is_low_latency*/);
10097 in->config.period_size = buffer_size / frame_size;
10098 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
10099 in->config.rate = config->sample_rate;
10100 in->af_period_multiplier = 1;
Mingshu Pangc2d65042021-01-14 16:19:10 +080010101 } else if (in->realtime) {
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +053010102#ifdef PLATFORM_AUTO
Kogara Naveen Kumara688a812022-04-27 16:45:59 +053010103 switch(config->sample_rate)
10104 {
10105 case 48000:
10106 in->config = pcm_config_audio_capture_rt_48KHz;
10107 break;
10108 case 32000:
10109 in->config = pcm_config_audio_capture_rt_32KHz;
10110 break;
10111 case 24000:
10112 in->config = pcm_config_audio_capture_rt_24KHz;
10113 break;
10114 case 16000:
10115 in->config = pcm_config_audio_capture_rt_16KHz;
10116 break;
10117 case 8000:
10118 in->config = pcm_config_audio_capture_rt_8KHz;
10119 break;
10120 default:
10121 in->config = pcm_config_audio_capture_rt_48KHz;
10122 }
Mingshu Pangc2d65042021-01-14 16:19:10 +080010123 in->config.format = pcm_format_from_audio_format(config->format);
10124 in->af_period_multiplier = af_period_multiplier;
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +053010125#else
10126 in->config = pcm_config_audio_capture_rt_48KHz;
10127#endif
10128} else {
Revathi Uddarajud2634032017-12-07 14:42:34 +053010129 int ret_val;
10130 pthread_mutex_lock(&adev->lock);
10131 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
10132 in, config, &channel_mask_updated);
10133 pthread_mutex_unlock(&adev->lock);
10134
10135 if (!ret_val) {
10136 if (channel_mask_updated == true) {
10137 ALOGD("%s: return error to retry with updated channel mask (%#x)",
10138 __func__, config->channel_mask);
10139 ret = -EINVAL;
10140 goto err_open;
10141 }
10142 ALOGD("%s: created multi-channel session succesfully",__func__);
10143 } else if (audio_extn_compr_cap_enabled() &&
10144 audio_extn_compr_cap_format_supported(config->format) &&
10145 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
10146 audio_extn_compr_cap_init(in);
10147 } else if (audio_extn_cin_applicable_stream(in)) {
Deeraj Soman14230922019-01-30 16:39:30 +053010148 ret = audio_extn_cin_configure_input_stream(in, config);
Revathi Uddarajud2634032017-12-07 14:42:34 +053010149 if (ret)
10150 goto err_open;
10151 } else {
10152 in->config = pcm_config_audio_capture;
10153 in->config.rate = config->sample_rate;
10154 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +053010155 in->format = config->format;
10156 frame_size = audio_stream_in_frame_size(&in->stream);
10157 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -070010158 config->format,
10159 channel_count,
10160 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +020010161 /* prevent division-by-zero */
10162 if (frame_size == 0) {
10163 ALOGE("%s: Error frame_size==0", __func__);
10164 ret = -EINVAL;
10165 goto err_open;
10166 }
10167
Revathi Uddarajud2634032017-12-07 14:42:34 +053010168 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -080010169 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -080010170
Revathi Uddarajud2634032017-12-07 14:42:34 +053010171 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
10172 /* optionally use VOIP usecase depending on config(s) */
10173 ret = adev_update_voice_comm_input_stream(in, config);
10174 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -080010175
Revathi Uddarajud2634032017-12-07 14:42:34 +053010176 if (ret) {
10177 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
10178 goto err_open;
10179 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -080010180 }
Jaideep Sharmad305a4a2020-02-27 14:29:04 +053010181
10182 /* assign concurrent capture usecase if record has to caried out from
10183 * actual hardware input source */
10184 if (audio_extn_is_concurrent_capture_enabled() &&
10185 !audio_is_virtual_input_source(in->source)) {
Samyak Jainc37062f2019-04-25 18:41:06 +053010186 /* Acquire lock to avoid two concurrent use cases initialized to
10187 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +080010188
Samyak Jainc37062f2019-04-25 18:41:06 +053010189 if (in->usecase == USECASE_AUDIO_RECORD) {
10190 pthread_mutex_lock(&adev->lock);
10191 if (!(adev->pcm_record_uc_state)) {
10192 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
10193 adev->pcm_record_uc_state = 1;
10194 pthread_mutex_unlock(&adev->lock);
Krishna Kishor Jha0f4d8482022-02-18 10:56:05 +053010195 } else if (audio_extn_is_concurrent_pcm_record_enabled()) {
10196 in->usecase = get_record_usecase(adev);
10197 pthread_mutex_unlock(&adev->lock);
Samyak Jainc37062f2019-04-25 18:41:06 +053010198 } else {
10199 pthread_mutex_unlock(&adev->lock);
10200 /* Assign compress record use case for second record */
10201 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
10202 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
10203 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
10204 if (audio_extn_cin_applicable_stream(in)) {
10205 in->sample_rate = config->sample_rate;
Deeraj Soman14230922019-01-30 16:39:30 +053010206 ret = audio_extn_cin_configure_input_stream(in, config);
Samyak Jainc37062f2019-04-25 18:41:06 +053010207 if (ret)
10208 goto err_open;
10209 }
10210 }
10211 }
kunleiz28c73e72019-03-27 17:24:04 +080010212 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -070010213 }
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +053010214
Ramjee Singh82fd0c12019-08-21 16:31:33 +053010215 if (audio_extn_ssr_get_stream() != in)
10216 in->config.channels = channel_count;
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -070010217
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -070010218 in->sample_rate = in->config.rate;
10219
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010220 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
10221 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010222 &in->device_list, flags, in->format,
Haynes Mathew George4ffef292017-11-21 15:08:02 -080010223 in->sample_rate, in->bit_width,
10224 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +053010225 register_format(in->format, in->supported_formats);
10226 register_channel_mask(in->channel_mask, in->supported_channel_masks);
10227 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010228
Dechen Chai22768452021-07-30 09:29:16 +053010229#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -080010230 in->error_log = error_log_create(
10231 ERROR_LOG_ENTRIES,
10232 1000000000 /* aggregate consecutive identical errors within one second */);
Dechen Chai22768452021-07-30 09:29:16 +053010233#endif
Aalique Grahame22e49102018-12-18 14:23:57 -080010234
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010235 /* This stream could be for sound trigger lab,
10236 get sound trigger pcm if present */
10237 audio_extn_sound_trigger_check_and_get_session(in);
10238
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010239 lock_input_stream(in);
10240 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
10241 pthread_mutex_lock(&adev->lock);
10242 in->card_status = adev->card_status;
10243 pthread_mutex_unlock(&adev->lock);
10244 pthread_mutex_unlock(&in->lock);
10245
Aalique Grahame22e49102018-12-18 14:23:57 -080010246 stream_app_type_cfg_init(&in->app_type_cfg);
10247
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010248 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -080010249
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010250 ret = io_streams_map_insert(adev, &in->stream.common,
10251 handle, AUDIO_PATCH_HANDLE_NONE);
10252 if (ret != 0)
10253 goto err_open;
10254
Susan Wang6dd13092021-01-25 10:27:11 -050010255 in->in_ctxt.input = in;
Derek Chenf939fb72018-11-13 13:34:41 -080010256
10257 pthread_mutex_lock(&adev->lock);
Susan Wang6dd13092021-01-25 10:27:11 -050010258 list_add_tail(&adev->active_inputs_list, &in->in_ctxt.list);
Derek Chenf939fb72018-11-13 13:34:41 -080010259 pthread_mutex_unlock(&adev->lock);
10260
Eric Laurent994a6932013-07-17 11:51:42 -070010261 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -080010262 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010263
10264err_open:
Krishna Kishor Jha0f4d8482022-02-18 10:56:05 +053010265 if (audio_extn_is_concurrent_pcm_record_enabled() && is_pcm_record_usecase(in->usecase)) {
10266 free_record_usecase(adev, in->usecase);
10267 } else if (in->usecase == USECASE_AUDIO_RECORD) {
Samyak Jainc37062f2019-04-25 18:41:06 +053010268 pthread_mutex_lock(&adev->lock);
10269 adev->pcm_record_uc_state = 0;
10270 pthread_mutex_unlock(&adev->lock);
10271 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010272 free(in);
10273 *stream_in = NULL;
10274 return ret;
10275}
10276
10277static void adev_close_input_stream(struct audio_hw_device *dev,
10278 struct audio_stream_in *stream)
10279{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080010280 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -070010281 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -070010282 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +053010283
Sidipotu Ashokf43018c2014-05-02 16:21:50 +053010284 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080010285
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010286 if (in == NULL) {
10287 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
10288 return;
10289 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010290 io_streams_map_remove(adev, in->capture_handle);
10291
Susan Wang6dd13092021-01-25 10:27:11 -050010292 // remove out_ctxt early to prevent the stream
10293 // being opened in a race condition
10294 pthread_mutex_lock(&adev->lock);
10295 list_remove(&in->in_ctxt.list);
10296 pthread_mutex_unlock(&adev->lock);
10297
kunleiz70e57612018-12-28 17:50:23 +080010298 /* must deregister from sndmonitor first to prevent races
10299 * between the callback and close_stream
10300 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010301 audio_extn_snd_mon_unregister_listener(stream);
10302
kunleiz70e57612018-12-28 17:50:23 +080010303 /* Disable echo reference if there are no active input, hfp call
10304 * and sound trigger while closing input stream
10305 */
Eric Laurent637e2d42018-11-15 12:24:31 -080010306 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +080010307 !audio_extn_hfp_is_active(adev) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010308 !audio_extn_sound_trigger_check_ec_ref_enable()) {
10309 struct listnode out_devices;
10310 list_init(&out_devices);
10311 platform_set_echo_reference(adev, false, &out_devices);
Zhenlin Lian4f947842022-05-14 15:50:52 +053010312 clear_devices(&out_devices);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010313 } else
kunleiz70e57612018-12-28 17:50:23 +080010314 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +053010315
Dechen Chai22768452021-07-30 09:29:16 +053010316#ifndef LINUX_ENABLED
Weiyin Jiang2995f662019-04-17 14:25:12 +080010317 error_log_destroy(in->error_log);
10318 in->error_log = NULL;
Dechen Chai22768452021-07-30 09:29:16 +053010319#endif
Pallavid7c7a272018-01-16 11:22:55 +053010320
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080010321 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +053010322 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080010323 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +053010324 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080010325 if (ret != 0)
10326 ALOGE("%s: Compress voip input cannot be closed, error:%d",
10327 __func__, ret);
10328 } else
10329 in_standby(&stream->common);
10330
Weiyin Jiang280ea742020-09-08 20:28:22 +080010331 pthread_mutex_destroy(&in->lock);
10332 pthread_mutex_destroy(&in->pre_lock);
10333
Revathi Uddarajud2634032017-12-07 14:42:34 +053010334 pthread_mutex_lock(&adev->lock);
Krishna Kishor Jha0f4d8482022-02-18 10:56:05 +053010335 if (audio_extn_is_concurrent_pcm_record_enabled() && is_pcm_record_usecase(in->usecase)) {
10336 free_record_usecase(adev, in->usecase);
10337 } else if (in->usecase == USECASE_AUDIO_RECORD) {
Samyak Jain15fda662018-12-18 16:40:52 +053010338 adev->pcm_record_uc_state = 0;
10339 }
10340
Kunlei Zhang5d5d8d92020-02-26 15:00:59 +080010341 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
10342 adev->enable_voicerx = false;
10343 }
10344
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -070010345 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -070010346 audio_extn_ssr_deinit();
10347 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010348
Garmond Leunge2433c32017-09-28 21:51:22 -070010349 if (audio_extn_ffv_get_stream() == in) {
10350 audio_extn_ffv_stream_deinit();
10351 }
10352
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010353 if (audio_extn_compr_cap_enabled() &&
Subhadra Jagadeesan63a1e832023-01-13 11:26:38 +053010354 audio_extn_compr_cap_format_supported(pcm_format_to_audio_format((in->config).format)))
Mingming Yine62d7842013-10-25 16:26:03 -070010355 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +053010356
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +053010357 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +053010358 audio_extn_cin_free_input_stream_resources(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010359
Mingming Yinfd7607b2016-01-22 12:48:44 -080010360 if (in->is_st_session) {
10361 ALOGV("%s: sound trigger pcm stop lab", __func__);
10362 audio_extn_sound_trigger_stop_lab(in);
10363 }
Zhenlin Lian4f947842022-05-14 15:50:52 +053010364 clear_devices(&in->device_list);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010365 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +053010366 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010367 return;
10368}
10369
Aalique Grahame22e49102018-12-18 14:23:57 -080010370/* verifies input and output devices and their capabilities.
10371 *
10372 * This verification is required when enabling extended bit-depth or
10373 * sampling rates, as not all qcom products support it.
10374 *
10375 * Suitable for calling only on initialization such as adev_open().
10376 * It fills the audio_device use_case_table[] array.
10377 *
10378 * Has a side-effect that it needs to configure audio routing / devices
10379 * in order to power up the devices and read the device parameters.
10380 * It does not acquire any hw device lock. Should restore the devices
10381 * back to "normal state" upon completion.
10382 */
10383static int adev_verify_devices(struct audio_device *adev)
10384{
10385 /* enumeration is a bit difficult because one really wants to pull
10386 * the use_case, device id, etc from the hidden pcm_device_table[].
10387 * In this case there are the following use cases and device ids.
10388 *
10389 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
10390 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
10391 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
10392 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
10393 * [USECASE_AUDIO_RECORD] = {0, 0},
10394 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
10395 * [USECASE_VOICE_CALL] = {2, 2},
10396 *
10397 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
10398 * USECASE_VOICE_CALL omitted, but possible for either input or output.
10399 */
10400
10401 /* should be the usecases enabled in adev_open_input_stream() */
10402 static const int test_in_usecases[] = {
10403 USECASE_AUDIO_RECORD,
10404 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
10405 };
10406 /* should be the usecases enabled in adev_open_output_stream()*/
10407 static const int test_out_usecases[] = {
10408 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
10409 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
10410 };
10411 static const usecase_type_t usecase_type_by_dir[] = {
10412 PCM_PLAYBACK,
10413 PCM_CAPTURE,
10414 };
10415 static const unsigned flags_by_dir[] = {
10416 PCM_OUT,
10417 PCM_IN,
10418 };
10419
10420 size_t i;
10421 unsigned dir;
10422 const unsigned card_id = adev->snd_card;
10423
10424 for (dir = 0; dir < 2; ++dir) {
10425 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
10426 const unsigned flags_dir = flags_by_dir[dir];
10427 const size_t testsize =
10428 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
10429 const int *testcases =
10430 dir ? test_in_usecases : test_out_usecases;
10431 const audio_devices_t audio_device =
10432 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
10433
10434 for (i = 0; i < testsize; ++i) {
10435 const audio_usecase_t audio_usecase = testcases[i];
10436 int device_id;
10437 struct pcm_params **pparams;
10438 struct stream_out out;
10439 struct stream_in in;
10440 struct audio_usecase uc_info;
10441 int retval;
10442
10443 pparams = &adev->use_case_table[audio_usecase];
10444 pcm_params_free(*pparams); /* can accept null input */
10445 *pparams = NULL;
10446
10447 /* find the device ID for the use case (signed, for error) */
10448 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
10449 if (device_id < 0)
10450 continue;
10451
10452 /* prepare structures for device probing */
10453 memset(&uc_info, 0, sizeof(uc_info));
10454 uc_info.id = audio_usecase;
10455 uc_info.type = usecase_type;
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010456 list_init(&uc_info.device_list);
Aalique Grahame22e49102018-12-18 14:23:57 -080010457 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -080010458 memset(&in, 0, sizeof(in));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010459 list_init(&in.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010460 update_device_list(&in.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -080010461 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
10462 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -080010463 }
10464 memset(&out, 0, sizeof(out));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010465 list_init(&out.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010466 update_device_list(&out.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -080010467 uc_info.stream.out = &out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010468 update_device_list(&uc_info.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -080010469 uc_info.in_snd_device = SND_DEVICE_NONE;
10470 uc_info.out_snd_device = SND_DEVICE_NONE;
10471 list_add_tail(&adev->usecase_list, &uc_info.list);
10472
10473 /* select device - similar to start_(in/out)put_stream() */
10474 retval = select_devices(adev, audio_usecase);
10475 if (retval >= 0) {
10476 *pparams = pcm_params_get(card_id, device_id, flags_dir);
10477#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -070010478 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -080010479 if (*pparams) {
10480 ALOGV("%s: (%s) card %d device %d", __func__,
10481 dir ? "input" : "output", card_id, device_id);
10482 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
10483 } else {
10484 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
10485 }
10486#endif
10487 }
10488
10489 /* deselect device - similar to stop_(in/out)put_stream() */
10490 /* 1. Get and set stream specific mixer controls */
10491 retval = disable_audio_route(adev, &uc_info);
10492 /* 2. Disable the rx device */
10493 retval = disable_snd_device(adev,
10494 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
10495 list_remove(&uc_info.list);
10496 }
10497 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010498 return 0;
10499}
10500
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010501int update_patch(unsigned int num_sources,
10502 const struct audio_port_config *sources,
10503 unsigned int num_sinks,
10504 const struct audio_port_config *sinks,
10505 audio_patch_handle_t handle,
10506 struct audio_patch_info *p_info,
10507 patch_type_t patch_type, bool new_patch)
10508{
Aniket Kumar Latad13758f2020-08-06 15:11:36 -070010509 ALOGV("%s: enter", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010510
10511 if (p_info == NULL) {
10512 ALOGE("%s: Invalid patch pointer", __func__);
10513 return -EINVAL;
10514 }
10515
10516 if (new_patch) {
10517 p_info->patch = (struct audio_patch *) calloc(1, sizeof(struct audio_patch));
10518 if (p_info->patch == NULL) {
10519 ALOGE("%s: Could not allocate patch", __func__);
10520 return -ENOMEM;
10521 }
10522 }
10523
10524 p_info->patch->id = handle;
10525 p_info->patch->num_sources = num_sources;
10526 p_info->patch->num_sinks = num_sinks;
10527
10528 for (int i = 0; i < num_sources; i++)
10529 p_info->patch->sources[i] = sources[i];
10530 for (int i = 0; i < num_sinks; i++)
10531 p_info->patch->sinks[i] = sinks[i];
10532
10533 p_info->patch_type = patch_type;
10534 return 0;
10535}
10536
10537audio_patch_handle_t generate_patch_handle()
10538{
10539 static audio_patch_handle_t patch_handle = AUDIO_PATCH_HANDLE_NONE;
10540 if (++patch_handle < 0)
10541 patch_handle = AUDIO_PATCH_HANDLE_NONE + 1;
10542 return patch_handle;
10543}
10544
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010545int adev_create_audio_patch(struct audio_hw_device *dev,
10546 unsigned int num_sources,
10547 const struct audio_port_config *sources,
10548 unsigned int num_sinks,
10549 const struct audio_port_config *sinks,
10550 audio_patch_handle_t *handle)
10551{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010552 int ret = 0;
10553 struct audio_device *adev = (struct audio_device *)dev;
10554 struct audio_patch_info *p_info = NULL;
10555 patch_type_t patch_type = PATCH_NONE;
10556 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10557 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
10558 struct audio_stream_info *s_info = NULL;
10559 struct audio_stream *stream = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010560 struct listnode devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010561 audio_devices_t device_type = AUDIO_DEVICE_NONE;
10562 bool new_patch = false;
10563 char addr[AUDIO_DEVICE_MAX_ADDRESS_LEN];
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010564
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010565 ALOGD("%s: enter: num sources %d, num_sinks %d, handle %d", __func__,
10566 num_sources, num_sinks, *handle);
10567
10568 if (num_sources == 0 || num_sources > AUDIO_PATCH_PORTS_MAX ||
10569 num_sinks == 0 || num_sinks > AUDIO_PATCH_PORTS_MAX) {
10570 ALOGE("%s: Invalid patch arguments", __func__);
10571 ret = -EINVAL;
10572 goto done;
10573 }
10574
10575 if (num_sources > 1) {
10576 ALOGE("%s: Multiple sources are not supported", __func__);
10577 ret = -EINVAL;
10578 goto done;
10579 }
10580
10581 if (sources == NULL || sinks == NULL) {
10582 ALOGE("%s: Invalid sources or sinks port config", __func__);
10583 ret = -EINVAL;
10584 goto done;
10585 }
10586
10587 ALOGV("%s: source role %d, source type %d", __func__,
10588 sources[0].type, sources[0].role);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010589 list_init(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010590
10591 // Populate source/sink information and fetch stream info
10592 switch (sources[0].type) {
10593 case AUDIO_PORT_TYPE_DEVICE: // Patch for audio capture or loopback
10594 device_type = sources[0].ext.device.type;
10595 strlcpy(&addr[0], &sources[0].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010596 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010597 if (sinks[0].type == AUDIO_PORT_TYPE_MIX) {
10598 patch_type = PATCH_CAPTURE;
10599 io_handle = sinks[0].ext.mix.handle;
10600 input_source = sinks[0].ext.mix.usecase.source;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010601 ALOGD("%s: Capture patch from device %x to mix %d",
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010602 __func__, device_type, io_handle);
10603 } else {
10604 // Device to device patch is not implemented.
10605 // This space will need changes if audio HAL
10606 // handles device to device patches in the future.
10607 patch_type = PATCH_DEVICE_LOOPBACK;
10608 }
10609 break;
10610 case AUDIO_PORT_TYPE_MIX: // Patch for audio playback
10611 io_handle = sources[0].ext.mix.handle;
10612 for (int i = 0; i < num_sinks; i++) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010613 device_type = sinks[i].ext.device.type;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010614 strlcpy(&addr[0], &sinks[i].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010615 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010616 }
10617 patch_type = PATCH_PLAYBACK;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010618 ALOGD("%s: Playback patch from mix handle %d to device %x",
10619 __func__, io_handle, get_device_types(&devices));
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010620 break;
10621 case AUDIO_PORT_TYPE_SESSION:
10622 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010623 ALOGE("%s: Unsupported source type %d", __func__, sources[0].type);
10624 ret = -EINVAL;
10625 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010626 }
10627
10628 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010629
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010630 // Generate patch info and update patch
10631 if (*handle == AUDIO_PATCH_HANDLE_NONE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010632 *handle = generate_patch_handle();
10633 p_info = (struct audio_patch_info *)
10634 calloc(1, sizeof(struct audio_patch_info));
10635 if (p_info == NULL) {
10636 ALOGE("%s: Failed to allocate memory", __func__);
10637 pthread_mutex_unlock(&adev->lock);
10638 ret = -ENOMEM;
10639 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010640 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010641 new_patch = true;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010642 } else {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010643 p_info = fetch_patch_info_l(adev, *handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010644 if (p_info == NULL) {
10645 ALOGE("%s: Unable to fetch patch for received patch handle %d",
10646 __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010647 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010648 ret = -EINVAL;
10649 goto done;
10650 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010651 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010652 update_patch(num_sources, sources, num_sinks, sinks,
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010653 *handle, p_info, patch_type, new_patch);
10654
10655 // Fetch stream info of associated mix for playback or capture patches
10656 if (p_info->patch_type == PATCH_PLAYBACK ||
10657 p_info->patch_type == PATCH_CAPTURE) {
10658 s_info = hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10659 if (s_info == NULL) {
10660 ALOGE("%s: Failed to obtain stream info", __func__);
10661 if (new_patch)
10662 free(p_info);
10663 pthread_mutex_unlock(&adev->lock);
10664 ret = -EINVAL;
10665 goto done;
10666 }
10667 ALOGV("%s: Fetched stream info with io_handle %d", __func__, io_handle);
10668 s_info->patch_handle = *handle;
10669 stream = s_info->stream;
10670 }
10671 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010672
10673 // Update routing for stream
10674 if (stream != NULL) {
Revathi Uddaraju4255a632021-12-02 05:11:13 -080010675 if (p_info->patch_type == PATCH_PLAYBACK) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010676 ret = route_output_stream((struct stream_out *) stream, &devices);
Revathi Uddaraju4255a632021-12-02 05:11:13 -080010677 } else if (p_info->patch_type == PATCH_CAPTURE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010678 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Revathi Uddaraju4255a632021-12-02 05:11:13 -080010679 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010680 if (ret < 0) {
10681 pthread_mutex_lock(&adev->lock);
10682 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10683 if (new_patch)
10684 free(p_info);
10685 pthread_mutex_unlock(&adev->lock);
10686 ALOGE("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10687 goto done;
10688 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010689 }
10690
10691 // Add new patch to patch map
10692 if (!ret && new_patch) {
10693 pthread_mutex_lock(&adev->lock);
10694 hashmapPut(adev->patch_map, (void *) (intptr_t) *handle, (void *) p_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010695 ALOGD("%s: Added a new patch with handle %d", __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010696 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010697 }
10698
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010699done:
Zhenlin Lian4f947842022-05-14 15:50:52 +053010700 clear_devices(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010701 audio_extn_hw_loopback_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010702 num_sources,
10703 sources,
10704 num_sinks,
10705 sinks,
10706 handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010707 audio_extn_auto_hal_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010708 num_sources,
10709 sources,
10710 num_sinks,
10711 sinks,
10712 handle);
10713 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010714}
10715
10716int adev_release_audio_patch(struct audio_hw_device *dev,
10717 audio_patch_handle_t handle)
10718{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010719 struct audio_device *adev = (struct audio_device *) dev;
10720 int ret = 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010721 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010722 struct audio_stream *stream = NULL;
Derek Chenf939fb72018-11-13 13:34:41 -080010723
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010724 if (handle == AUDIO_PATCH_HANDLE_NONE) {
10725 ALOGE("%s: Invalid patch handle %d", __func__, handle);
10726 ret = -EINVAL;
10727 goto done;
10728 }
10729
10730 ALOGD("%s: Remove patch with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010731 pthread_mutex_lock(&adev->lock);
10732 struct audio_patch_info *p_info = fetch_patch_info_l(adev, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010733 if (p_info == NULL) {
10734 ALOGE("%s: Patch info not found with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010735 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010736 ret = -EINVAL;
10737 goto done;
10738 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010739 struct audio_patch *patch = p_info->patch;
10740 if (patch == NULL) {
10741 ALOGE("%s: Patch not found for handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010742 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010743 ret = -EINVAL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010744 goto done;
10745 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010746 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10747 switch (patch->sources[0].type) {
10748 case AUDIO_PORT_TYPE_MIX:
10749 io_handle = patch->sources[0].ext.mix.handle;
10750 break;
10751 case AUDIO_PORT_TYPE_DEVICE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010752 if (p_info->patch_type == PATCH_CAPTURE)
10753 io_handle = patch->sinks[0].ext.mix.handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010754 break;
10755 case AUDIO_PORT_TYPE_SESSION:
10756 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010757 pthread_mutex_unlock(&adev->lock);
10758 ret = -EINVAL;
10759 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010760 }
10761
10762 // Remove patch and reset patch handle in stream info
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010763 patch_type_t patch_type = p_info->patch_type;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010764 patch_map_remove_l(adev, handle);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010765 if (patch_type == PATCH_PLAYBACK ||
10766 patch_type == PATCH_CAPTURE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010767 struct audio_stream_info *s_info =
10768 hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10769 if (s_info == NULL) {
10770 ALOGE("%s: stream for io_handle %d is not available", __func__, io_handle);
10771 pthread_mutex_unlock(&adev->lock);
10772 goto done;
10773 }
10774 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10775 stream = s_info->stream;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010776 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010777 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010778
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010779 if (stream != NULL) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010780 struct listnode devices;
10781 list_init(&devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010782 if (patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010783 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010784 else if (patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010785 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Zhenlin Lian4f947842022-05-14 15:50:52 +053010786 clear_devices(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010787 }
10788
10789 if (ret < 0)
10790 ALOGW("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10791
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010792done:
10793 audio_extn_hw_loopback_release_audio_patch(dev, handle);
10794 audio_extn_auto_hal_release_audio_patch(dev, handle);
10795
10796 ALOGV("%s: Successfully released patch %d", __func__, handle);
Derek Chenf939fb72018-11-13 13:34:41 -080010797 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010798}
10799
10800int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
10801{
Derek Chenf13dd492018-11-13 14:53:51 -080010802 int ret = 0;
10803
10804 ret = audio_extn_hw_loopback_get_audio_port(dev, config);
10805 ret |= audio_extn_auto_hal_get_audio_port(dev, config);
10806 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010807}
10808
10809int adev_set_audio_port_config(struct audio_hw_device *dev,
10810 const struct audio_port_config *config)
10811{
Derek Chenf13dd492018-11-13 14:53:51 -080010812 int ret = 0;
10813
10814 ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
10815 ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
10816 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010817}
10818
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -070010819static int adev_dump(const audio_hw_device_t *device __unused,
10820 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010821{
10822 return 0;
10823}
10824
10825static int adev_close(hw_device_t *device)
10826{
Aalique Grahame22e49102018-12-18 14:23:57 -080010827 size_t i;
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010828 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -070010829
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010830 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -070010831 return 0;
10832
10833 pthread_mutex_lock(&adev_init_lock);
10834
10835 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +053010836 if (audio_extn_spkr_prot_is_enabled())
10837 audio_extn_spkr_prot_deinit();
Jaideep Sharmaa2b49672019-09-10 20:37:03 +053010838 audio_extn_battery_properties_listener_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010839 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010840 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -080010841 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010842 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -080010843 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010844 audio_extn_utils_release_streams_cfg_lists(
10845 &adev->streams_output_cfg_list,
10846 &adev->streams_input_cfg_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010847 if (audio_extn_qap_is_enabled())
10848 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010849 if (audio_extn_qaf_is_enabled())
10850 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -070010851 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +080010852 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -070010853 free(adev->snd_dev_ref_cnt);
10854 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010855 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
10856 pcm_params_free(adev->use_case_table[i]);
10857 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010858 if (adev->adm_deinit)
10859 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010860 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010861 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010862 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010863 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010864 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010865 if (adev->device_cfg_params) {
10866 free(adev->device_cfg_params);
10867 adev->device_cfg_params = NULL;
10868 }
Derek Chend2530072014-11-24 12:39:14 -080010869 if(adev->ext_hw_plugin)
10870 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -080010871 audio_extn_auto_hal_deinit();
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010872 free_map(adev->patch_map);
10873 free_map(adev->io_streams_map);
Kiran Kandi910e1862013-10-29 13:29:42 -070010874 free(device);
10875 adev = NULL;
10876 }
10877 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +053010878 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010879 return 0;
10880}
10881
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010882/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
10883 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
10884 * just that it _might_ work.
10885 */
10886static int period_size_is_plausible_for_low_latency(int period_size)
10887{
10888 switch (period_size) {
10889 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -070010890 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010891 case 240:
10892 case 320:
10893 case 480:
10894 return 1;
10895 default:
10896 return 0;
10897 }
10898}
10899
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010900static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
10901{
10902 bool is_snd_card_status = false;
10903 bool is_ext_device_status = false;
10904 char value[32];
10905 int card = -1;
10906 card_status_t status;
10907
10908 if (cookie != adev || !parms)
10909 return;
10910
10911 if (!parse_snd_card_status(parms, &card, &status)) {
10912 is_snd_card_status = true;
10913 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
10914 is_ext_device_status = true;
10915 } else {
10916 // not a valid event
10917 return;
10918 }
10919
10920 pthread_mutex_lock(&adev->lock);
10921 if (card == adev->snd_card || is_ext_device_status) {
10922 if (is_snd_card_status && adev->card_status != status) {
Jaideep Sharmacb402512020-09-24 17:51:07 +053010923 ALOGD("%s card_status %d", __func__, status);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010924 adev->card_status = status;
10925 platform_snd_card_update(adev->platform, status);
10926 audio_extn_fm_set_parameters(adev, parms);
Derek Chend6f371d2019-03-01 13:45:58 -080010927 audio_extn_auto_hal_set_parameters(adev, parms);
Zhou Song4f43e352019-07-02 00:32:23 +080010928 if (status == CARD_STATUS_OFFLINE)
10929 audio_extn_sco_reset_configuration();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010930 } else if (is_ext_device_status) {
10931 platform_set_parameters(adev->platform, parms);
10932 }
10933 }
10934 pthread_mutex_unlock(&adev->lock);
10935 return;
10936}
10937
Weiyin Jiang280ea742020-09-08 20:28:22 +080010938/* adev lock held */
10939int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010940{
10941 struct audio_usecase *uc_info;
Zhou Song407e5aa2020-12-27 19:13:04 +080010942 struct audio_usecase *usecase;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010943 struct listnode devices;
Zhou Song407e5aa2020-12-27 19:13:04 +080010944 struct listnode *node;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010945
10946 uc_info = get_usecase_from_list(adev, out->usecase);
10947 if (uc_info == NULL) {
10948 ALOGE("%s: Could not find the usecase (%d) in the list",
10949 __func__, out->usecase);
10950 return -EINVAL;
10951 }
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010952 list_init(&devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010953
Zhou Songbaddf9f2020-11-20 13:57:39 +080010954 ALOGD("%s: enter: usecase(%d: %s), a2dp muted %d", __func__,
10955 out->usecase, use_case_table[out->usecase], out->a2dp_muted);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010956
10957 if (restore) {
Weiyin Jiang280ea742020-09-08 20:28:22 +080010958 pthread_mutex_lock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010959 // restore A2DP device for active usecases and unmute if required
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010960 if (is_a2dp_out_device_type(&out->device_list)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010961 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
Zhou Songe5225132019-09-26 15:33:36 +080010962 if (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)
10963 select_devices(adev, uc_info->id);
Zhou Songbaddf9f2020-11-20 13:57:39 +080010964
10965 if (is_offload_usecase(out->usecase)) {
10966 if (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)
Weiyin Jiang280ea742020-09-08 20:28:22 +080010967 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
Zhou Songbaddf9f2020-11-20 13:57:39 +080010968 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
10969 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
10970 } else {
10971 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010972 }
Zhou Songbaddf9f2020-11-20 13:57:39 +080010973 out->a2dp_muted = false;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010974 }
Weiyin Jiang280ea742020-09-08 20:28:22 +080010975 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010976 } else {
Weiyin Jiang280ea742020-09-08 20:28:22 +080010977 pthread_mutex_lock(&out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +080010978 // mute stream and switch to speaker if suspended
10979 if (!out->a2dp_muted && !out->standby) {
Zhou Songbaddf9f2020-11-20 13:57:39 +080010980 assign_devices(&devices, &out->device_list);
10981 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Zhou Song407e5aa2020-12-27 19:13:04 +080010982 list_for_each(node, &adev->usecase_list) {
10983 usecase = node_to_item(node, struct audio_usecase, list);
Zhou Songe63b6fe2021-04-15 13:54:46 +080010984 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
10985 !is_a2dp_out_device_type(&usecase->stream.out->device_list) &&
Zhou Songcf77af02021-05-14 18:21:14 +080010986 !is_sco_out_device_type(&usecase->stream.out->device_list) &&
Zhou Songe63b6fe2021-04-15 13:54:46 +080010987 platform_check_backends_match(SND_DEVICE_OUT_SPEAKER,
10988 usecase->out_snd_device)) {
Zhou Song407e5aa2020-12-27 19:13:04 +080010989 assign_devices(&out->device_list, &usecase->stream.out->device_list);
10990 break;
10991 }
10992 }
Zhou Songcf77af02021-05-14 18:21:14 +080010993 if ((is_a2dp_out_device_type(&devices) && list_length(&devices) == 1) ||
10994 (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)) {
Zhou Song8edbbdb2021-01-14 16:48:03 +080010995 out->a2dp_muted = true;
10996 if (is_offload_usecase(out->usecase)) {
10997 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10998 compress_pause(out->compr);
10999 out_set_compr_volume(&out->stream, (float)0, (float)0);
Zhou Song8edbbdb2021-01-14 16:48:03 +080011000 } else {
Weiyin Jiang906db3c2021-03-02 13:17:04 +080011001 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
11002 out_set_voip_volume(&out->stream, (float)0, (float)0);
11003 else
11004 out_set_pcm_volume(&out->stream, (float)0, (float)0);
11005
Zhou Song8edbbdb2021-01-14 16:48:03 +080011006 /* wait for stale pcm drained before switching to speaker */
11007 uint32_t latency =
11008 (out->config.period_count * out->config.period_size * 1000) /
11009 (out->config.rate);
11010 usleep(latency * 1000);
11011 }
Zhou Songbaddf9f2020-11-20 13:57:39 +080011012 }
11013 select_devices(adev, out->usecase);
Zhou Song8edbbdb2021-01-14 16:48:03 +080011014 ALOGD("%s: switched to device:%s and stream muted:%d", __func__,
11015 platform_get_snd_device_name(uc_info->out_snd_device), out->a2dp_muted);
Zhou Songbaddf9f2020-11-20 13:57:39 +080011016 if (is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011017 if (out->offload_state == OFFLOAD_STATE_PLAYING)
11018 compress_resume(out->compr);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011019 }
Zhou Songbaddf9f2020-11-20 13:57:39 +080011020 assign_devices(&out->device_list, &devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011021 }
Weiyin Jiang280ea742020-09-08 20:28:22 +080011022 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011023 }
Zhenlin Lian4f947842022-05-14 15:50:52 +053011024 clear_devices(&devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011025 ALOGV("%s: exit", __func__);
11026 return 0;
11027}
11028
Haynes Mathew George01156f92018-04-13 15:29:54 -070011029void adev_on_battery_status_changed(bool charging)
11030{
11031 pthread_mutex_lock(&adev->lock);
11032 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
11033 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +080011034 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -070011035 pthread_mutex_unlock(&adev->lock);
11036}
11037
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011038static int adev_open(const hw_module_t *module, const char *name,
11039 hw_device_t **device)
11040{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053011041 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -080011042 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053011043 char mixer_ctl_name[128] = {0};
11044 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053011045
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080011046 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011047 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
11048
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070011049 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -070011050 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070011051 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -070011052 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070011053 ALOGD("%s: returning existing instance of adev", __func__);
11054 ALOGD("%s: exit", __func__);
11055 pthread_mutex_unlock(&adev_init_lock);
11056 return 0;
11057 }
11058
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011059 adev = calloc(1, sizeof(struct audio_device));
11060
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -070011061 if (!adev) {
11062 pthread_mutex_unlock(&adev_init_lock);
11063 return -ENOMEM;
11064 }
11065
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -070011066 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
11067
Weiyin Jiange6ce6312019-01-28 18:28:22 +080011068 // register audio ext hidl at the earliest
11069 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053011070#ifdef DYNAMIC_LOG_ENABLED
11071 register_for_dynamic_logging("hal");
11072#endif
11073
Derek Chenf939fb72018-11-13 13:34:41 -080011074 /* default audio HAL major version */
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011075 uint32_t maj_version = 3;
Derek Chenf939fb72018-11-13 13:34:41 -080011076 if(property_get("vendor.audio.hal.maj.version", value, NULL))
11077 maj_version = atoi(value);
11078
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011079 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -080011080 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011081 adev->device.common.module = (struct hw_module_t *)module;
11082 adev->device.common.close = adev_close;
11083
11084 adev->device.init_check = adev_init_check;
11085 adev->device.set_voice_volume = adev_set_voice_volume;
11086 adev->device.set_master_volume = adev_set_master_volume;
11087 adev->device.get_master_volume = adev_get_master_volume;
11088 adev->device.set_master_mute = adev_set_master_mute;
11089 adev->device.get_master_mute = adev_get_master_mute;
11090 adev->device.set_mode = adev_set_mode;
11091 adev->device.set_mic_mute = adev_set_mic_mute;
11092 adev->device.get_mic_mute = adev_get_mic_mute;
11093 adev->device.set_parameters = adev_set_parameters;
11094 adev->device.get_parameters = adev_get_parameters;
11095 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
11096 adev->device.open_output_stream = adev_open_output_stream;
11097 adev->device.close_output_stream = adev_close_output_stream;
11098 adev->device.open_input_stream = adev_open_input_stream;
11099 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053011100 adev->device.create_audio_patch = adev_create_audio_patch;
11101 adev->device.release_audio_patch = adev_release_audio_patch;
11102 adev->device.get_audio_port = adev_get_audio_port;
11103 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011104 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +053011105 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011106
11107 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011108 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -080011109 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011110 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011111 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -080011112 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -070011113 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +053011114 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -070011115 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -070011116 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -070011117 /* Init audio and voice feature */
11118 audio_extn_feature_init();
11119 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070011120 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -080011121 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -080011122 list_init(&adev->active_inputs_list);
11123 list_init(&adev->active_outputs_list);
Rahul Sharma99770982019-03-06 17:05:26 +053011124 list_init(&adev->audio_patch_record_list);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011125 adev->io_streams_map = hashmapCreate(AUDIO_IO_PORTS_MAX, audio_extn_utils_hash_fn,
11126 audio_extn_utils_hash_eq);
11127 if (!adev->io_streams_map) {
11128 ALOGE("%s: Could not create io streams map", __func__);
11129 ret = -ENOMEM;
11130 goto adev_open_err;
11131 }
11132 adev->patch_map = hashmapCreate(AUDIO_PATCH_PORTS_MAX, audio_extn_utils_hash_fn,
11133 audio_extn_utils_hash_eq);
11134 if (!adev->patch_map) {
11135 ALOGE("%s: Could not create audio patch map", __func__);
11136 ret = -ENOMEM;
11137 goto adev_open_err;
11138 }
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -080011139 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -070011140 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +053011141 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +053011142 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +053011143 adev->perf_lock_opts[0] = 0x101;
11144 adev->perf_lock_opts[1] = 0x20E;
11145 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +080011146 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -070011147 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053011148 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070011149 adev->adm_routing_changed = false;
Revathi Uddarajub26e3932020-06-10 14:51:02 +053011150 adev->a2dp_started = false;
Zhou Song503196b2021-07-23 17:31:05 +080011151 adev->ha_proxy_enable = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +053011152
Zhou Song68ebc352019-12-05 17:11:15 +080011153 audio_extn_perf_lock_init();
11154
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011155 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -070011156 adev->platform = platform_init(adev);
11157 if (!adev->platform) {
Eric Laurentb23d5282013-05-14 15:27:20 -070011158 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011159 ret = -EINVAL;
11160 goto adev_open_err;
Eric Laurentb23d5282013-05-14 15:27:20 -070011161 }
Eric Laurentc4aef752013-09-12 17:45:53 -070011162
Aalique Grahame22e49102018-12-18 14:23:57 -080011163 adev->extspk = audio_extn_extspk_init(adev);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053011164 if (audio_extn_qap_is_enabled()) {
11165 ret = audio_extn_qap_init(adev);
11166 if (ret < 0) {
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053011167 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011168 goto adev_open_err;
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053011169 }
11170 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
11171 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
11172 }
Aalique Grahame22e49102018-12-18 14:23:57 -080011173
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053011174 if (audio_extn_qaf_is_enabled()) {
11175 ret = audio_extn_qaf_init(adev);
11176 if (ret < 0) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053011177 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011178 goto adev_open_err;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053011179 }
11180
11181 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
11182 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
11183 }
11184
Derek Chenae7b0342019-02-08 15:17:04 -080011185 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -080011186 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
11187
Eric Laurentc4aef752013-09-12 17:45:53 -070011188 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
11189 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
11190 if (adev->visualizer_lib == NULL) {
11191 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
11192 } else {
11193 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
11194 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080011195 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070011196 "visualizer_hal_start_output");
11197 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080011198 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070011199 "visualizer_hal_stop_output");
11200 }
11201 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +053011202 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080011203 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -080011204 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +080011205 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +053011206 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070011207 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -070011208
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080011209 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
11210 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
11211 if (adev->offload_effects_lib == NULL) {
11212 ALOGE("%s: DLOPEN failed for %s", __func__,
11213 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
11214 } else {
11215 ALOGV("%s: DLOPEN successful for %s", __func__,
11216 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
11217 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +053011218 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080011219 "offload_effects_bundle_hal_start_output");
11220 adev->offload_effects_stop_output =
11221 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
11222 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080011223 adev->offload_effects_set_hpx_state =
11224 (int (*)(bool))dlsym(adev->offload_effects_lib,
11225 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +053011226 adev->offload_effects_get_parameters =
11227 (void (*)(struct str_parms *, struct str_parms *))
11228 dlsym(adev->offload_effects_lib,
11229 "offload_effects_bundle_get_parameters");
11230 adev->offload_effects_set_parameters =
11231 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
11232 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080011233 }
11234 }
11235
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070011236 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
11237 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
11238 if (adev->adm_lib == NULL) {
11239 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
11240 } else {
11241 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
11242 adev->adm_init = (adm_init_t)
11243 dlsym(adev->adm_lib, "adm_init");
11244 adev->adm_deinit = (adm_deinit_t)
11245 dlsym(adev->adm_lib, "adm_deinit");
11246 adev->adm_register_input_stream = (adm_register_input_stream_t)
11247 dlsym(adev->adm_lib, "adm_register_input_stream");
11248 adev->adm_register_output_stream = (adm_register_output_stream_t)
11249 dlsym(adev->adm_lib, "adm_register_output_stream");
11250 adev->adm_deregister_stream = (adm_deregister_stream_t)
11251 dlsym(adev->adm_lib, "adm_deregister_stream");
11252 adev->adm_request_focus = (adm_request_focus_t)
11253 dlsym(adev->adm_lib, "adm_request_focus");
11254 adev->adm_abandon_focus = (adm_abandon_focus_t)
11255 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -070011256 adev->adm_set_config = (adm_set_config_t)
11257 dlsym(adev->adm_lib, "adm_set_config");
11258 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
11259 dlsym(adev->adm_lib, "adm_request_focus_v2");
11260 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
11261 dlsym(adev->adm_lib, "adm_is_noirq_avail");
11262 adev->adm_on_routing_change = (adm_on_routing_change_t)
11263 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070011264 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
11265 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070011266 }
11267 }
11268
Aalique Grahame22e49102018-12-18 14:23:57 -080011269 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070011270 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +080011271 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Kunlei Zhanga3c4cb02021-03-05 16:03:54 +080011272 adev->fluence_nn_usecase_id = USECASE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -080011273 //initialize this to false for now,
11274 //this will be set to true through set param
11275 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070011276
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -070011277 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011278 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -080011279
11280 if (k_enable_extended_precision)
11281 adev_verify_devices(adev);
11282
Xiaojun Sang785b5da2017-08-03 15:52:29 +080011283 adev->dsp_bit_width_enforce_mode =
11284 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011285
Dhananjay Kumard6d32152016-10-13 16:11:03 +053011286 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
11287 &adev->streams_output_cfg_list,
11288 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070011289
Kiran Kandi910e1862013-10-29 13:29:42 -070011290 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070011291
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070011292 int trial;
Manisha Agarwalc75a0202019-12-06 18:48:25 +053011293 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070011294 trial = atoi(value);
11295 if (period_size_is_plausible_for_low_latency(trial)) {
11296 pcm_config_low_latency.period_size = trial;
11297 pcm_config_low_latency.start_threshold = trial / 4;
11298 pcm_config_low_latency.avail_min = trial / 4;
11299 configured_low_latency_capture_period_size = trial;
11300 }
11301 }
ronghuiz93177262021-04-21 19:58:13 +080011302 if (property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070011303 trial = atoi(value);
11304 if (period_size_is_plausible_for_low_latency(trial)) {
11305 configured_low_latency_capture_period_size = trial;
11306 }
11307 }
11308
Vignesh Kulothungan7d374312018-02-21 17:12:00 -080011309 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
11310
Eric Laurent4b084132018-10-19 17:33:43 -070011311 adev->camera_orientation = CAMERA_DEFAULT;
11312
Manisha Agarwalc75a0202019-12-06 18:48:25 +053011313 if (property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -070011314 af_period_multiplier = atoi(value);
11315 if (af_period_multiplier < 0)
11316 af_period_multiplier = 2;
11317 else if (af_period_multiplier > 4)
11318 af_period_multiplier = 4;
11319
11320 ALOGV("new period_multiplier = %d", af_period_multiplier);
11321 }
11322
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080011323 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080011324
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -070011325 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070011326 pthread_mutex_unlock(&adev_init_lock);
11327
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070011328 if (adev->adm_init)
11329 adev->adm_data = adev->adm_init();
11330
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053011331 qahwi_init(*device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080011332 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053011333
11334 audio_extn_snd_mon_init();
11335 pthread_mutex_lock(&adev->lock);
11336 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
11337 adev->card_status = CARD_STATUS_ONLINE;
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -050011338 adev->out_power_policy = POWER_POLICY_STATUS_ONLINE;
11339 adev->in_power_policy = POWER_POLICY_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -070011340 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
11341 /*
11342 * if the battery state callback happens before charging can be queried,
11343 * it will be guarded with the adev->lock held in the cb function and so
11344 * the callback value will reflect the latest state
11345 */
11346 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053011347 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +080011348 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -070011349 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +080011350 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053011351 /* Allocate memory for Device config params */
11352 adev->device_cfg_params = (struct audio_device_config_param*)
11353 calloc(platform_get_max_codec_backend(),
11354 sizeof(struct audio_device_config_param));
11355 if (adev->device_cfg_params == NULL)
11356 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053011357
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053011358 /*
11359 * Check if new PSPD matrix mixer control is supported. If not
11360 * supported, then set flag so that old mixer ctrl is sent while
11361 * sending pspd coefficients on older kernel version. Query mixer
11362 * control for default pcm id and channel value one.
11363 */
11364 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
11365 "AudStr %d ChMixer Weight Ch %d", 0, 1);
11366
11367 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
11368 if (!ctl) {
11369 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
11370 __func__, mixer_ctl_name);
11371 adev->use_old_pspd_mix_ctrl = true;
11372 }
11373
Jaideep Sharma0fa53812020-09-17 09:00:11 +053011374 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011375 return 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011376
11377adev_open_err:
11378 free_map(adev->patch_map);
11379 free_map(adev->io_streams_map);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080011380 free(adev->snd_dev_ref_cnt);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011381 pthread_mutex_destroy(&adev->lock);
11382 free(adev);
11383 adev = NULL;
11384 *device = NULL;
11385 pthread_mutex_unlock(&adev_init_lock);
11386 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011387}
11388
11389static struct hw_module_methods_t hal_module_methods = {
11390 .open = adev_open,
11391};
11392
11393struct audio_module HAL_MODULE_INFO_SYM = {
11394 .common = {
11395 .tag = HARDWARE_MODULE_TAG,
11396 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
11397 .hal_api_version = HARDWARE_HAL_API_VERSION,
11398 .id = AUDIO_HARDWARE_MODULE_ID,
11399 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -080011400 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011401 .methods = &hal_module_methods,
11402 },
11403};