blob: 1fc058661320ecb77cd40e1cf7bbd83234f80063 [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
Krishna Kishor Jhaaf83fd82022-11-15 17:54:07 +053096#define SKIP_INPUT_SOURCE_PRIORITY
97
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070098#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053099/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
100#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700101#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700102#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Arun Mirpuri5d170872019-03-26 13:21:31 -0700103#define MMAP_PLAYBACK_VOLUME_MAX 0x2000
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530104#define PCM_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530105#define DSD_VOLUME_MIN_DB (-110)
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700106#define INVALID_OUT_VOLUME -1
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700107#define AUDIO_IO_PORTS_MAX 32
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700108
Zhou Songbaddf9f2020-11-20 13:57:39 +0800109#define PLAYBACK_GAIN_MAX 1.0f
Aalique Grahame22e49102018-12-18 14:23:57 -0800110#define RECORD_GAIN_MIN 0.0f
111#define RECORD_GAIN_MAX 1.0f
112#define RECORD_VOLUME_CTL_MAX 0x2000
113
114/* treat as unsigned Q1.13 */
115#define APP_TYPE_GAIN_DEFAULT 0x2000
116
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700117#define PROXY_OPEN_RETRY_COUNT 100
118#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800119
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800120#define GET_USECASE_AUDIO_PLAYBACK_PRIMARY(db) \
121 (db)? USECASE_AUDIO_PLAYBACK_DEEP_BUFFER : \
122 USECASE_AUDIO_PLAYBACK_LOW_LATENCY
123#define GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(db) \
124 (db)? pcm_config_deep_buffer : pcm_config_low_latency
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800125
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700126#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700127#define DEFAULT_VOIP_BUF_DURATION_MS 20
128#define DEFAULT_VOIP_BIT_DEPTH_BYTE sizeof(int16_t)
129#define DEFAULT_VOIP_SAMP_RATE 48000
130
131#define VOIP_IO_BUF_SIZE(SR, DURATION_MS, BIT_DEPTH) (SR)/1000 * DURATION_MS * BIT_DEPTH
132
133struct pcm_config default_pcm_config_voip_copp = {
134 .channels = 1,
135 .rate = DEFAULT_VOIP_SAMP_RATE, /* changed when the stream is opened */
136 .period_size = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
137 .period_count = 2,
138 .format = PCM_FORMAT_S16_LE,
kunleiz95b597a2017-10-23 17:07:33 +0800139 .avail_min = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
140 .stop_threshold = INT_MAX,
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700141};
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700142
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700143#define MIN_CHANNEL_COUNT 1
144#define DEFAULT_CHANNEL_COUNT 2
145#define MAX_HIFI_CHANNEL_COUNT 8
146
Aalique Grahame22e49102018-12-18 14:23:57 -0800147#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
148#define MAX_CHANNEL_COUNT 1
149#else
150#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
151#define XSTR(x) STR(x)
152#define STR(x) #x
153#endif
154
Avinash Chandrad7296d42021-08-04 15:07:47 +0530155#define IS_USB_HIFI (MAX_HIFI_CHANNEL_COUNT >= MAX_CHANNEL_COUNT) ? \
156 true : false
157
Dechen Chai22768452021-07-30 09:29:16 +0530158#ifdef LINUX_ENABLED
159static inline int64_t audio_utils_ns_from_timespec(const struct timespec *ts)
160{
161 return ts->tv_sec * 1000000000LL + ts->tv_nsec;
162}
163#endif
164
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700165static unsigned int configured_low_latency_capture_period_size =
166 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
167
Haynes Mathew George16081042017-05-31 17:16:49 -0700168#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
169#define MMAP_PERIOD_COUNT_MIN 32
170#define MMAP_PERIOD_COUNT_MAX 512
171#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
172
Aalique Grahame22e49102018-12-18 14:23:57 -0800173/* This constant enables extended precision handling.
174 * TODO The flag is off until more testing is done.
175 */
176static const bool k_enable_extended_precision = false;
Arun Mirpurie008ed22019-03-21 11:21:04 -0700177extern int AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Aalique Grahame22e49102018-12-18 14:23:57 -0800178
Eric Laurentb23d5282013-05-14 15:27:20 -0700179struct pcm_config pcm_config_deep_buffer = {
180 .channels = 2,
181 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
182 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
183 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
184 .format = PCM_FORMAT_S16_LE,
185 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
186 .stop_threshold = INT_MAX,
187 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
188};
189
190struct pcm_config pcm_config_low_latency = {
191 .channels = 2,
192 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
193 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
194 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
195 .format = PCM_FORMAT_S16_LE,
196 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
197 .stop_threshold = INT_MAX,
198 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
199};
200
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800201struct pcm_config pcm_config_haptics_audio = {
202 .channels = 1,
203 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
204 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
205 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
206 .format = PCM_FORMAT_S16_LE,
207 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
208 .stop_threshold = INT_MAX,
209 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
210};
211
212struct pcm_config pcm_config_haptics = {
213 .channels = 1,
214 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
215 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
216 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
217 .format = PCM_FORMAT_S16_LE,
218 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
219 .stop_threshold = INT_MAX,
220 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
221};
222
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700223static int af_period_multiplier = 4;
224struct pcm_config pcm_config_rt = {
225 .channels = 2,
226 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
227 .period_size = ULL_PERIOD_SIZE, //1 ms
228 .period_count = 512, //=> buffer size is 512ms
229 .format = PCM_FORMAT_S16_LE,
230 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
231 .stop_threshold = INT_MAX,
232 .silence_threshold = 0,
233 .silence_size = 0,
234 .avail_min = ULL_PERIOD_SIZE, //1 ms
235};
236
Eric Laurentb23d5282013-05-14 15:27:20 -0700237struct pcm_config pcm_config_hdmi_multi = {
238 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
239 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
240 .period_size = HDMI_MULTI_PERIOD_SIZE,
241 .period_count = HDMI_MULTI_PERIOD_COUNT,
242 .format = PCM_FORMAT_S16_LE,
243 .start_threshold = 0,
244 .stop_threshold = INT_MAX,
245 .avail_min = 0,
246};
247
Haynes Mathew George16081042017-05-31 17:16:49 -0700248struct pcm_config pcm_config_mmap_playback = {
249 .channels = 2,
250 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
251 .period_size = MMAP_PERIOD_SIZE,
252 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
253 .format = PCM_FORMAT_S16_LE,
254 .start_threshold = MMAP_PERIOD_SIZE*8,
255 .stop_threshold = INT32_MAX,
256 .silence_threshold = 0,
257 .silence_size = 0,
258 .avail_min = MMAP_PERIOD_SIZE, //1 ms
259};
260
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700261struct pcm_config pcm_config_hifi = {
262 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
263 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
264 .period_size = HIFI_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
265 .period_count = HIFI_BUFFER_OUTPUT_PERIOD_COUNT,
266 .format = PCM_FORMAT_S24_3LE,
267 .start_threshold = 0,
268 .stop_threshold = INT_MAX,
269 .avail_min = 0,
270};
271
Eric Laurentb23d5282013-05-14 15:27:20 -0700272struct pcm_config pcm_config_audio_capture = {
273 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700274 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
275 .format = PCM_FORMAT_S16_LE,
276};
277
Haynes Mathew George16081042017-05-31 17:16:49 -0700278struct pcm_config pcm_config_mmap_capture = {
279 .channels = 2,
280 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
281 .period_size = MMAP_PERIOD_SIZE,
282 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
283 .format = PCM_FORMAT_S16_LE,
284 .start_threshold = 0,
285 .stop_threshold = INT_MAX,
286 .silence_threshold = 0,
287 .silence_size = 0,
288 .avail_min = MMAP_PERIOD_SIZE, //1 ms
289};
290
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700291#define AFE_PROXY_CHANNEL_COUNT 2
292#define AFE_PROXY_SAMPLING_RATE 48000
293
294#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
295#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
296
297struct pcm_config pcm_config_afe_proxy_playback = {
298 .channels = AFE_PROXY_CHANNEL_COUNT,
299 .rate = AFE_PROXY_SAMPLING_RATE,
300 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
301 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
302 .format = PCM_FORMAT_S16_LE,
303 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
304 .stop_threshold = INT_MAX,
305 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
306};
307
308#define AFE_PROXY_RECORD_PERIOD_SIZE 768
309#define AFE_PROXY_RECORD_PERIOD_COUNT 4
310
Aalique Grahame22e49102018-12-18 14:23:57 -0800311struct pcm_config pcm_config_audio_capture_rt = {
312 .channels = 2,
313 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
314 .period_size = ULL_PERIOD_SIZE,
315 .period_count = 512,
316 .format = PCM_FORMAT_S16_LE,
317 .start_threshold = 0,
318 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
319 .silence_threshold = 0,
320 .silence_size = 0,
321 .avail_min = ULL_PERIOD_SIZE, //1 ms
322};
323
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +0530324struct pcm_config pcm_config_audio_capture_rt_48KHz = {
325 .channels = 2,
326 .rate = 48000,
327 .period_size = 48,
328 .period_count = 512,
329 .format = PCM_FORMAT_S16_LE,
330 .start_threshold = 0,
331 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
332 .silence_threshold = 0,
333 .silence_size = 0,
334 .avail_min = 48, //1 ms
335};
336struct pcm_config pcm_config_audio_capture_rt_32KHz = {
337 .channels = 2,
338 .rate = 32000,
339 .period_size = 32,
340 .period_count = 512,
341 .format = PCM_FORMAT_S16_LE,
342 .start_threshold = 0,
343 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
344 .silence_threshold = 0,
345 .silence_size = 0,
346 .avail_min = 32, //1 ms
347};
348struct pcm_config pcm_config_audio_capture_rt_24KHz = {
349 .channels = 2,
350 .rate = 24000,
351 .period_size = 24,
352 .period_count = 512,
353 .format = PCM_FORMAT_S16_LE,
354 .start_threshold = 0,
355 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
356 .silence_threshold = 0,
357 .silence_size = 0,
358 .avail_min = 24, //1 ms
359};
360struct pcm_config pcm_config_audio_capture_rt_16KHz = {
361 .channels = 2,
362 .rate = 16000,
363 .period_size = 16,
364 .period_count = 512,
365 .format = PCM_FORMAT_S16_LE,
366 .start_threshold = 0,
367 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
368 .silence_threshold = 0,
369 .silence_size = 0,
370 .avail_min = 16, //1 ms
371};
372struct pcm_config pcm_config_audio_capture_rt_8KHz = {
373 .channels = 2,
374 .rate = 8000,
375 .period_size = 8,
376 .period_count = 512,
377 .format = PCM_FORMAT_S16_LE,
378 .start_threshold = 0,
379 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
380 .silence_threshold = 0,
381 .silence_size = 0,
382 .avail_min = 8, //1 ms
383};
384
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700385struct pcm_config pcm_config_afe_proxy_record = {
386 .channels = AFE_PROXY_CHANNEL_COUNT,
387 .rate = AFE_PROXY_SAMPLING_RATE,
388 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
389 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
390 .format = PCM_FORMAT_S16_LE,
391 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
392 .stop_threshold = INT_MAX,
393 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
394};
395
Ashish Jainf1eaa582016-05-23 20:54:24 +0530396#define AUDIO_MAX_PCM_FORMATS 7
397
398const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
399 [AUDIO_FORMAT_DEFAULT] = 0,
400 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
401 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
402 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
403 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
404 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
405 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
406};
407
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800408const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700409 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
410 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800411 [USECASE_AUDIO_PLAYBACK_WITH_HAPTICS] = "audio-with-haptics-playback",
Meng Wang51d8c2a2020-04-27 15:23:21 +0800412 [USECASE_AUDIO_PLAYBACK_HAPTICS] = "haptics-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700413 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
414 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700415 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700416 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700417 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
418 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
419 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
420 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
421 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
422 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
423 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
424 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
Haynes Mathew George16081042017-05-31 17:16:49 -0700425 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
426 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700427 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Aalique Grahame22e49102018-12-18 14:23:57 -0800428 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
vivek mehta0ea887a2015-08-26 14:01:20 -0700429
Eric Laurentb23d5282013-05-14 15:27:20 -0700430 [USECASE_AUDIO_RECORD] = "audio-record",
Krishna Kishor Jha0f4d8482022-02-18 10:56:05 +0530431 [USECASE_AUDIO_RECORD2] = "audio-record2",
432 [USECASE_AUDIO_RECORD3] = "audio-record3",
Mingming Yine62d7842013-10-25 16:26:03 -0700433 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530434 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
435 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
436 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Dhananjay Kumar376e38b2017-09-28 22:26:23 +0530437 [USECASE_AUDIO_RECORD_COMPRESS5] = "audio-record-compress5",
438 [USECASE_AUDIO_RECORD_COMPRESS6] = "audio-record-compress6",
Eric Laurentb23d5282013-05-14 15:27:20 -0700439 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Kogara Naveen Kumarc5758232022-11-07 20:25:40 +0530440 [USECASE_AUDIO_RECORD_LOW_LATENCY2] = "low-latency-record2",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700441 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700442 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700443 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700444
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800445 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800446 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Derek Chenf7092792017-05-23 12:23:53 -0400447 [USECASE_AUDIO_HFP_SCO_DOWNLINK] = "hfp-sco-downlink",
448 [USECASE_AUDIO_HFP_SCO_WB_DOWNLINK] = "hfp-sco-wb-downlink",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700449
Derek Chenf7092792017-05-23 12:23:53 -0400450 [USECASE_VOICE_CALL] = "voice-call",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700451 [USECASE_VOICE2_CALL] = "voice2-call",
452 [USECASE_VOLTE_CALL] = "volte-call",
453 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800454 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800455 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
456 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800457 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700458 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
459 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
460 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800461 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
462 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
463 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
464
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700465 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
466 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700467 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
468 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700469
470 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
471 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Zhou Song62ea0282020-03-22 19:53:01 +0800472 [USECASE_AUDIO_RECORD_AFE_PROXY2] = "afe-proxy-record2",
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +0530473 [USECASE_AUDIO_PLAYBACK_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700474
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530475 /* Transcode loopback cases */
Surendar Karka93cd25a2018-08-28 14:21:37 +0530476 [USECASE_AUDIO_TRANSCODE_LOOPBACK_RX] = "audio-transcode-loopback-rx",
477 [USECASE_AUDIO_TRANSCODE_LOOPBACK_TX] = "audio-transcode-loopback-tx",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700478
479 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
480 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Revathi Uddarajud9f23d92020-07-27 10:55:06 +0530481 [USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY] = "audio-record-voip-low-latency",
Varun Balaraje49253e2017-07-06 19:48:56 +0530482 /* For Interactive Audio Streams */
483 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
484 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
485 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
486 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
487 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
488 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
489 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
490 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700491
Aniket Kumar Lata7fd86e12018-02-20 19:26:10 -0800492 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture",
493
Derek Chenf6318be2017-06-12 17:16:24 -0400494 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
495
496 [USECASE_AUDIO_PLAYBACK_MEDIA] = "media-playback",
Kogara Naveen Kumarc5758232022-11-07 20:25:40 +0530497 [USECASE_AUDIO_PLAYBACK_MEDIA_LL] = "media-playback-ll",
Derek Chenf6318be2017-06-12 17:16:24 -0400498 [USECASE_AUDIO_PLAYBACK_SYS_NOTIFICATION] = "sys-notification-playback",
499 [USECASE_AUDIO_PLAYBACK_NAV_GUIDANCE] = "nav-guidance-playback",
Kogara Naveen Kumarc5758232022-11-07 20:25:40 +0530500 [USECASE_AUDIO_PLAYBACK_NAV_GUIDANCE_LL] = "nav-guidance-playback-ll",
Derek Chenf6318be2017-06-12 17:16:24 -0400501 [USECASE_AUDIO_PLAYBACK_PHONE] = "phone-playback",
Kogara Naveen Kumar65828fe2022-10-14 16:41:04 +0530502 [USECASE_AUDIO_PLAYBACK_PHONE_LL] = "phone-playback-ll",
Susan Wang117cf6f2022-04-06 20:11:46 -0400503 [USECASE_AUDIO_PLAYBACK_ALERTS] = "alerts-playback",
Kogara Naveen Kumarc5758232022-11-07 20:25:40 +0530504 [USECASE_AUDIO_PLAYBACK_ALERTS_LL] = "alerts-playback-ll",
Derek Chen1bcdc6b2020-02-06 22:44:53 -0800505 [USECASE_AUDIO_PLAYBACK_FRONT_PASSENGER] = "front-passenger-playback",
Derek Chendf05eea2019-08-01 13:57:49 -0700506 [USECASE_AUDIO_PLAYBACK_REAR_SEAT] = "rear-seat-playback",
Rahul Sharma99770982019-03-06 17:05:26 +0530507 [USECASE_AUDIO_FM_TUNER_EXT] = "fm-tuner-ext",
Derek Chena30a5f42019-12-03 11:17:09 -0500508 [USECASE_ICC_CALL] = "icc-call",
Huicheng Liu1404ba12020-09-11 01:03:25 -0400509
510 [USECASE_AUDIO_RECORD_BUS] = "audio-record",
511 [USECASE_AUDIO_RECORD_BUS_FRONT_PASSENGER] = "front-passenger-record",
512 [USECASE_AUDIO_RECORD_BUS_REAR_SEAT] = "rear-seat-record",
Fei Tongaffdf732020-02-20 20:39:05 +0800513 [USECASE_AUDIO_PLAYBACK_SYNTHESIZER] = "synth-loopback",
Susan Wange3959562021-03-11 11:50:26 -0500514 [USECASE_AUDIO_RECORD_ECHO_REF_EXT] = "echo-reference-external",
Eric Laurentb23d5282013-05-14 15:27:20 -0700515};
516
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700517static const audio_usecase_t offload_usecases[] = {
518 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700519 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
520 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
521 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
522 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
523 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
524 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
525 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
526 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700527};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800528
Varun Balaraje49253e2017-07-06 19:48:56 +0530529static const audio_usecase_t interactive_usecases[] = {
530 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
531 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
532 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
533 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
534 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
535 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
536 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
537 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
538};
539
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800540#define STRING_TO_ENUM(string) { #string, string }
541
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800542struct string_to_enum {
543 const char *name;
544 uint32_t value;
545};
546
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700547static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800548 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800549 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
550 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
551 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700552 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800553 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
554 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800555 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700556 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
557 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
558 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
559 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
560 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
561 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
562 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
563 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
564 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
565 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
566 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800567};
568
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700569static const struct string_to_enum formats_name_to_enum_table[] = {
570 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
571 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
572 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700573 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
574 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
575 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700576 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800577 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
578 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700579 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800580};
581
582//list of all supported sample rates by HDMI specification.
583static const int out_hdmi_sample_rates[] = {
584 32000, 44100, 48000, 88200, 96000, 176400, 192000,
585};
586
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700587static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800588 STRING_TO_ENUM(32000),
589 STRING_TO_ENUM(44100),
590 STRING_TO_ENUM(48000),
591 STRING_TO_ENUM(88200),
592 STRING_TO_ENUM(96000),
593 STRING_TO_ENUM(176400),
594 STRING_TO_ENUM(192000),
Mingshu pange8aedf12019-10-25 15:38:27 +0800595 STRING_TO_ENUM(352800),
596 STRING_TO_ENUM(384000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700597};
598
Carter Hsu2e429db2019-05-14 18:50:52 +0800599struct in_effect_list {
600 struct listnode list;
601 effect_handle_t handle;
602};
603
Krishna Kishor Jha0f4d8482022-02-18 10:56:05 +0530604static const audio_usecase_t record_usecases[] = {
605 USECASE_AUDIO_RECORD,
606 USECASE_AUDIO_RECORD2,
607 USECASE_AUDIO_RECORD3,
608};
609
Kogara Naveen Kumarc5758232022-11-07 20:25:40 +0530610static const audio_usecase_t low_latency_record_usecases[] = {
611 USECASE_AUDIO_RECORD_LOW_LATENCY,
612 USECASE_AUDIO_RECORD_LOW_LATENCY2,
613};
614
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700615static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700616static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700617static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700618//cache last MBDRC cal step level
619static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700620
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530621static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Arun Mirpuri5d170872019-03-26 13:21:31 -0700622static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800623static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530624static int out_set_pcm_volume(struct audio_stream_out *stream, float left, float right);
Krishna Kishor Jha10ad39f2022-02-21 17:02:47 +0530625#ifdef SOFT_VOLUME
626static int out_set_soft_volume_params(struct audio_stream_out *stream);
627#endif
Derek Chen6f293672019-04-01 01:40:24 -0700628static void adev_snd_mon_cb(void *cookie, struct str_parms *parms);
629static void in_snd_mon_cb(void * stream, struct str_parms * parms);
630static void out_snd_mon_cb(void * stream, struct str_parms * parms);
631
Zhou Song331c8e52019-08-26 14:16:12 +0800632static int configure_btsco_sample_rate(snd_device_t snd_device);
633
Vatsal Buchac09ae062018-11-14 13:25:08 +0530634#ifdef AUDIO_FEATURE_ENABLED_GCOV
635extern void __gcov_flush();
636static void enable_gcov()
637{
638 __gcov_flush();
639}
640#else
641static void enable_gcov()
642{
643}
644#endif
645
justinweng20fb6d82019-02-21 18:49:00 -0700646static int in_set_microphone_direction(const struct audio_stream_in *stream,
647 audio_microphone_direction_t dir);
648static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom);
649
Krishna Kishor Jha0f4d8482022-02-18 10:56:05 +0530650static bool is_pcm_record_usecase(audio_usecase_t uc_id)
651{
652 unsigned int record_uc_index;
653 unsigned int num_usecase = sizeof(record_usecases)/sizeof(record_usecases[0]);
654
655 for (record_uc_index = 0; record_uc_index < num_usecase; record_uc_index++) {
656 if (uc_id == record_usecases[record_uc_index])
657 return true;
658 }
659 return false;
660}
661
662static audio_usecase_t get_record_usecase(struct audio_device *adev)
663{
664 audio_usecase_t ret_uc = USECASE_INVALID;
665 unsigned int record_uc_index;
666 unsigned int num_usecase = sizeof(record_usecases)/sizeof(record_usecases[0]);
667
668 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
669 for (record_uc_index = 0; record_uc_index < num_usecase; record_uc_index++) {
670 if (!(adev->pcm_record_uc_state & (0x1 << record_uc_index))) {
671 adev->pcm_record_uc_state |= 0x1 << record_uc_index;
672 ret_uc = record_usecases[record_uc_index];
673 break;
674 }
675 }
676
677 ALOGV("%s: pcm record usecase is %d", __func__, ret_uc);
678 return ret_uc;
679}
680
681static void free_record_usecase(struct audio_device *adev,
682 audio_usecase_t uc_id)
683{
684 unsigned int record_uc_index;
685 unsigned int num_usecase = sizeof(record_usecases)/sizeof(record_usecases[0]);
686
687 for (record_uc_index = 0; record_uc_index < num_usecase; record_uc_index++) {
688 if (record_usecases[record_uc_index] == uc_id) {
689 adev->pcm_record_uc_state &= ~(0x1 << record_uc_index);
690 break;
691 }
692 }
693 ALOGV("%s: free pcm record usecase %d", __func__, uc_id);
694}
695
Kogara Naveen Kumarc5758232022-11-07 20:25:40 +0530696static bool is_pcm_low_latency_record_usecase(audio_usecase_t uc_id)
697{
698 unsigned int record_uc_index;
699 unsigned int num_usecase = sizeof(low_latency_record_usecases)/sizeof(low_latency_record_usecases[0]);
700 ALOGD("%s: Check low latency pcm record usecase", __func__);
701
702 for (record_uc_index = 0; record_uc_index < num_usecase; record_uc_index++) {
703 if (uc_id == low_latency_record_usecases[record_uc_index])
704 return true;
705 }
706 return false;
707}
708
709static audio_usecase_t get_low_latency_record_usecase(struct audio_device *adev)
710{
711 audio_usecase_t ret_uc = USECASE_INVALID;
712 unsigned int record_uc_index;
713 unsigned int num_usecase = sizeof(low_latency_record_usecases)/sizeof(low_latency_record_usecases[0]);
714
715 ALOGD("%s: get_low_latency_record_usecase: %d", __func__, num_usecase);
716 for (record_uc_index = 0; record_uc_index < num_usecase; record_uc_index++) {
717 if (!(adev->pcm_low_latency_record_uc_state & (0x1 << record_uc_index))) {
718 adev->pcm_low_latency_record_uc_state |= 0x1 << record_uc_index;
719 ALOGD("%s: get_low_latency_record_usecase: %d", __func__, record_uc_index);
720 ret_uc = low_latency_record_usecases[record_uc_index];
721 break;
722 }
723 }
724
725 ALOGD("%s: low latency pcm record usecase is %d", __func__, ret_uc);
726 return ret_uc;
727}
728
729static void free_low_latency_record_usecase(struct audio_device *adev,
730 audio_usecase_t uc_id)
731{
732 unsigned int record_uc_index;
733 unsigned int num_usecase = sizeof(low_latency_record_usecases)/sizeof(low_latency_record_usecases[0]);
734
735 for (record_uc_index = 0; record_uc_index < num_usecase; record_uc_index++) {
736 if (low_latency_record_usecases[record_uc_index] == uc_id) {
737 adev->pcm_low_latency_record_uc_state &= ~(0x1 << record_uc_index);
738 break;
739 }
740 }
741 ALOGD("%s: free low latency pcm record usecase %d", __func__, uc_id);
742}
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700743static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
744 int flags __unused)
745{
746 int dir = 0;
747 switch (uc_id) {
748 case USECASE_AUDIO_RECORD_LOW_LATENCY:
Revathi Uddarajud9f23d92020-07-27 10:55:06 +0530749 case USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY:
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700750 dir = 1;
751 case USECASE_AUDIO_PLAYBACK_ULL:
752 break;
753 default:
754 return false;
755 }
756
757 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
758 PCM_PLAYBACK : PCM_CAPTURE);
759 if (adev->adm_is_noirq_avail)
760 return adev->adm_is_noirq_avail(adev->adm_data,
761 adev->snd_card, dev_id, dir);
762 return false;
763}
764
765static void register_out_stream(struct stream_out *out)
766{
767 struct audio_device *adev = out->dev;
768 if (is_offload_usecase(out->usecase) ||
769 !adev->adm_register_output_stream)
770 return;
771
772 // register stream first for backward compatibility
773 adev->adm_register_output_stream(adev->adm_data,
774 out->handle,
775 out->flags);
776
777 if (!adev->adm_set_config)
778 return;
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +0530779#ifdef PLATFORM_AUTO
Kogara Naveen Kumar6db5fb02022-05-07 00:22:50 +0530780 if (out->realtime || (out->flags & AUDIO_OUTPUT_FLAG_SYS_NOTIFICATION))
781 adev->adm_set_config(adev->adm_data,
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700782 out->handle,
783 out->pcm, &out->config);
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +0530784#else
785 if (out->realtime)
786 adev->adm_set_config(adev->adm_data,
787 out->handle,
788 out->pcm, &out->config);
789#endif
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700790}
791
792static void register_in_stream(struct stream_in *in)
793{
794 struct audio_device *adev = in->dev;
795 if (!adev->adm_register_input_stream)
796 return;
797
798 adev->adm_register_input_stream(adev->adm_data,
799 in->capture_handle,
800 in->flags);
801
802 if (!adev->adm_set_config)
803 return;
804
805 if (in->realtime)
806 adev->adm_set_config(adev->adm_data,
807 in->capture_handle,
808 in->pcm,
809 &in->config);
810}
811
812static void request_out_focus(struct stream_out *out, long ns)
813{
814 struct audio_device *adev = out->dev;
815
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700816 if (adev->adm_request_focus_v2)
817 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
818 else if (adev->adm_request_focus)
819 adev->adm_request_focus(adev->adm_data, out->handle);
820}
821
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700822static int request_in_focus(struct stream_in *in, long ns)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700823{
824 struct audio_device *adev = in->dev;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700825 int ret = 0;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700826
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700827 if (adev->adm_request_focus_v2_1)
828 ret = adev->adm_request_focus_v2_1(adev->adm_data, in->capture_handle, ns);
829 else if (adev->adm_request_focus_v2)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700830 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
831 else if (adev->adm_request_focus)
832 adev->adm_request_focus(adev->adm_data, in->capture_handle);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700833
834 return ret;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700835}
836
837static void release_out_focus(struct stream_out *out)
838{
839 struct audio_device *adev = out->dev;
840
841 if (adev->adm_abandon_focus)
842 adev->adm_abandon_focus(adev->adm_data, out->handle);
843}
844
845static void release_in_focus(struct stream_in *in)
846{
847 struct audio_device *adev = in->dev;
848 if (adev->adm_abandon_focus)
849 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
850}
851
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530852static int parse_snd_card_status(struct str_parms *parms, int *card,
853 card_status_t *status)
854{
855 char value[32]={0};
856 char state[32]={0};
857
858 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
859 if (ret < 0)
860 return -1;
861
862 // sscanf should be okay as value is of max length 32.
863 // same as sizeof state.
864 if (sscanf(value, "%d,%s", card, state) < 2)
865 return -1;
866
867 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
868 CARD_STATUS_OFFLINE;
869 return 0;
870}
871
Avinash Chandrad7296d42021-08-04 15:07:47 +0530872bool is_combo_audio_input_device(struct listnode *devices){
873
Sandhya Mutha Naga Venkata153d95e2022-07-12 14:54:43 +0530874 if ((devices == NULL) || (!list_empty(devices)))
Avinash Chandrad7296d42021-08-04 15:07:47 +0530875 return false;
876
877 if(compare_device_type(devices, AUDIO_DEVICE_IN_BUILTIN_MIC|AUDIO_DEVICE_IN_SPEAKER_MIC2))
878 return true;
879 else
880 return false;
881}
882
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700883static inline void adjust_frames_for_device_delay(struct stream_out *out,
884 uint32_t *dsp_frames) {
885 // Adjustment accounts for A2dp encoder latency with offload usecases
886 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -0800887 if (is_a2dp_out_device_type(&out->device_list)) {
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700888 unsigned long offset =
889 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
890 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
891 }
892}
893
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700894static inline bool free_entry(void *key __unused,
895 void *value, void *context __unused)
896{
897 free(value);
898 return true;
899}
900
901static inline void free_map(Hashmap *map)
902{
903 if (map) {
904 hashmapForEach(map, free_entry, (void *) NULL);
905 hashmapFree(map);
906 }
907}
908
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800909static inline void patch_map_remove_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700910 audio_patch_handle_t patch_handle)
911{
912 if (patch_handle == AUDIO_PATCH_HANDLE_NONE)
913 return;
914
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700915 struct audio_patch_info *p_info =
916 hashmapGet(adev->patch_map, (void *) (intptr_t) patch_handle);
917 if (p_info) {
918 ALOGV("%s: Remove patch %d", __func__, patch_handle);
919 hashmapRemove(adev->patch_map, (void *) (intptr_t) patch_handle);
920 free(p_info->patch);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700921 free(p_info);
922 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700923}
924
925static inline int io_streams_map_insert(struct audio_device *adev,
926 struct audio_stream *stream,
927 audio_io_handle_t handle,
928 audio_patch_handle_t patch_handle)
929{
930 struct audio_stream_info *s_info =
931 (struct audio_stream_info *) calloc(1, sizeof(struct audio_stream_info));
932
933 if (s_info == NULL) {
934 ALOGE("%s: Could not allocate stream info", __func__);
935 return -ENOMEM;
936 }
937 s_info->stream = stream;
938 s_info->patch_handle = patch_handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700939
940 pthread_mutex_lock(&adev->lock);
941 struct audio_stream_info *stream_info =
942 hashmapPut(adev->io_streams_map, (void *) (intptr_t) handle, (void *) s_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700943 if (stream_info != NULL)
944 free(stream_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800945 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Latad13758f2020-08-06 15:11:36 -0700946 ALOGV("%s: Added stream in io_streams_map with handle %d", __func__, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700947 return 0;
948}
949
950static inline void io_streams_map_remove(struct audio_device *adev,
951 audio_io_handle_t handle)
952{
953 pthread_mutex_lock(&adev->lock);
954 struct audio_stream_info *s_info =
955 hashmapRemove(adev->io_streams_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700956 if (s_info == NULL)
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800957 goto done;
Aniket Kumar Latad13758f2020-08-06 15:11:36 -0700958 ALOGV("%s: Removed stream with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800959 patch_map_remove_l(adev, s_info->patch_handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700960 free(s_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800961done:
962 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700963 return;
964}
965
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800966static struct audio_patch_info* fetch_patch_info_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700967 audio_patch_handle_t handle)
968{
969 struct audio_patch_info *p_info = NULL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700970 p_info = (struct audio_patch_info *)
971 hashmapGet(adev->patch_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700972 return p_info;
973}
974
vivek mehtaa76401a2015-04-24 14:12:15 -0700975__attribute__ ((visibility ("default")))
976bool audio_hw_send_gain_dep_calibration(int level) {
977 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700978 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700979
980 pthread_mutex_lock(&adev_init_lock);
981
982 if (adev != NULL && adev->platform != NULL) {
983 pthread_mutex_lock(&adev->lock);
984 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700985
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530986 // cache level info for any of the use case which
987 // was not started.
988 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700989
vivek mehtaa76401a2015-04-24 14:12:15 -0700990 pthread_mutex_unlock(&adev->lock);
991 } else {
992 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
993 }
994
995 pthread_mutex_unlock(&adev_init_lock);
996
997 return ret_val;
998}
999
Ashish Jain5106d362016-05-11 19:23:33 +05301000static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
1001{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08001002 bool gapless_enabled = false;
1003 const char *mixer_ctl_name = "Compress Gapless Playback";
1004 struct mixer_ctl *ctl;
1005
1006 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07001007 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +05301008
1009 /*Disable gapless if its AV playback*/
1010 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08001011
1012 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1013 if (!ctl) {
1014 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1015 __func__, mixer_ctl_name);
1016 return -EINVAL;
1017 }
1018
1019 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
1020 ALOGE("%s: Could not set gapless mode %d",
1021 __func__, gapless_enabled);
1022 return -EINVAL;
1023 }
1024 return 0;
1025}
Haynes Mathew George5191a852013-09-11 14:19:36 -07001026
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -07001027__attribute__ ((visibility ("default")))
1028int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
1029 int table_size) {
1030 int ret_val = 0;
1031 ALOGV("%s: enter ... ", __func__);
1032
1033 pthread_mutex_lock(&adev_init_lock);
1034 if (adev == NULL) {
1035 ALOGW("%s: adev is NULL .... ", __func__);
1036 goto done;
1037 }
1038
1039 pthread_mutex_lock(&adev->lock);
1040 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
1041 pthread_mutex_unlock(&adev->lock);
1042done:
1043 pthread_mutex_unlock(&adev_init_lock);
1044 ALOGV("%s: exit ... ", __func__);
1045 return ret_val;
1046}
1047
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001048bool audio_hw_send_qdsp_parameter(int stream_type, float vol, bool active)
Aalique Grahame22e49102018-12-18 14:23:57 -08001049{
1050 bool ret = false;
1051 ALOGV("%s: enter ...", __func__);
1052
1053 pthread_mutex_lock(&adev_init_lock);
1054
1055 if (adev != NULL && adev->platform != NULL) {
1056 pthread_mutex_lock(&adev->lock);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001057 ret = audio_extn_qdsp_set_state(adev, stream_type, vol, active);
Aalique Grahame22e49102018-12-18 14:23:57 -08001058 pthread_mutex_unlock(&adev->lock);
1059 }
1060
1061 pthread_mutex_unlock(&adev_init_lock);
1062
1063 ALOGV("%s: exit with ret %d", __func__, ret);
1064 return ret;
1065}
Aalique Grahame22e49102018-12-18 14:23:57 -08001066
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001067static bool is_supported_format(audio_format_t format)
1068{
Eric Laurent86e17132013-09-12 17:49:30 -07001069 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +05301070 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +05301071 format == AUDIO_FORMAT_AAC_LC ||
1072 format == AUDIO_FORMAT_AAC_HE_V1 ||
1073 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +05301074 format == AUDIO_FORMAT_AAC_ADTS_LC ||
1075 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
1076 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05301077 format == AUDIO_FORMAT_AAC_LATM_LC ||
1078 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
1079 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +05301080 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
1081 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +05301082 format == AUDIO_FORMAT_PCM_FLOAT ||
1083 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -07001084 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301085 format == AUDIO_FORMAT_AC3 ||
1086 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -07001087 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301088 format == AUDIO_FORMAT_DTS ||
1089 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001090 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301091 format == AUDIO_FORMAT_ALAC ||
1092 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301093 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301094 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001095 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05301096 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07001097 format == AUDIO_FORMAT_APTX ||
1098 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08001099 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001100
1101 return false;
1102}
1103
Kunlei Zhang67cc7072020-12-18 17:16:49 +08001104static bool is_supported_conc_usecase_for_power_mode_call(struct audio_device *adev)
1105{
1106 struct listnode *node;
1107 struct audio_usecase *usecase;
1108
1109 list_for_each(node, &adev->usecase_list) {
1110 usecase = node_to_item(node, struct audio_usecase, list);
1111 if (usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1112 ALOGD("%s: FM usecase is active, not setting power mode", __func__);
1113 return false;
1114 }
1115 }
1116
1117 return true;
1118}
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001119static inline bool is_mmap_usecase(audio_usecase_t uc_id)
1120{
1121 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
Zhou Song62ea0282020-03-22 19:53:01 +08001122 (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY2) ||
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001123 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
1124}
1125
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07001126static inline bool is_valid_volume(float left, float right)
1127{
1128 return ((left >= 0.0f && right >= 0.0f) ? true : false);
1129}
1130
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301131static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301132{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301133 ALOGV("%s", __func__);
1134 audio_route_apply_and_update_path(adev->audio_route,
1135 "asrc-mode");
1136 adev->asrc_mode_enabled = true;
1137}
1138
1139static void disable_asrc_mode(struct audio_device *adev)
1140{
1141 ALOGV("%s", __func__);
1142 audio_route_reset_and_update_path(adev->audio_route,
1143 "asrc-mode");
1144 adev->asrc_mode_enabled = false;
1145}
1146
Saurav Kumarc1411662020-10-14 10:50:45 +05301147static void check_and_configure_headphone(struct audio_device *adev,
1148 struct audio_usecase *uc_info,
1149 snd_device_t snd_device)
1150{
1151 struct listnode *node;
1152 struct audio_usecase *usecase;
1153 int new_backend_idx, usecase_backend_idx;
1154 bool spkr_hph_single_be_native_concurrency;
1155
1156 new_backend_idx = platform_get_backend_index(snd_device);
1157 spkr_hph_single_be_native_concurrency = platform_get_spkr_hph_single_be_native_concurrency_flag();
Zhou Songd4b18c42021-01-14 15:15:29 +08001158 if ((spkr_hph_single_be_native_concurrency && (new_backend_idx == DEFAULT_CODEC_BACKEND)) ||
1159 uc_info->id == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
Saurav Kumarc1411662020-10-14 10:50:45 +05301160 list_for_each(node, &adev->usecase_list) {
1161 usecase = node_to_item(node, struct audio_usecase, list);
1162 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
1163 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
1164 if (((usecase_backend_idx == HEADPHONE_BACKEND) ||
1165 (usecase_backend_idx == HEADPHONE_44_1_BACKEND)) &&
1166 ((usecase->stream.out->sample_rate % OUTPUT_SAMPLING_RATE_44100) == 0)) {
1167 disable_audio_route(adev, usecase);
1168 disable_snd_device(adev, usecase->out_snd_device);
1169 usecase->stream.out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Saurav Kumar70902382020-10-28 11:16:04 +05301170 platform_check_and_set_codec_backend_cfg(adev, usecase,
1171 usecase->out_snd_device);
Saurav Kumarc1411662020-10-14 10:50:45 +05301172 enable_snd_device(adev, usecase->out_snd_device);
Zhou Songd4b18c42021-01-14 15:15:29 +08001173 enable_audio_route(adev, usecase);
Saurav Kumarc1411662020-10-14 10:50:45 +05301174 }
1175 }
Revathi Uddaraju2c0eac02021-07-27 02:06:42 -07001176 else if ((usecase->type != PCM_CAPTURE) && (usecase == uc_info)) {
1177 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
1178 if (((usecase_backend_idx == HEADPHONE_BACKEND) ||
1179 (usecase_backend_idx == HEADPHONE_44_1_BACKEND)) &&
1180 ((usecase->stream.out->sample_rate % OUTPUT_SAMPLING_RATE_44100) == 0)) {
1181 usecase->stream.out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1182 platform_check_and_set_codec_backend_cfg(adev, usecase,
1183 usecase->out_snd_device);
1184 }
1185 }
Saurav Kumarc1411662020-10-14 10:50:45 +05301186 }
1187 }
1188}
1189
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301190/*
1191 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
1192 * 44.1 or Native DSD backends are enabled for any of current use case.
1193 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
1194 * - Disable current mix path use case(Headphone backend) and re-enable it with
1195 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
1196 * e.g. Naitve DSD or Headphone 44.1 -> + 48
1197 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301198static void check_and_set_asrc_mode(struct audio_device *adev,
1199 struct audio_usecase *uc_info,
1200 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301201{
1202 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301203 int i, num_new_devices = 0;
1204 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
1205 /*
1206 *Split snd device for new combo use case
1207 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
1208 */
1209 if (platform_split_snd_device(adev->platform,
1210 snd_device,
1211 &num_new_devices,
1212 split_new_snd_devices) == 0) {
1213 for (i = 0; i < num_new_devices; i++)
1214 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
1215 } else {
1216 int new_backend_idx = platform_get_backend_index(snd_device);
1217 if (((new_backend_idx == HEADPHONE_BACKEND) ||
1218 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
1219 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
1220 !adev->asrc_mode_enabled) {
1221 struct listnode *node = NULL;
1222 struct audio_usecase *uc = NULL;
1223 struct stream_out *curr_out = NULL;
1224 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
1225 int i, num_devices, ret = 0;
1226 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301227
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301228 list_for_each(node, &adev->usecase_list) {
1229 uc = node_to_item(node, struct audio_usecase, list);
1230 curr_out = (struct stream_out*) uc->stream.out;
1231 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
1232 /*
1233 *Split snd device for existing combo use case
1234 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
1235 */
1236 ret = platform_split_snd_device(adev->platform,
1237 uc->out_snd_device,
1238 &num_devices,
1239 split_snd_devices);
1240 if (ret < 0 || num_devices == 0) {
1241 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
1242 split_snd_devices[0] = uc->out_snd_device;
1243 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -08001244 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301245 for (i = 0; i < num_devices; i++) {
1246 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
1247 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
1248 if((new_backend_idx == HEADPHONE_BACKEND) &&
1249 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
1250 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07001251 ALOGV("%s:DSD or native stream detected enabling asrcmode in hardware",
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301252 __func__);
1253 enable_asrc_mode(adev);
1254 break;
1255 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
1256 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
1257 (usecase_backend_idx == HEADPHONE_BACKEND)) {
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07001258 ALOGV("%s: 48K stream detected, disabling and enabling it \
1259 with asrcmode in hardware", __func__);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301260 disable_audio_route(adev, uc);
1261 disable_snd_device(adev, uc->out_snd_device);
1262 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
1263 if (new_backend_idx == DSD_NATIVE_BACKEND)
1264 audio_route_apply_and_update_path(adev->audio_route,
1265 "hph-true-highquality-mode");
1266 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
1267 (curr_out->bit_width >= 24))
1268 audio_route_apply_and_update_path(adev->audio_route,
1269 "hph-highquality-mode");
1270 enable_asrc_mode(adev);
1271 enable_snd_device(adev, uc->out_snd_device);
1272 enable_audio_route(adev, uc);
1273 break;
1274 }
1275 }
1276 // reset split devices count
1277 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -08001278 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301279 if (adev->asrc_mode_enabled)
1280 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301281 }
1282 }
1283 }
1284}
1285
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001286static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
1287 struct audio_effect_config effect_config,
1288 unsigned int param_value)
1289{
1290 char mixer_ctl_name[] = "Audio Effect";
1291 struct mixer_ctl *ctl;
1292 long set_values[6];
Eric Laurent637e2d42018-11-15 12:24:31 -08001293 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001294
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001295 if (in == NULL) {
1296 ALOGE("%s: active input stream is NULL", __func__);
1297 return -EINVAL;
1298 }
1299
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001300 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1301 if (!ctl) {
1302 ALOGE("%s: Could not get mixer ctl - %s",
1303 __func__, mixer_ctl_name);
1304 return -EINVAL;
1305 }
1306
1307 set_values[0] = 1; //0:Rx 1:Tx
1308 set_values[1] = in->app_type_cfg.app_type;
1309 set_values[2] = (long)effect_config.module_id;
1310 set_values[3] = (long)effect_config.instance_id;
1311 set_values[4] = (long)effect_config.param_id;
1312 set_values[5] = param_value;
1313
1314 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
1315
1316 return 0;
1317
1318}
1319
1320static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
1321 int effect_type, unsigned int *param_value)
1322{
1323 int ret = 0;
1324 struct audio_effect_config other_effect_config;
1325 struct audio_usecase *usecase = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08001326 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001327
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001328 if (in == NULL) {
1329 ALOGE("%s: active input stream is NULL", __func__);
1330 return -EINVAL;
1331 }
1332
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001333 usecase = get_usecase_from_list(adev, in->usecase);
1334 if (!usecase)
1335 return -EINVAL;
1336
1337 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
1338 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
1339 if (ret < 0) {
1340 ALOGE("%s Failed to get effect params %d", __func__, ret);
1341 return ret;
1342 }
1343
1344 if (module_id == other_effect_config.module_id) {
1345 //Same module id for AEC/NS. Values need to be combined
1346 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
1347 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
1348 *param_value |= other_effect_config.param_value;
1349 }
1350 }
1351
1352 return ret;
1353}
1354
1355static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
Gangadhar Sb0210342019-02-22 17:39:41 +05301356{
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001357 struct audio_effect_config effect_config;
1358 struct audio_usecase *usecase = NULL;
1359 int ret = 0;
1360 unsigned int param_value = 0;
Eric Laurent637e2d42018-11-15 12:24:31 -08001361 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001362
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001363 if(!voice_extn_is_dynamic_ecns_enabled())
1364 return ENOSYS;
1365
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001366 if (!in) {
1367 ALOGE("%s: Invalid input stream", __func__);
1368 return -EINVAL;
1369 }
1370
1371 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
1372
1373 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +08001374 if (usecase == NULL) {
1375 ALOGE("%s: Could not find the usecase (%d) in the list",
1376 __func__, in->usecase);
1377 return -EINVAL;
1378 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001379
1380 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
1381 if (ret < 0) {
1382 ALOGE("%s Failed to get module id %d", __func__, ret);
1383 return ret;
1384 }
1385 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
1386 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
1387
1388 if(enable)
1389 param_value = effect_config.param_value;
1390
1391 /*Special handling for AEC & NS effects Param values need to be
1392 updated if module ids are same*/
1393
1394 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
1395 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
1396 if (ret < 0)
1397 return ret;
1398 }
1399
1400 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
1401
1402 return ret;
1403}
1404
1405static void check_and_enable_effect(struct audio_device *adev)
1406{
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001407 if(!voice_extn_is_dynamic_ecns_enabled())
1408 return;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001409
Eric Laurent637e2d42018-11-15 12:24:31 -08001410 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001411
Eric Laurent637e2d42018-11-15 12:24:31 -08001412 if (in != NULL && !in->standby) {
1413 if (in->enable_aec)
1414 enable_disable_effect(adev, EFFECT_AEC, true);
1415
1416 if (in->enable_ns &&
1417 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1418 enable_disable_effect(adev, EFFECT_NS, true);
1419 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001420 }
1421}
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001422
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001423int pcm_ioctl(struct pcm *pcm, int request, ...)
1424{
1425 va_list ap;
1426 void * arg;
1427 int pcm_fd = *(int*)pcm;
1428
1429 va_start(ap, request);
1430 arg = va_arg(ap, void *);
1431 va_end(ap);
1432
1433 return ioctl(pcm_fd, request, arg);
1434}
1435
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001436int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001437 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001438{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001439 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001440 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +05301441 struct stream_out *out = NULL;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301442 struct stream_in *in = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001443 struct listnode out_devices;
Soumya Managoli6993b762018-06-28 16:04:57 +05301444 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001445
1446 if (usecase == NULL)
1447 return -EINVAL;
1448
1449 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
1450
Carter Hsu2e429db2019-05-14 18:50:52 +08001451 if (usecase->type == PCM_CAPTURE) {
1452 struct stream_in *in = usecase->stream.in;
1453 struct audio_usecase *uinfo;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001454 snd_device = usecase->in_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001455
1456 if (in) {
1457 if (in->enable_aec || in->enable_ec_port) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001458 list_init(&out_devices);
1459 update_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "", true);
Carter Hsu2e429db2019-05-14 18:50:52 +08001460 struct listnode *node;
1461 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1462 USECASE_AUDIO_PLAYBACK_VOIP);
1463 if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001464 assign_devices(&out_devices,
1465 &voip_usecase->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001466 } else if (adev->primary_output &&
1467 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001468 assign_devices(&out_devices,
1469 &adev->primary_output->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001470 } else {
1471 list_for_each(node, &adev->usecase_list) {
1472 uinfo = node_to_item(node, struct audio_usecase, list);
1473 if (uinfo->type != PCM_CAPTURE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001474 assign_devices(&out_devices,
1475 &uinfo->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001476 break;
1477 }
1478 }
1479 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001480
1481 platform_set_echo_reference(adev, true, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001482 in->ec_opened = true;
Zhenlin Lian4f947842022-05-14 15:50:52 +05301483 clear_devices(&out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001484 }
1485 }
Guodong Huf5e614d2019-06-24 18:42:03 +08001486 } else if ((usecase->type == TRANSCODE_LOOPBACK_TX) || ((usecase->type == PCM_HFP_CALL) &&
1487 ((usecase->id == USECASE_AUDIO_HFP_SCO) || (usecase->id == USECASE_AUDIO_HFP_SCO_WB)) &&
1488 (usecase->in_snd_device == SND_DEVICE_IN_VOICE_SPEAKER_MIC_HFP_MMSECNS))) {
Carter Hsu2e429db2019-05-14 18:50:52 +08001489 snd_device = usecase->in_snd_device;
1490 } else {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001491 snd_device = usecase->out_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001492 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001493
Kunlei Zhanga3c4cb02021-03-05 16:03:54 +08001494 if (usecase->type == PCM_CAPTURE) {
1495 if (platform_get_fluence_nn_state(adev->platform) == 0) {
1496 platform_set_fluence_nn_state(adev->platform, true);
1497 ALOGD("%s: set fluence nn capture state", __func__);
1498 }
1499 }
1500
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001501#ifdef DS1_DOLBY_DAP_ENABLED
1502 audio_extn_dolby_set_dmid(adev);
1503 audio_extn_dolby_set_endpoint(adev);
1504#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001505 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001506 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301507 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001508 audio_extn_utils_send_app_type_cfg(adev, usecase);
Jasmine Cha4dcc1092019-03-04 18:12:47 +08001509 if (audio_extn_is_maxx_audio_enabled())
1510 audio_extn_ma_set_device(usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301511 audio_extn_utils_send_audio_calibration(adev, usecase);
Zhou Songbaddf9f2020-11-20 13:57:39 +08001512 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1513 out = usecase->stream.out;
1514 if (out && out->compr)
Manish Dewangan58229382017-02-02 15:48:41 +05301515 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1516 }
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301517
1518 if (usecase->type == PCM_CAPTURE) {
Kunlei Zhanga3c4cb02021-03-05 16:03:54 +08001519 if (platform_get_fluence_nn_state(adev->platform) == 1 &&
1520 adev->fluence_nn_usecase_id == USECASE_INVALID ) {
1521 adev->fluence_nn_usecase_id = usecase->id;
1522 ALOGD("%s: assign fluence nn usecase %d", __func__, usecase->id);
1523 }
1524 }
1525
1526 if (usecase->type == PCM_CAPTURE) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301527 in = usecase->stream.in;
Avinash Chandrad7296d42021-08-04 15:07:47 +05301528 if ((in && is_loopback_input_device(get_device_types(&in->device_list))) ||
1529 (in && is_combo_audio_input_device(&in->device_list)) ||
1530 (in && ((compare_device_type(&in->device_list, AUDIO_DEVICE_IN_BUILTIN_MIC) ||
1531 compare_device_type(&in->device_list, AUDIO_DEVICE_IN_LINE)) &&
1532 (snd_device == SND_DEVICE_IN_HANDSET_GENERIC_6MIC)))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301533 ALOGD("%s: set custom mtmx params v1", __func__);
1534 audio_extn_set_custom_mtmx_params_v1(adev, usecase, true);
1535 }
1536 } else {
1537 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
1538 }
Manish Dewangan58229382017-02-02 15:48:41 +05301539
Andy Hung756ecc12018-10-19 17:47:12 -07001540 // we shouldn't truncate mixer_path
1541 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1542 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1543 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001544 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001545 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301546 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1547 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1548 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1549 if (parms) {
1550 audio_extn_fm_set_parameters(adev, parms);
1551 str_parms_destroy(parms);
1552 }
1553 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001554 ALOGV("%s: exit", __func__);
1555 return 0;
1556}
1557
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001558int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001559 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001560{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001561 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001562 char mixer_path[MIXER_PATH_MAX_LENGTH];
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301563 struct stream_in *in = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001564
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301565 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001566 return -EINVAL;
1567
1568 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301569 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001570 snd_device = usecase->in_snd_device;
1571 else
1572 snd_device = usecase->out_snd_device;
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001573
1574 /* disable island and power mode on supported device for voice call */
1575 if (usecase->type == VOICE_CALL) {
1576 if (usecase->in_snd_device != SND_DEVICE_NONE) {
1577 if (platform_get_island_cfg_on_device(adev->platform, usecase->in_snd_device) &&
1578 platform_get_power_mode_on_device(adev->platform, usecase->in_snd_device)) {
1579 platform_set_island_cfg_on_device(adev, usecase->in_snd_device, false);
1580 platform_set_power_mode_on_device(adev, usecase->in_snd_device, false);
1581 platform_reset_island_power_status(adev->platform, usecase->in_snd_device);
Kunlei Zhang91c4b332020-07-20 17:53:14 +08001582 if (voice_is_lte_call_active(adev))
1583 platform_set_tx_lpi_mode(adev->platform, false);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001584 ALOGD("%s: disable island cfg and power mode in voice tx path",
1585 __func__);
1586 }
1587 }
1588 if (usecase->out_snd_device != SND_DEVICE_NONE) {
1589 if (platform_get_island_cfg_on_device(adev->platform, usecase->out_snd_device) &&
1590 platform_get_power_mode_on_device(adev->platform, usecase->out_snd_device)) {
1591 platform_set_island_cfg_on_device(adev, usecase->out_snd_device, false);
1592 platform_set_power_mode_on_device(adev, usecase->out_snd_device, false);
1593 platform_reset_island_power_status(adev->platform, usecase->out_snd_device);
1594 ALOGD("%s: disable island cfg and power mode in voice rx path",
1595 __func__);
1596 }
1597 }
1598 }
1599
Andy Hung756ecc12018-10-19 17:47:12 -07001600 // we shouldn't truncate mixer_path
1601 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1602 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1603 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001604 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001605 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001606 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Carter Hsu2e429db2019-05-14 18:50:52 +08001607 if (usecase->type == PCM_CAPTURE) {
1608 struct stream_in *in = usecase->stream.in;
1609 if (in && in->ec_opened) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001610 struct listnode out_devices;
1611 list_init(&out_devices);
1612 platform_set_echo_reference(in->dev, false, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001613 in->ec_opened = false;
Zhenlin Lian4f947842022-05-14 15:50:52 +05301614 clear_devices(&out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001615 }
1616 }
Kunlei Zhanga3c4cb02021-03-05 16:03:54 +08001617 if (usecase->id == adev->fluence_nn_usecase_id) {
1618 platform_set_fluence_nn_state(adev->platform, false);
1619 adev->fluence_nn_usecase_id = USECASE_INVALID;
1620 ALOGD("%s: reset fluence nn capture state", __func__);
1621 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001622 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301623 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301624
1625 if (usecase->type == PCM_CAPTURE) {
1626 in = usecase->stream.in;
Avinash Chandrad7296d42021-08-04 15:07:47 +05301627 if ((in && is_loopback_input_device(get_device_types(&in->device_list))) ||
1628 (in && is_combo_audio_input_device(&in->device_list)) ||
1629 (in && ((compare_device_type(&in->device_list, AUDIO_DEVICE_IN_BUILTIN_MIC) ||
1630 compare_device_type(&in->device_list, AUDIO_DEVICE_IN_LINE)) &&
1631 (snd_device == SND_DEVICE_IN_HANDSET_GENERIC_6MIC)))){
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301632 ALOGD("%s: reset custom mtmx params v1", __func__);
1633 audio_extn_set_custom_mtmx_params_v1(adev, usecase, false);
1634 }
1635 } else {
1636 audio_extn_set_custom_mtmx_params_v2(adev, usecase, false);
1637 }
1638
Weiyin Jiang298ffd92019-06-03 14:29:30 +08001639 if ((usecase->type == PCM_PLAYBACK) &&
1640 (usecase->stream.out != NULL))
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05301641 usecase->stream.out->pspd_coeff_sent = false;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301642
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001643 ALOGV("%s: exit", __func__);
1644 return 0;
1645}
1646
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001647int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001648 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001649{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301650 int i, num_devices = 0;
1651 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001652 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1653
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001654 if (snd_device < SND_DEVICE_MIN ||
1655 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001656 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001657 return -EINVAL;
1658 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001659
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001660 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001661 ALOGE("%s: Invalid sound device returned", __func__);
1662 return -EINVAL;
1663 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001664
1665 adev->snd_dev_ref_cnt[snd_device]++;
1666
1667 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1668 (platform_split_snd_device(adev->platform,
1669 snd_device,
1670 &num_devices,
1671 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001672 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001673 __func__, snd_device, device_name);
Aniket Kumar Lata990de552019-07-11 14:20:23 -07001674 /* Set backend config for A2DP to ensure slimbus configuration
1675 is correct if A2DP is already active and backend is closed
1676 and re-opened */
1677 if (snd_device == SND_DEVICE_OUT_BT_A2DP)
1678 audio_extn_a2dp_set_source_backend_cfg();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001679 return 0;
1680 }
1681
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001682 if (audio_extn_spkr_prot_is_enabled())
1683 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001684
Aalique Grahame22e49102018-12-18 14:23:57 -08001685 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1686
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001687 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1688 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001689 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1690 goto err;
1691 }
1692 audio_extn_dev_arbi_acquire(snd_device);
1693 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001694 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001695 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001696 goto err;
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001697 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001698 } else if (platform_split_snd_device(adev->platform,
1699 snd_device,
1700 &num_devices,
1701 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301702 for (i = 0; i < num_devices; i++) {
1703 enable_snd_device(adev, new_snd_devices[i]);
1704 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001705 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001706 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001707 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301708
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001709 /* enable island and power mode on supported device */
1710 if (platform_get_island_cfg_on_device(adev->platform, snd_device) &&
1711 platform_get_power_mode_on_device(adev->platform, snd_device)) {
1712 platform_set_island_cfg_on_device(adev, snd_device, true);
1713 platform_set_power_mode_on_device(adev, snd_device, true);
Kunlei Zhang91c4b332020-07-20 17:53:14 +08001714 if (voice_is_lte_call_active(adev) &&
1715 (snd_device >= SND_DEVICE_IN_BEGIN &&
1716 snd_device < SND_DEVICE_IN_END))
1717 platform_set_tx_lpi_mode(adev->platform, true);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001718 ALOGD("%s: enable island cfg and power mode on: %s",
1719 __func__, device_name);
1720 }
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301721
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301722 if (SND_DEVICE_OUT_BT_A2DP == snd_device) {
Ramjee Singh2d2944a2021-12-14 14:13:41 +05301723
1724 struct audio_usecase *usecase;
1725 struct listnode *node;
1726 /* Disable SCO Devices and enable handset mic for active input stream */
1727 list_for_each(node, &adev->usecase_list) {
1728 usecase = node_to_item(node, struct audio_usecase, list);
1729 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
1730 is_sco_in_device_type(&usecase->stream.in->device_list)) {
1731 ALOGD("a2dp resumed, switch bt sco mic to handset mic");
1732 reassign_device_list(&usecase->stream.in->device_list,
1733 AUDIO_DEVICE_IN_BUILTIN_MIC, "");
1734 select_devices(adev, usecase->id);
1735 }
1736 }
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301737 if (audio_extn_a2dp_start_playback() < 0) {
1738 ALOGE(" fail to configure A2dp Source control path ");
1739 goto err;
1740 } else {
1741 adev->a2dp_started = true;
1742 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001743 }
Florian Pfister1a84f312018-07-19 14:38:18 +02001744
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001745 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1746 (audio_extn_a2dp_start_capture() < 0)) {
1747 ALOGE(" fail to configure A2dp Sink control path ");
1748 goto err;
1749 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301750
Mingshu Pang7be5b1d2020-03-04 15:24:38 +08001751 if ((SND_DEVICE_OUT_BT_SCO_SWB == snd_device) ||
1752 (SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC == snd_device) ||
1753 (SND_DEVICE_IN_BT_SCO_MIC_SWB == snd_device)) {
1754 if (!adev->bt_sco_on || (audio_extn_sco_start_configuration() < 0)) {
1755 ALOGE(" fail to configure sco control path ");
1756 goto err;
1757 }
Zhou Song12c29502019-03-16 10:37:18 +08001758 }
1759
Zhou Song331c8e52019-08-26 14:16:12 +08001760 configure_btsco_sample_rate(snd_device);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001761 /* due to the possibility of calibration overwrite between listen
1762 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001763 audio_extn_sound_trigger_update_device_status(snd_device,
1764 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301765 audio_extn_listen_update_device_status(snd_device,
1766 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001767 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001768 audio_extn_sound_trigger_update_device_status(snd_device,
1769 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301770 audio_extn_listen_update_device_status(snd_device,
1771 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001772 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001773 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001774 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001775 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301776
1777 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1778 !adev->native_playback_enabled &&
1779 audio_is_true_native_stream_active(adev)) {
1780 ALOGD("%s: %d: napb: enabling native mode in hardware",
1781 __func__, __LINE__);
1782 audio_route_apply_and_update_path(adev->audio_route,
1783 "true-native-mode");
1784 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301785 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301786 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1787 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001788 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001789 ALOGD("%s: init ec ref loopback", __func__);
1790 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1791 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001792 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001793 return 0;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001794err:
1795 adev->snd_dev_ref_cnt[snd_device]--;
1796 return -EINVAL;;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001797}
1798
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001799int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001800 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001801{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301802 int i, num_devices = 0;
1803 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001804 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1805
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001806 if (snd_device < SND_DEVICE_MIN ||
1807 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001808 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001809 return -EINVAL;
1810 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001811
1812 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1813 ALOGE("%s: Invalid sound device returned", __func__);
1814 return -EINVAL;
1815 }
1816
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001817 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1818 ALOGE("%s: device ref cnt is already 0", __func__);
1819 return -EINVAL;
1820 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001821
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001822 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001823
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001824
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001825 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001826 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301827
Aalique Grahame22e49102018-12-18 14:23:57 -08001828 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1829
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001830 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1831 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001832 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001833
1834 // when speaker device is disabled, reset swap.
1835 // will be renabled on usecase start
1836 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001837 } else if (platform_split_snd_device(adev->platform,
1838 snd_device,
1839 &num_devices,
1840 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301841 for (i = 0; i < num_devices; i++) {
1842 disable_snd_device(adev, new_snd_devices[i]);
1843 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001844 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001845 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001846 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001847 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001848
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301849 if (snd_device == SND_DEVICE_OUT_BT_A2DP) {
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301850 audio_extn_a2dp_stop_playback();
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301851 adev->a2dp_started = false;
1852 } else if (snd_device == SND_DEVICE_IN_BT_A2DP)
Florian Pfister1a84f312018-07-19 14:38:18 +02001853 audio_extn_a2dp_stop_capture();
Zhou Songd6d71752019-05-21 18:08:51 +08001854 else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001855 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
Ashish Jain81eb2a82015-05-13 10:52:34 +05301856 adev->is_channel_status_set = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001857 else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301858 adev->native_playback_enabled) {
1859 ALOGD("%s: %d: napb: disabling native mode in hardware",
1860 __func__, __LINE__);
1861 audio_route_reset_and_update_path(adev->audio_route,
1862 "true-native-mode");
1863 adev->native_playback_enabled = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001864 } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301865 adev->asrc_mode_enabled) {
1866 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301867 disable_asrc_mode(adev);
1868 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001869 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301870 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001871 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001872 ALOGD("%s: deinit ec ref loopback", __func__);
1873 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1874 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001875
1876 audio_extn_utils_release_snd_device(snd_device);
1877 } else {
1878 if (platform_split_snd_device(adev->platform,
1879 snd_device,
1880 &num_devices,
1881 new_snd_devices) == 0) {
1882 for (i = 0; i < num_devices; i++) {
1883 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1884 }
1885 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001886 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001887
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001888 return 0;
1889}
1890
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001891/*
1892 legend:
1893 uc - existing usecase
1894 new_uc - new usecase
1895 d1, d11, d2 - SND_DEVICE enums
1896 a1, a2 - corresponding ANDROID device enums
1897 B1, B2 - backend strings
1898
1899case 1
1900 uc->dev d1 (a1) B1
1901 new_uc->dev d1 (a1), d2 (a2) B1, B2
1902
1903 resolution: disable and enable uc->dev on d1
1904
1905case 2
1906 uc->dev d1 (a1) B1
1907 new_uc->dev d11 (a1) B1
1908
1909 resolution: need to switch uc since d1 and d11 are related
1910 (e.g. speaker and voice-speaker)
1911 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1912
1913case 3
1914 uc->dev d1 (a1) B1
1915 new_uc->dev d2 (a2) B2
1916
1917 resolution: no need to switch uc
1918
1919case 4
1920 uc->dev d1 (a1) B1
1921 new_uc->dev d2 (a2) B1
1922
1923 resolution: disable enable uc-dev on d2 since backends match
1924 we cannot enable two streams on two different devices if they
1925 share the same backend. e.g. if offload is on speaker device using
1926 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1927 using the same backend, offload must also be switched to voice-handset.
1928
1929case 5
1930 uc->dev d1 (a1) B1
1931 new_uc->dev d1 (a1), d2 (a2) B1
1932
1933 resolution: disable enable uc-dev on d2 since backends match
1934 we cannot enable two streams on two different devices if they
1935 share the same backend.
1936
1937case 6
1938 uc->dev d1 (a1) B1
1939 new_uc->dev d2 (a1) B2
1940
1941 resolution: no need to switch
1942
1943case 7
1944 uc->dev d1 (a1), d2 (a2) B1, B2
1945 new_uc->dev d1 (a1) B1
1946
1947 resolution: no need to switch
1948
Zhou Song4ba65882018-07-09 14:48:07 +08001949case 8
1950 uc->dev d1 (a1) B1
1951 new_uc->dev d11 (a1), d2 (a2) B1, B2
1952 resolution: compared to case 1, for this case, d1 and d11 are related
1953 then need to do the same as case 2 to siwtch to new uc
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301954
1955case 9
1956 uc->dev d1 (a1), d2(a2) B1 B2
1957 new_uc->dev d1 (a1), d22 (a2) B1, B2
1958 resolution: disable enable uc-dev on d2 since backends match
1959 we cannot enable two streams on two different devices if they
1960 share the same backend. This is special case for combo use case
1961 with a2dp and sco devices which uses same backend.
1962 e.g. speaker-a2dp and speaker-btsco
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001963*/
1964static snd_device_t derive_playback_snd_device(void * platform,
1965 struct audio_usecase *uc,
1966 struct audio_usecase *new_uc,
1967 snd_device_t new_snd_device)
1968{
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001969 struct listnode a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001970
1971 snd_device_t d1 = uc->out_snd_device;
1972 snd_device_t d2 = new_snd_device;
Sandhya Mutha Naga Venkataa597a962023-02-07 11:35:51 +05301973 int ret = 0;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001974
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001975 list_init(&a1);
1976 list_init(&a2);
1977
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301978 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301979 case TRANSCODE_LOOPBACK_RX :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001980 assign_devices(&a1, &uc->stream.inout->out_config.device_list);
1981 assign_devices(&a2, &new_uc->stream.inout->out_config.device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301982 break;
1983 default :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001984 assign_devices(&a1, &uc->stream.out->device_list);
1985 assign_devices(&a2, &new_uc->stream.out->device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301986 break;
1987 }
1988
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001989 // Treat as a special case when a1 and a2 are not disjoint
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001990 if (!compare_devices(&a1, &a2) &&
1991 compare_devices_for_any_match(&a1 ,&a2)) {
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001992 snd_device_t d3[2];
1993 int num_devices = 0;
Sandhya Mutha Naga Venkataa597a962023-02-07 11:35:51 +05301994 ret = platform_split_snd_device(platform,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001995 list_length(&a1) > 1 ? d1 : d2,
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001996 &num_devices,
1997 d3);
1998 if (ret < 0) {
1999 if (ret != -ENOSYS) {
2000 ALOGW("%s failed to split snd_device %d",
2001 __func__,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002002 list_length(&a1) > 1 ? d1 : d2);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07002003 }
Sandhya Mutha Naga Venkata4c6fc9f2022-10-14 19:38:02 +05302004 ret = d2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07002005 goto end;
2006 }
2007
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07002008 if (platform_check_backends_match(d3[0], d3[1])) {
Sandhya Mutha Naga Venkata4c6fc9f2022-10-14 19:38:02 +05302009 ret = d2;
2010 goto end; // case 5
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07002011 } else {
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05302012 if ((list_length(&a1) > 1) && (list_length(&a2) > 1) &&
Sandhya Mutha Naga Venkata4c6fc9f2022-10-14 19:38:02 +05302013 platform_check_backends_match(d1, d2)) {
2014 ret = d2;
2015 goto end; //case 9
2016 }
2017 if (list_length(&a1) > 1) {
2018 ret = d1;
2019 goto end; //case 7
2020 }
Garmond Leungb9eeba42018-09-18 11:10:41 -07002021 // check if d1 is related to any of d3's
Sandhya Mutha Naga Venkata4c6fc9f2022-10-14 19:38:02 +05302022 if (d1 == d3[0] || d1 == d3[1]) {
2023 ret = d1;
2024 goto end; // case 1
2025 } else {
2026 ret = d3[1];
2027 goto end; // case 8
2028 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07002029 }
2030 } else {
2031 if (platform_check_backends_match(d1, d2)) {
Sandhya Mutha Naga Venkata4c6fc9f2022-10-14 19:38:02 +05302032 ret = d2;
2033 goto end; // case 2, 4
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07002034 } else {
Sandhya Mutha Naga Venkata4c6fc9f2022-10-14 19:38:02 +05302035 ret = d1;
2036 goto end; // case 6, 3
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07002037 }
2038 }
2039
2040end:
Sandhya Mutha Naga Venkata4c6fc9f2022-10-14 19:38:02 +05302041 clear_devices(&a1);
2042 clear_devices(&a2);
2043 return ret; // return whatever was calculated before.
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07002044}
2045
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002046static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05302047 struct audio_usecase *uc_info,
2048 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002049{
2050 struct listnode *node;
2051 struct audio_usecase *usecase;
2052 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05302053 snd_device_t uc_derive_snd_device;
2054 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08002055 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
2056 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08002057 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302058 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002059 /*
2060 * This function is to make sure that all the usecases that are active on
2061 * the hardware codec backend are always routed to any one device that is
2062 * handled by the hardware codec.
2063 * For example, if low-latency and deep-buffer usecases are currently active
2064 * on speaker and out_set_parameters(headset) is received on low-latency
2065 * output, then we have to make sure deep-buffer is also switched to headset,
2066 * because of the limitation that both the devices cannot be enabled
2067 * at the same time as they share the same backend.
2068 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07002069 /*
2070 * This call is to check if we need to force routing for a particular stream
2071 * If there is a backend configuration change for the device when a
2072 * new stream starts, then ADM needs to be closed and re-opened with the new
2073 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08002074 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07002075 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08002076 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
2077 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302078 /* For a2dp device reconfigure all active sessions
2079 * with new AFE encoder format based on a2dp state
2080 */
2081 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05302082 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device ||
2083 SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP == snd_device) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302084 audio_extn_a2dp_is_force_device_switch()) {
2085 force_routing = true;
2086 force_restart_session = true;
2087 }
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08002088
2089 /*
2090 * Island cfg and power mode config needs to set before AFE port start.
2091 * Set force routing in case of voice device was enable before.
2092 */
2093 if (uc_info->type == VOICE_CALL &&
2094 voice_extn_is_voice_power_mode_supported() &&
Kunlei Zhang67cc7072020-12-18 17:16:49 +08002095 is_supported_conc_usecase_for_power_mode_call(adev) &&
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08002096 platform_check_and_update_island_power_status(adev->platform,
2097 uc_info,
2098 snd_device)) {
2099 force_routing = true;
2100 ALOGD("%s:becf: force routing %d for power mode supported device",
2101 __func__, force_routing);
2102 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302103 ALOGD("%s:becf: force routing %d", __func__, force_routing);
2104
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002105 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002106 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002107 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002108 for (i = 0; i < AUDIO_USECASE_MAX; i++)
2109 switch_device[i] = false;
2110
2111 list_for_each(node, &adev->usecase_list) {
2112 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08002113
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05302114 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
2115 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302116 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05302117 platform_get_snd_device_name(usecase->out_snd_device),
2118 platform_check_backends_match(snd_device, usecase->out_snd_device));
Rahul Sharma99770982019-03-06 17:05:26 +05302119 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
2120 (usecase->type != PCM_PASSTHROUGH)) {
Ashish Jain6a65b352017-03-21 17:24:40 +05302121 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
2122 usecase, uc_info, snd_device);
2123 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002124 (is_codec_backend_out_device_type(&usecase->device_list) ||
2125 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
2126 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_DEVICE) ||
2127 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_HEADSET) ||
2128 is_a2dp_out_device_type(&usecase->device_list) ||
2129 is_sco_out_device_type(&usecase->device_list)) &&
Ashish Jain6a65b352017-03-21 17:24:40 +05302130 ((force_restart_session) ||
2131 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05302132 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
2133 __func__, use_case_table[usecase->id],
2134 platform_get_snd_device_name(usecase->out_snd_device));
2135 disable_audio_route(adev, usecase);
2136 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05302137 /* Enable existing usecase on derived playback device */
2138 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05302139 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05302140 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002141 }
2142 }
2143
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302144 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
2145 num_uc_to_switch);
2146
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002147 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07002148 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002149
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05302150 /* Make sure the previous devices to be disabled first and then enable the
2151 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002152 list_for_each(node, &adev->usecase_list) {
2153 usecase = node_to_item(node, struct audio_usecase, list);
2154 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08002155 /* Check if output sound device to be switched can be split and if any
2156 of the split devices match with derived sound device */
2157 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
2158 &num_devices, split_snd_devices) == 0) {
2159 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
2160 for (i = 0; i < num_devices; i++) {
2161 /* Disable devices that do not match with derived sound device */
2162 if (split_snd_devices[i] != derive_snd_device[usecase->id])
2163 disable_snd_device(adev, split_snd_devices[i]);
2164 }
2165 } else {
2166 disable_snd_device(adev, usecase->out_snd_device);
2167 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002168 }
2169 }
2170
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07002171 list_for_each(node, &adev->usecase_list) {
2172 usecase = node_to_item(node, struct audio_usecase, list);
2173 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08002174 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
2175 &num_devices, split_snd_devices) == 0) {
2176 /* Enable derived sound device only if it does not match with
2177 one of the split sound devices. This is because the matching
2178 sound device was not disabled */
2179 bool should_enable = true;
2180 for (i = 0; i < num_devices; i++) {
2181 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
2182 should_enable = false;
2183 break;
2184 }
2185 }
2186 if (should_enable)
2187 enable_snd_device(adev, derive_snd_device[usecase->id]);
2188 } else {
2189 enable_snd_device(adev, derive_snd_device[usecase->id]);
2190 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07002191 }
2192 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002193
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002194 /* Re-route all the usecases on the shared backend other than the
2195 specified usecase to new snd devices */
2196 list_for_each(node, &adev->usecase_list) {
2197 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05302198 /* Update the out_snd_device only before enabling the audio route */
2199 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05302200 usecase->out_snd_device = derive_snd_device[usecase->id];
Lakshman Chaluvarajuab7e5572020-10-28 19:29:23 +05302201 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
2202 use_case_table[usecase->id],
2203 platform_get_snd_device_name(usecase->out_snd_device));
2204 /* Update voc calibration before enabling Voice/VoIP route */
2205 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL)
2206 status = platform_switch_voice_call_device_post(adev->platform,
2207 usecase->out_snd_device,
2208 platform_get_input_snd_device(
2209 adev->platform, NULL,
2210 &uc_info->device_list,
2211 usecase->type));
2212 enable_audio_route(adev, usecase);
2213 if (usecase->stream.out && usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
2214 out_set_voip_volume(&usecase->stream.out->stream,
2215 usecase->stream.out->volume_l,
2216 usecase->stream.out->volume_r);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05302217 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002218 }
2219 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002220 }
2221}
2222
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302223static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002224 struct audio_usecase *uc_info,
2225 snd_device_t snd_device)
2226{
2227 struct listnode *node;
2228 struct audio_usecase *usecase;
2229 bool switch_device[AUDIO_USECASE_MAX];
2230 int i, num_uc_to_switch = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002231 int backend_check_cond = is_codec_backend_out_device_type(&uc_info->device_list);
kunleiz5cd52b82016-11-07 17:22:52 +08002232 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002233
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302234 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
2235 snd_device);
2236 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05302237
2238 /*
2239 * Make sure out devices is checked against out codec backend device and
2240 * also in devices against in codec backend. Checking out device against in
2241 * codec backend or vice versa causes issues.
2242 */
2243 if (uc_info->type == PCM_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002244 backend_check_cond = is_codec_backend_in_device_type(&uc_info->device_list);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08002245
2246 /*
2247 * Island cfg and power mode config needs to set before AFE port start.
2248 * Set force routing in case of voice device was enable before.
2249 */
2250
2251 if (uc_info->type == VOICE_CALL &&
2252 voice_extn_is_voice_power_mode_supported() &&
Kunlei Zhang67cc7072020-12-18 17:16:49 +08002253 is_supported_conc_usecase_for_power_mode_call(adev) &&
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08002254 platform_check_and_update_island_power_status(adev->platform,
2255 uc_info,
2256 snd_device)) {
2257 force_routing = true;
2258 ALOGD("%s:becf: force routing %d for power mode supported device",
2259 __func__, force_routing);
2260 }
2261
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002262 /*
2263 * This function is to make sure that all the active capture usecases
2264 * are always routed to the same input sound device.
2265 * For example, if audio-record and voice-call usecases are currently
2266 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
2267 * is received for voice call then we have to make sure that audio-record
2268 * usecase is also switched to earpiece i.e. voice-dmic-ef,
2269 * because of the limitation that two devices cannot be enabled
2270 * at the same time if they share the same backend.
2271 */
2272 for (i = 0; i < AUDIO_USECASE_MAX; i++)
2273 switch_device[i] = false;
2274
2275 list_for_each(node, &adev->usecase_list) {
2276 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05302277 /*
2278 * TODO: Enhance below condition to handle BT sco/USB multi recording
2279 */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302280
2281 bool capture_uc_needs_routing = usecase->type != PCM_PLAYBACK && (usecase != uc_info &&
2282 (usecase->in_snd_device != snd_device || force_routing));
2283 bool call_proxy_snd_device = platform_is_call_proxy_snd_device(snd_device) ||
2284 platform_is_call_proxy_snd_device(usecase->in_snd_device);
2285 if (capture_uc_needs_routing && !call_proxy_snd_device &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002286 ((backend_check_cond &&
2287 (is_codec_backend_in_device_type(&usecase->device_list) ||
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08002288 (usecase->type == VOIP_CALL))) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08002289 ((uc_info->type == VOICE_CALL &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002290 is_single_device_type_equal(&usecase->device_list,
2291 AUDIO_DEVICE_IN_VOICE_CALL)) ||
Anver sadhique4fdc6992022-01-21 12:26:28 +05302292 platform_check_all_backends_match(snd_device,\
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002293 usecase->in_snd_device))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07002294 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05302295 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..",
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002296 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07002297 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002298 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002299 switch_device[usecase->id] = true;
2300 num_uc_to_switch++;
2301 }
2302 }
2303
2304 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07002305 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002306
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05302307 /* Make sure the previous devices to be disabled first and then enable the
2308 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002309 list_for_each(node, &adev->usecase_list) {
2310 usecase = node_to_item(node, struct audio_usecase, list);
2311 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002312 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08002313 }
2314 }
2315
2316 list_for_each(node, &adev->usecase_list) {
2317 usecase = node_to_item(node, struct audio_usecase, list);
2318 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002319 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002320 }
2321 }
2322
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002323 /* Re-route all the usecases on the shared backend other than the
2324 specified usecase to new snd devices */
2325 list_for_each(node, &adev->usecase_list) {
2326 usecase = node_to_item(node, struct audio_usecase, list);
2327 /* Update the in_snd_device only before enabling the audio route */
2328 if (switch_device[usecase->id] ) {
2329 usecase->in_snd_device = snd_device;
Lakshman Chaluvarajuab7e5572020-10-28 19:29:23 +05302330 /* Update voc calibration before enabling Voice/VoIP route */
2331 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
2332 snd_device_t voip_snd_device;
2333 voip_snd_device = platform_get_output_snd_device(adev->platform,
2334 usecase->stream.out,
2335 usecase->type);
2336 status = platform_switch_voice_call_device_post(adev->platform,
2337 voip_snd_device,
2338 usecase->in_snd_device);
kunleiz5cd52b82016-11-07 17:22:52 +08002339 }
Lakshman Chaluvarajuab7e5572020-10-28 19:29:23 +05302340 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002341 }
2342 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002343 }
2344}
2345
Mingming Yin3a941d42016-02-17 18:08:05 -08002346static void reset_hdmi_sink_caps(struct stream_out *out) {
2347 int i = 0;
2348
2349 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
2350 out->supported_channel_masks[i] = 0;
2351 }
2352 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
2353 out->supported_formats[i] = 0;
2354 }
2355 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
2356 out->supported_sample_rates[i] = 0;
2357 }
2358}
2359
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002360/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08002361static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002362{
Mingming Yin3a941d42016-02-17 18:08:05 -08002363 int ret = 0, i = 0, j = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002364 int channels = platform_edid_get_max_channels_v2(out->dev->platform,
2365 out->extconn.cs.controller,
2366 out->extconn.cs.stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002367
Mingming Yin3a941d42016-02-17 18:08:05 -08002368 reset_hdmi_sink_caps(out);
2369
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002370 /* Cache ext disp type */
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002371 ret = platform_get_ext_disp_type_v2(adev->platform,
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002372 out->extconn.cs.controller,
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002373 out->extconn.cs.stream);
2374 if(ret < 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002375 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07002376 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002377 }
2378
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002379 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002380 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08002381 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002382 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08002383 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
2384 case 6:
2385 ALOGV("%s: HDMI supports 5.1 channels", __func__);
2386 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
2387 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
2388 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
2389 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
2390 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002391 break;
2392 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08002393 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002394 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002395 break;
2396 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002397
2398 // check channel format caps
2399 i = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002400 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_AC3,
2401 out->extconn.cs.controller,
2402 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002403 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
2404 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
2405 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
2406 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
2407 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
2408 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
2409 }
2410
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002411 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD,
2412 out->extconn.cs.controller,
2413 out->extconn.cs.stream)) {
Ben Romberger1aaaf862017-04-06 17:49:46 -07002414 ALOGV(":%s HDMI supports TRUE HD format", __func__);
2415 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
2416 }
2417
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002418 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS,
2419 out->extconn.cs.controller,
2420 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002421 ALOGV(":%s HDMI supports DTS format", __func__);
2422 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
2423 }
2424
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002425 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS_HD,
2426 out->extconn.cs.controller,
2427 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002428 ALOGV(":%s HDMI supports DTS HD format", __func__);
2429 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
2430 }
2431
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002432 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_IEC61937,
2433 out->extconn.cs.controller,
2434 out->extconn.cs.stream)) {
Naresh Tanniru928f0862017-04-07 16:44:23 -07002435 ALOGV(":%s HDMI supports IEC61937 format", __func__);
2436 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
2437 }
2438
Mingming Yin3a941d42016-02-17 18:08:05 -08002439
2440 // check sample rate caps
2441 i = 0;
2442 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002443 if (platform_is_edid_supported_sample_rate_v2(out->dev->platform, out_hdmi_sample_rates[j],
2444 out->extconn.cs.controller,
2445 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002446 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
2447 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
2448 }
2449 }
2450
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002451 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002452}
2453
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002454static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
2455 uint32_t *supported_sample_rates __unused,
2456 uint32_t max_rates __unused)
2457{
2458 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
2459 supported_sample_rates,
2460 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05302461 ssize_t i = 0;
2462
2463 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002464 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
2465 supported_sample_rates[i]);
2466 }
2467 return count;
2468}
2469
2470static inline int read_usb_sup_channel_masks(bool is_playback,
2471 audio_channel_mask_t *supported_channel_masks,
2472 uint32_t max_masks)
2473{
2474 int channels = audio_extn_usb_get_max_channels(is_playback);
2475 int channel_count;
2476 uint32_t num_masks = 0;
2477 if (channels > MAX_HIFI_CHANNEL_COUNT)
2478 channels = MAX_HIFI_CHANNEL_COUNT;
2479
2480 if (is_playback) {
Eric Laurent68a87112019-05-01 18:07:29 -07002481 // start from 2 channels as framework currently doesn't support mono.
2482 if (channels >= FCC_2) {
2483 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(FCC_2);
2484 }
2485 for (channel_count = FCC_2;
2486 channel_count <= channels && num_masks < max_masks;
2487 ++channel_count) {
2488 supported_channel_masks[num_masks++] =
2489 audio_channel_mask_for_index_assignment_from_count(channel_count);
2490 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002491 } else {
vincenttewf51c94e2019-05-07 10:28:53 +08002492 // For capture we report all supported channel masks from 1 channel up.
2493 channel_count = MIN_CHANNEL_COUNT;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002494 // audio_channel_in_mask_from_count() does the right conversion to either positional or
2495 // indexed mask
Eric Laurent68a87112019-05-01 18:07:29 -07002496 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
2497 audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
2498 if (channel_count <= FCC_2) {
2499 mask = audio_channel_in_mask_from_count(channel_count);
2500 supported_channel_masks[num_masks++] = mask;
2501 }
2502 const audio_channel_mask_t index_mask =
2503 audio_channel_mask_for_index_assignment_from_count(channel_count);
2504 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
2505 supported_channel_masks[num_masks++] = index_mask;
2506 }
2507 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002508 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302509
vincenttewf51c94e2019-05-07 10:28:53 +08002510 for (size_t i = 0; i < num_masks; ++i) {
2511 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
2512 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302513 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002514 return num_masks;
2515}
2516
2517static inline int read_usb_sup_formats(bool is_playback __unused,
2518 audio_format_t *supported_formats,
2519 uint32_t max_formats __unused)
2520{
2521 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
2522 switch (bitwidth) {
2523 case 24:
2524 // XXX : usb.c returns 24 for s24 and s24_le?
2525 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
2526 break;
2527 case 32:
2528 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
2529 break;
2530 case 16:
2531 default :
2532 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
2533 break;
2534 }
2535 ALOGV("%s: %s supported format %d", __func__,
2536 is_playback ? "P" : "C", bitwidth);
2537 return 1;
2538}
2539
2540static inline int read_usb_sup_params_and_compare(bool is_playback,
2541 audio_format_t *format,
2542 audio_format_t *supported_formats,
2543 uint32_t max_formats,
2544 audio_channel_mask_t *mask,
2545 audio_channel_mask_t *supported_channel_masks,
2546 uint32_t max_masks,
2547 uint32_t *rate,
2548 uint32_t *supported_sample_rates,
2549 uint32_t max_rates) {
2550 int ret = 0;
2551 int num_formats;
2552 int num_masks;
2553 int num_rates;
2554 int i;
2555
2556 num_formats = read_usb_sup_formats(is_playback, supported_formats,
2557 max_formats);
2558 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
2559 max_masks);
2560
2561 num_rates = read_usb_sup_sample_rates(is_playback,
2562 supported_sample_rates, max_rates);
2563
2564#define LUT(table, len, what, dflt) \
2565 for (i=0; i<len && (table[i] != what); i++); \
2566 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
2567
2568 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
2569 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
2570 LUT(supported_sample_rates, num_rates, *rate, 0);
2571
2572#undef LUT
2573 return ret < 0 ? -EINVAL : 0; // HACK TBD
2574}
2575
Alexy Josephb1379942016-01-29 15:49:38 -08002576audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002577 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002578{
2579 struct audio_usecase *usecase;
2580 struct listnode *node;
2581
2582 list_for_each(node, &adev->usecase_list) {
2583 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002584 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002585 ALOGV("%s: usecase id %d", __func__, usecase->id);
2586 return usecase->id;
2587 }
2588 }
2589 return USECASE_INVALID;
2590}
2591
Alexy Josephb1379942016-01-29 15:49:38 -08002592struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002593 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002594{
2595 struct audio_usecase *usecase;
2596 struct listnode *node;
2597
2598 list_for_each(node, &adev->usecase_list) {
2599 usecase = node_to_item(node, struct audio_usecase, list);
2600 if (usecase->id == uc_id)
2601 return usecase;
2602 }
2603 return NULL;
2604}
2605
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302606/*
2607 * is a true native playback active
2608 */
2609bool audio_is_true_native_stream_active(struct audio_device *adev)
2610{
2611 bool active = false;
2612 int i = 0;
2613 struct listnode *node;
2614
2615 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
2616 ALOGV("%s:napb: not in true mode or non hdphones device",
2617 __func__);
2618 active = false;
2619 goto exit;
2620 }
2621
2622 list_for_each(node, &adev->usecase_list) {
2623 struct audio_usecase *uc;
2624 uc = node_to_item(node, struct audio_usecase, list);
2625 struct stream_out *curr_out =
2626 (struct stream_out*) uc->stream.out;
2627
2628 if (curr_out && PCM_PLAYBACK == uc->type) {
2629 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
2630 "(%d) device %s", __func__, i++, use_case_table[uc->id],
2631 uc->id, curr_out->sample_rate,
2632 curr_out->bit_width,
2633 platform_get_snd_device_name(uc->out_snd_device));
2634
2635 if (is_offload_usecase(uc->id) &&
2636 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
2637 active = true;
2638 ALOGD("%s:napb:native stream detected", __func__);
2639 }
2640 }
2641 }
2642exit:
2643 return active;
2644}
2645
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002646uint32_t adev_get_dsp_bit_width_enforce_mode()
2647{
2648 if (adev == NULL) {
2649 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
2650 return 0;
2651 }
2652 return adev->dsp_bit_width_enforce_mode;
2653}
2654
2655static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
2656{
2657 char value[PROPERTY_VALUE_MAX];
2658 int trial;
2659 uint32_t dsp_bit_width_enforce_mode = 0;
2660
2661 if (!mixer) {
2662 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
2663 __func__);
2664 return 0;
2665 }
2666
2667 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
2668 value, NULL) > 0) {
2669 trial = atoi(value);
2670 switch (trial) {
2671 case 16:
2672 dsp_bit_width_enforce_mode = 16;
2673 break;
2674 case 24:
2675 dsp_bit_width_enforce_mode = 24;
2676 break;
2677 case 32:
2678 dsp_bit_width_enforce_mode = 32;
2679 break;
2680 default:
2681 dsp_bit_width_enforce_mode = 0;
2682 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
2683 break;
2684 }
2685 }
2686
2687 return dsp_bit_width_enforce_mode;
2688}
2689
2690static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
2691 uint32_t enforce_mode,
2692 bool enable)
2693{
2694 struct mixer_ctl *ctl = NULL;
2695 const char *mixer_ctl_name = "ASM Bit Width";
2696 uint32_t asm_bit_width_mode = 0;
2697
2698 if (enforce_mode == 0) {
2699 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
2700 return;
2701 }
2702
2703 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
2704 if (!ctl) {
2705 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2706 __func__, mixer_ctl_name);
2707 return;
2708 }
2709
2710 if (enable)
2711 asm_bit_width_mode = enforce_mode;
2712 else
2713 asm_bit_width_mode = 0;
2714
2715 ALOGV("%s DSP bit width feature status is %d width=%d",
2716 __func__, enable, asm_bit_width_mode);
2717 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2718 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2719 asm_bit_width_mode);
2720
2721 return;
2722}
2723
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302724/*
2725 * if native DSD playback active
2726 */
2727bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2728{
2729 bool active = false;
2730 struct listnode *node = NULL;
2731 struct audio_usecase *uc = NULL;
2732 struct stream_out *curr_out = NULL;
2733
2734 list_for_each(node, &adev->usecase_list) {
2735 uc = node_to_item(node, struct audio_usecase, list);
2736 curr_out = (struct stream_out*) uc->stream.out;
2737
2738 if (curr_out && PCM_PLAYBACK == uc->type &&
2739 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2740 active = true;
2741 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302742 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302743 }
2744 }
2745 return active;
2746}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302747
2748static bool force_device_switch(struct audio_usecase *usecase)
2749{
2750 bool ret = false;
2751 bool is_it_true_mode = false;
2752
Zhou Song30f2c3e2018-02-08 14:02:15 +08002753 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302754 usecase->type == TRANSCODE_LOOPBACK_RX ||
2755 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002756 return false;
2757 }
2758
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002759 if(usecase->stream.out == NULL) {
2760 ALOGE("%s: stream.out is NULL", __func__);
2761 return false;
2762 }
2763
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302764 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002765 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002766 (compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADSET) ||
2767 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADPHONE))) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302768 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2769 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2770 (!is_it_true_mode && adev->native_playback_enabled)){
2771 ret = true;
2772 ALOGD("napb: time to toggle native mode");
2773 }
2774 }
2775
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302776 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302777 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2778 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002779 if(is_a2dp_out_device_type(&usecase->stream.out->device_list) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302780 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302781 ALOGD("Force a2dp device switch to update new encoder config");
2782 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002783 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302784
Florian Pfister1a84f312018-07-19 14:38:18 +02002785 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302786 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2787 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002788 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302789 return ret;
2790}
2791
Aalique Grahame22e49102018-12-18 14:23:57 -08002792static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2793{
2794 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2795}
2796
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302797bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2798{
2799 bool ret=false;
2800 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
Zhou Song5657f492019-08-07 11:30:39 +08002801 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
2802 out_snd_device == SND_DEVICE_OUT_BT_SCO_SWB) ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302803 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2804 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
Zhou Song5657f492019-08-07 11:30:39 +08002805 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302806 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
Mingshu Pang16093502020-04-20 11:21:16 +08002807 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC ||
2808 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC)
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302809 ret = true;
2810
2811 return ret;
2812}
2813
2814bool is_a2dp_device(snd_device_t out_snd_device)
2815{
2816 bool ret=false;
2817 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2818 ret = true;
2819
2820 return ret;
2821}
2822
2823bool is_bt_soc_on(struct audio_device *adev)
2824{
2825 struct mixer_ctl *ctl;
2826 char *mixer_ctl_name = "BT SOC status";
2827 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2828 bool bt_soc_status = true;
2829 if (!ctl) {
2830 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2831 __func__, mixer_ctl_name);
2832 /*This is to ensure we dont break targets which dont have the kernel change*/
2833 return true;
2834 }
2835 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2836 ALOGD("BT SOC status: %d",bt_soc_status);
2837 return bt_soc_status;
2838}
2839
Zhou Song331c8e52019-08-26 14:16:12 +08002840static int configure_btsco_sample_rate(snd_device_t snd_device)
2841{
2842 struct mixer_ctl *ctl = NULL;
2843 struct mixer_ctl *ctl_sr_rx = NULL, *ctl_sr_tx = NULL, *ctl_sr = NULL;
2844 char *rate_str = NULL;
2845 bool is_rx_dev = true;
2846
2847 if (is_btsco_device(snd_device, snd_device)) {
2848 ctl_sr_tx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate TX");
2849 ctl_sr_rx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate RX");
2850 if (!ctl_sr_tx || !ctl_sr_rx) {
2851 ctl_sr = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate");
2852 if (!ctl_sr)
2853 return -ENOSYS;
2854 }
2855
2856 switch (snd_device) {
2857 case SND_DEVICE_OUT_BT_SCO:
2858 rate_str = "KHZ_8";
2859 break;
2860 case SND_DEVICE_IN_BT_SCO_MIC_NREC:
2861 case SND_DEVICE_IN_BT_SCO_MIC:
2862 rate_str = "KHZ_8";
2863 is_rx_dev = false;
2864 break;
2865 case SND_DEVICE_OUT_BT_SCO_WB:
2866 rate_str = "KHZ_16";
2867 break;
2868 case SND_DEVICE_IN_BT_SCO_MIC_WB_NREC:
2869 case SND_DEVICE_IN_BT_SCO_MIC_WB:
2870 rate_str = "KHZ_16";
2871 is_rx_dev = false;
2872 break;
2873 default:
2874 return 0;
2875 }
2876
2877 ctl = (ctl_sr == NULL) ? (is_rx_dev ? ctl_sr_rx : ctl_sr_tx) : ctl_sr;
2878 if (mixer_ctl_set_enum_by_string(ctl, rate_str) != 0)
2879 return -ENOSYS;
2880 }
2881 return 0;
2882}
2883
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302884int out_standby_l(struct audio_stream *stream);
2885
Eric Laurent637e2d42018-11-15 12:24:31 -08002886struct stream_in *adev_get_active_input(const struct audio_device *adev)
2887{
2888 struct listnode *node;
2889 struct stream_in *last_active_in = NULL;
2890
2891 /* Get last added active input.
2892 * TODO: We may use a priority mechanism to pick highest priority active source */
2893 list_for_each(node, &adev->usecase_list)
2894 {
2895 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2896 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL)
2897 last_active_in = usecase->stream.in;
2898 }
2899
2900 return last_active_in;
2901}
2902
2903struct stream_in *get_voice_communication_input(const struct audio_device *adev)
2904{
2905 struct listnode *node;
2906
2907 /* First check active inputs with voice communication source and then
2908 * any input if audio mode is in communication */
2909 list_for_each(node, &adev->usecase_list)
2910 {
2911 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2912 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
2913 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
2914 return usecase->stream.in;
2915 }
2916 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION)
2917 return adev_get_active_input(adev);
2918
2919 return NULL;
2920}
2921
Carter Hsu2e429db2019-05-14 18:50:52 +08002922/*
2923 * Aligned with policy.h
2924 */
2925static inline int source_priority(int inputSource)
2926{
2927 switch (inputSource) {
2928 case AUDIO_SOURCE_VOICE_COMMUNICATION:
2929 return 9;
2930 case AUDIO_SOURCE_CAMCORDER:
2931 return 8;
2932 case AUDIO_SOURCE_VOICE_PERFORMANCE:
2933 return 7;
2934 case AUDIO_SOURCE_UNPROCESSED:
2935 return 6;
2936 case AUDIO_SOURCE_MIC:
2937 return 5;
2938 case AUDIO_SOURCE_ECHO_REFERENCE:
2939 return 4;
2940 case AUDIO_SOURCE_FM_TUNER:
2941 return 3;
2942 case AUDIO_SOURCE_VOICE_RECOGNITION:
2943 return 2;
2944 case AUDIO_SOURCE_HOTWORD:
2945 return 1;
2946 default:
2947 break;
2948 }
2949 return 0;
2950}
2951
2952static struct stream_in *get_priority_input(struct audio_device *adev)
2953{
2954 struct listnode *node;
2955 struct audio_usecase *usecase;
2956 int last_priority = 0, priority;
2957 struct stream_in *priority_in = NULL;
2958 struct stream_in *in;
2959
2960 list_for_each(node, &adev->usecase_list) {
2961 usecase = node_to_item(node, struct audio_usecase, list);
2962 if (usecase->type == PCM_CAPTURE) {
2963 in = usecase->stream.in;
2964 if (!in)
2965 continue;
Krishna Kishor Jha0b7175d2022-07-28 22:33:46 +05302966
2967 if (USECASE_AUDIO_RECORD_FM_VIRTUAL == usecase->id)
2968 continue;
Krishna Kishor Jhaaf83fd82022-11-15 17:54:07 +05302969#ifdef SKIP_INPUT_SOURCE_PRIORITY
2970 // temporary fix to resolve issue when accessing Google Assistant while FM is active.
2971 if (USECASE_AUDIO_RECORD_ECHO_REF_EXT == usecase->id) {
2972 continue;
2973 }
2974#endif
Carter Hsu2e429db2019-05-14 18:50:52 +08002975 priority = source_priority(in->source);
2976
2977 if (priority > last_priority) {
2978 last_priority = priority;
2979 priority_in = in;
2980 }
2981 }
2982 }
2983 return priority_in;
2984}
2985
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002986int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002987{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002988 snd_device_t out_snd_device = SND_DEVICE_NONE;
2989 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002990 struct audio_usecase *usecase = NULL;
2991 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002992 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002993 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302994 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002995 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002996 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002997
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302998 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2999
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003000 usecase = get_usecase_from_list(adev, uc_id);
3001 if (usecase == NULL) {
3002 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
3003 return -EINVAL;
3004 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003005
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003006 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08003007 (usecase->type == VOIP_CALL) ||
Derek Chena30a5f42019-12-03 11:17:09 -05003008 (usecase->type == PCM_HFP_CALL)||
Fei Tongaffdf732020-02-20 20:39:05 +08003009 (usecase->type == ICC_CALL) ||
3010 (usecase->type == SYNTH_LOOPBACK)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05303011 if(usecase->stream.out == NULL) {
3012 ALOGE("%s: stream.out is NULL", __func__);
3013 return -EINVAL;
3014 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003015 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS)) {
Guodong Hu267bdf82019-08-12 19:22:32 +08003016 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev,
3017 uc_id);
3018 in_snd_device = audio_extn_auto_hal_get_input_snd_device(adev,
3019 uc_id);
3020 } else {
3021 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05303022 usecase->stream.out, usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08003023 in_snd_device = platform_get_input_snd_device(adev->platform,
3024 NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05303025 &usecase->stream.out->device_list,
3026 usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08003027 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003028 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05303029 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05303030 if (usecase->stream.inout == NULL) {
3031 ALOGE("%s: stream.inout is NULL", __func__);
3032 return -EINVAL;
3033 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003034 assign_devices(&stream_out.device_list, &usecase->stream.inout->out_config.device_list);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05303035 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
3036 stream_out.format = usecase->stream.inout->out_config.format;
3037 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
Jaideep Sharma477917f2020-03-13 18:13:33 +05303038 out_snd_device = platform_get_output_snd_device(adev->platform, &stream_out, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003039 assign_devices(&usecase->device_list,
3040 &usecase->stream.inout->out_config.device_list);
Zhenlin Lian4f947842022-05-14 15:50:52 +05303041 clear_devices(&stream_out.device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05303042 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
3043 if (usecase->stream.inout == NULL) {
3044 ALOGE("%s: stream.inout is NULL", __func__);
3045 return -EINVAL;
3046 }
Manisha Agarwal03297972020-04-17 15:36:55 +05303047 struct listnode out_devices;
3048 list_init(&out_devices);
3049 in_snd_device = platform_get_input_snd_device(adev->platform, NULL,
3050 &out_devices, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003051 assign_devices(&usecase->device_list,
3052 &usecase->stream.inout->in_config.device_list);
Zhenlin Lian4f947842022-05-14 15:50:52 +05303053 clear_devices(&out_devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003054 } else {
3055 /*
3056 * If the voice call is active, use the sound devices of voice call usecase
3057 * so that it would not result any device switch. All the usecases will
3058 * be switched to new device when select_devices() is called for voice call
3059 * usecase. This is to avoid switching devices for voice call when
3060 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07003061 * choose voice call device only if the use case device is
3062 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003063 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08003064 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003065 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08003066 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003067 if ((vc_usecase) && ((is_codec_backend_out_device_type(&vc_usecase->device_list) &&
3068 is_codec_backend_out_device_type(&usecase->device_list)) ||
3069 (is_codec_backend_out_device_type(&vc_usecase->device_list) &&
3070 is_codec_backend_in_device_type(&usecase->device_list)) ||
3071 is_single_device_type_equal(&vc_usecase->device_list,
3072 AUDIO_DEVICE_OUT_HEARING_AID) ||
3073 is_single_device_type_equal(&usecase->device_list,
Robert Lee8a6aaf32019-09-20 16:40:19 +08003074 AUDIO_DEVICE_IN_VOICE_CALL) ||
3075 (is_single_device_type_equal(&usecase->device_list,
Gautam Manam8fa06162021-09-24 10:41:29 +05303076 AUDIO_DEVICE_IN_BUILTIN_MIC) &&
3077 is_single_device_type_equal(&vc_usecase->device_list,
3078 AUDIO_DEVICE_OUT_USB_HEADSET)) ||
3079 (is_single_device_type_equal(&usecase->device_list,
Robert Lee8a6aaf32019-09-20 16:40:19 +08003080 AUDIO_DEVICE_IN_USB_HEADSET) &&
3081 is_single_device_type_equal(&vc_usecase->device_list,
Kamalakar Yalasiri5edba852021-01-28 14:52:38 +05303082 AUDIO_DEVICE_OUT_USB_HEADSET))||
Gautam Manamf4002142021-09-13 22:05:56 +05303083 (is_single_device_type_equal(&usecase->device_list,
3084 AUDIO_DEVICE_IN_USB_HEADSET) &&
3085 is_codec_backend_out_device_type(&vc_usecase->device_list)) ||
Kamalakar Yalasiri5edba852021-01-28 14:52:38 +05303086 (is_single_device_type_equal(&usecase->device_list,
3087 AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) &&
3088 is_codec_backend_out_device_type(&vc_usecase->device_list)))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003089 in_snd_device = vc_usecase->in_snd_device;
3090 out_snd_device = vc_usecase->out_snd_device;
3091 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003092 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08003093 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08003094 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08003095 if ((voip_usecase != NULL) &&
3096 (usecase->type == PCM_PLAYBACK) &&
3097 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08003098 out_snd_device_backend_match = platform_check_backends_match(
3099 voip_usecase->out_snd_device,
3100 platform_get_output_snd_device(
3101 adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05303102 usecase->stream.out, usecase->type));
yidongh02ef86f2017-04-21 15:36:04 +08003103 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003104 if ((voip_usecase) && (is_codec_backend_out_device_type(&voip_usecase->device_list) &&
3105 (is_codec_backend_out_device_type(&usecase->device_list) ||
3106 is_codec_backend_in_device_type(&usecase->device_list)) &&
yidongh02ef86f2017-04-21 15:36:04 +08003107 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07003108 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003109 in_snd_device = voip_usecase->in_snd_device;
3110 out_snd_device = voip_usecase->out_snd_device;
3111 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08003112 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08003113 hfp_ucid = audio_extn_hfp_get_usecase();
3114 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003115 if ((hfp_usecase) && is_codec_backend_out_device_type(&hfp_usecase->device_list)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08003116 in_snd_device = hfp_usecase->in_snd_device;
3117 out_snd_device = hfp_usecase->out_snd_device;
3118 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003119 }
3120 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05303121 if (usecase->stream.out == NULL) {
3122 ALOGE("%s: stream.out is NULL", __func__);
3123 return -EINVAL;
3124 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003125 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003126 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003127 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003128 struct stream_out *voip_out = adev->primary_output;
3129 struct stream_in *voip_in = get_voice_communication_input(adev);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003130 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS))
Guodong Hu267bdf82019-08-12 19:22:32 +08003131 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev, uc_id);
3132 else
3133 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05303134 usecase->stream.out,
3135 usecase->type);
kunleizdcf967a2018-08-07 17:09:11 +08003136 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizdcf967a2018-08-07 17:09:11 +08003137
Eric Laurent637e2d42018-11-15 12:24:31 -08003138 if (voip_usecase)
3139 voip_out = voip_usecase->stream.out;
3140
3141 if (usecase->stream.out == voip_out && voip_in != NULL)
3142 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003143 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003144 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05303145 if (usecase->stream.in == NULL) {
3146 ALOGE("%s: stream.in is NULL", __func__);
3147 return -EINVAL;
3148 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003149 assign_devices(&usecase->device_list, &usecase->stream.in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003150 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003151 if (in_snd_device == SND_DEVICE_NONE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003152 struct listnode out_devices;
Eric Laurent637e2d42018-11-15 12:24:31 -08003153 struct stream_in *voip_in = get_voice_communication_input(adev);
Carter Hsu2e429db2019-05-14 18:50:52 +08003154 struct stream_in *priority_in = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08003155
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003156 list_init(&out_devices);
Eric Laurent637e2d42018-11-15 12:24:31 -08003157 if (voip_in != NULL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003158 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
3159 USECASE_AUDIO_PLAYBACK_VOIP);
3160
Carter Hsu2e429db2019-05-14 18:50:52 +08003161 usecase->stream.in->enable_ec_port = false;
3162
Zhou Song503196b2021-07-23 17:31:05 +08003163 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY ||
3164 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY2) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003165 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_TELEPHONY_TX, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08003166 } else if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003167 assign_devices(&out_devices, &voip_usecase->stream.out->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08003168 } else if (adev->primary_output &&
3169 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003170 assign_devices(&out_devices, &adev->primary_output->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08003171 } else {
3172 /* forcing speaker o/p device to get matching i/p pair
3173 in case o/p is not routed from same primary HAL */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003174 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08003175 }
Carter Hsu2e429db2019-05-14 18:50:52 +08003176 priority_in = voip_in;
3177 } else {
Krishna Kishor Jhaaf83fd82022-11-15 17:54:07 +05303178#ifdef SKIP_INPUT_SOURCE_PRIORITY
Kogara Naveen Kumar912313f2022-11-23 09:38:28 +05303179 ALOGD("%s: Skipping get_priority_input for use-case-id:%d(%s).", __func__, uc_id, use_case_table[uc_id]);
Krishna Kishor Jhaaf83fd82022-11-15 17:54:07 +05303180#else
Carter Hsu2e429db2019-05-14 18:50:52 +08003181 priority_in = get_priority_input(adev);
Krishna Kishor Jhaaf83fd82022-11-15 17:54:07 +05303182#endif
Carter Hsu2e429db2019-05-14 18:50:52 +08003183
Susan Wang727dd6b2021-03-26 11:28:59 -04003184 if (!priority_in ||
3185 audio_extn_auto_hal_overwrite_priority_for_auto(usecase->stream.in))
Carter Hsu2e429db2019-05-14 18:50:52 +08003186 priority_in = usecase->stream.in;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003187 }
Huicheng Liu1404ba12020-09-11 01:03:25 -04003188 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_IN_BUS)){
3189 in_snd_device = audio_extn_auto_hal_get_snd_device_for_car_audio_stream(priority_in->car_audio_stream);
3190 }
3191 else
3192 in_snd_device = platform_get_input_snd_device(adev->platform,
3193 priority_in,
3194 &out_devices,
3195 usecase->type);
Zhenlin Lian4f947842022-05-14 15:50:52 +05303196 clear_devices(&out_devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003197 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003198 }
3199 }
3200
3201 if (out_snd_device == usecase->out_snd_device &&
3202 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05303203
3204 if (!force_device_switch(usecase))
3205 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003206 }
3207
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003208 if (!compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS) &&
Guodong Hu267bdf82019-08-12 19:22:32 +08003209 ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003210 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready()))) {
Guodong Hu267bdf82019-08-12 19:22:32 +08003211 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
3212 return 0;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303213 }
3214
Aalique Grahame22e49102018-12-18 14:23:57 -08003215 if (out_snd_device != SND_DEVICE_NONE &&
3216 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
3217 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
3218 __func__,
3219 use_case_table[uc_id],
3220 adev->last_logged_snd_device[uc_id][0],
3221 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
3222 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
3223 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
3224 -1,
3225 out_snd_device,
3226 platform_get_snd_device_name(out_snd_device),
3227 platform_get_snd_device_acdb_id(out_snd_device));
3228 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
3229 }
3230 if (in_snd_device != SND_DEVICE_NONE &&
3231 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
3232 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
3233 __func__,
3234 use_case_table[uc_id],
3235 adev->last_logged_snd_device[uc_id][1],
3236 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
3237 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
3238 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
3239 -1,
3240 in_snd_device,
3241 platform_get_snd_device_name(in_snd_device),
3242 platform_get_snd_device_acdb_id(in_snd_device));
3243 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
3244 }
3245
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003246
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003247 /*
3248 * Limitation: While in call, to do a device switch we need to disable
3249 * and enable both RX and TX devices though one of them is same as current
3250 * device.
3251 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07003252 if ((usecase->type == VOICE_CALL) &&
3253 (usecase->in_snd_device != SND_DEVICE_NONE) &&
3254 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07003255 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07003256 }
3257
3258 if (((usecase->type == VOICE_CALL) ||
3259 (usecase->type == VOIP_CALL)) &&
3260 (usecase->out_snd_device != SND_DEVICE_NONE)) {
3261 /* Disable sidetone only if voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303262 if (voice_is_call_state_active_in_call(adev) ||
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07003263 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07003264 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003265
3266 /* Disable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303267 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003268 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08003269 }
3270
Aalique Grahame22e49102018-12-18 14:23:57 -08003271 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
3272 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003273 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303274 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08003275 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
3276 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
3277 else
3278 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303279 }
3280
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003281 /* Disable current sound devices */
3282 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003283 disable_audio_route(adev, usecase);
3284 disable_snd_device(adev, usecase->out_snd_device);
Gautam Manam274f4752021-09-24 10:58:49 +05303285 if (usecase->id == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
3286 disable_snd_device(adev, SND_DEVICE_OUT_HAPTICS);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003287 }
3288
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003289 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003290 disable_audio_route(adev, usecase);
3291 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003292 }
3293
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08003294 /* Applicable only on the targets that has external modem.
3295 * New device information should be sent to modem before enabling
3296 * the devices to reduce in-call device switch time.
3297 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07003298 if ((usecase->type == VOICE_CALL) &&
3299 (usecase->in_snd_device != SND_DEVICE_NONE) &&
3300 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08003301 status = platform_switch_voice_call_enable_device_config(adev->platform,
3302 out_snd_device,
3303 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07003304 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08003305
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003306 /* Enable new sound devices */
3307 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08003308 check_usecases_codec_backend(adev, usecase, out_snd_device);
Saurav Kumarc1411662020-10-14 10:50:45 +05303309 check_and_configure_headphone(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05303310 if (platform_check_codec_asrc_support(adev->platform))
3311 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003312 enable_snd_device(adev, out_snd_device);
Zhou Songd9bd9302020-08-04 16:34:45 +08003313 /* Enable haptics device for haptic usecase */
3314 if (usecase->id == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
3315 enable_snd_device(adev, SND_DEVICE_OUT_HAPTICS);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003316 }
3317
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07003318 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303319 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003320 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07003321 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003322
Lakshman Chaluvarajuab7e5572020-10-28 19:29:23 +05303323 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL)
Eric Laurentb23d5282013-05-14 15:27:20 -07003324 status = platform_switch_voice_call_device_post(adev->platform,
3325 out_snd_device,
3326 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08003327
sangwoo170731f2013-06-08 15:36:36 +09003328 usecase->in_snd_device = in_snd_device;
3329 usecase->out_snd_device = out_snd_device;
3330
Dhananjay Kumard6d32152016-10-13 16:11:03 +05303331 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
3332 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05303333 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003334 if ((24 == usecase->stream.out->bit_width) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003335 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_SPEAKER)) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003336 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3337 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
3338 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
3339 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
3340 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
3341 /*
3342 * To best utlize DSP, check if the stream sample rate is supported/multiple of
3343 * configured device sample rate, if not update the COPP rate to be equal to the
3344 * device sample rate, else open COPP at stream sample rate
3345 */
3346 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
3347 usecase->stream.out->sample_rate,
3348 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05303349 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
Preetam Singh Ranawat590d0432019-09-30 14:39:47 +05303350 out_snd_device != SND_DEVICE_OUT_HEADPHONES &&
3351 out_snd_device != SND_DEVICE_OUT_HEADPHONES_HIFI_FILTER &&
Ashish Jain4826f6c2017-02-06 13:33:20 +05303352 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003353 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
3354 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +05303355#ifdef PLATFORM_AUTO
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +05303356 if (!(compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS) && ((usecase->stream.out->flags &
3357 (audio_output_flags_t)AUDIO_OUTPUT_FLAG_SYS_NOTIFICATION) || (usecase->stream.out->flags &
3358 (audio_output_flags_t)AUDIO_OUTPUT_FLAG_PHONE)))) {
3359 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3360 }
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +05303361#else
3362 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3363#endif
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003364 }
Weiyin Jiangcdece202019-07-08 16:13:16 +08003365 }
3366 enable_audio_route(adev, usecase);
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003367
Shalini Manjunatha5e610912020-12-29 13:02:25 +05303368 if (uc_id == USECASE_AUDIO_PLAYBACK_VOIP) {
3369 struct stream_in *voip_in = get_voice_communication_input(adev);
3370 struct audio_usecase *voip_in_usecase = NULL;
3371 voip_in_usecase = get_usecase_from_list(adev, USECASE_AUDIO_RECORD_VOIP);
3372 if (voip_in != NULL &&
3373 voip_in_usecase != NULL &&
3374 !(out_snd_device == AUDIO_DEVICE_OUT_SPEAKER ||
3375 out_snd_device == AUDIO_DEVICE_OUT_SPEAKER_SAFE) &&
3376 (voip_in_usecase->in_snd_device ==
3377 platform_get_input_snd_device(adev->platform, voip_in,
3378 &usecase->stream.out->device_list,usecase->type))) {
3379 /*
3380 * if VOIP TX is enabled before VOIP RX, needs to re-route the TX path
3381 * for enabling echo-reference-voip with correct port
3382 */
3383 ALOGD("%s: VOIP TX is enabled before VOIP RX,needs to re-route the TX path",__func__);
3384 disable_audio_route(adev, voip_in_usecase);
3385 disable_snd_device(adev, voip_in_usecase->in_snd_device);
3386 enable_snd_device(adev, voip_in_usecase->in_snd_device);
3387 enable_audio_route(adev, voip_in_usecase);
3388 }
3389 }
Ramjee Singhcdf67af2021-09-29 14:20:27 +05303390 if (voice_extn_compress_voip_is_active(adev)) {
3391 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
3392 USECASE_COMPRESS_VOIP_CALL);
3393 /*
3394 * If only compress voip input is opened voip out will be primary out.
3395 * Need to consider re-routing to select correct i/p pair
3396 */
3397 if ((voip_usecase != NULL) &&
3398 (usecase->type == PCM_PLAYBACK) &&
3399 (usecase->stream.out == voip_usecase->stream.out)) {
3400 in_snd_device = platform_get_input_snd_device(adev->platform,
3401 NULL,
3402 &usecase->stream.out->device_list,
3403 usecase->type);
3404 if (voip_usecase->in_snd_device != in_snd_device ) {
3405 ALOGD("%s:Re routing compress voip tx snd device matching voip rx pair",
3406 __func__);
3407 disable_audio_route(adev, voip_usecase);
3408 disable_snd_device(adev, voip_usecase->in_snd_device);
3409 voip_usecase->in_snd_device = in_snd_device;
3410 voip_usecase->out_snd_device = usecase->out_snd_device;
3411 /* Route all TX usecase to Compress voip BE */
3412 check_usecases_capture_codec_backend(adev, voip_usecase, in_snd_device);
3413 enable_snd_device(adev, in_snd_device);
3414 /* Send Voice related calibration for RX /TX pair */
3415 status = platform_switch_voice_call_device_post(adev->platform,
3416 out_snd_device,
3417 in_snd_device);
3418 enable_audio_route(adev, voip_usecase);
3419 }
3420 }
3421 }
Shalini Manjunatha5e610912020-12-29 13:02:25 +05303422
3423
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08003424 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08003425
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003426 /* If input stream is already running then effect needs to be
3427 applied on the new input device that's being enabled here. */
Eric Laurent637e2d42018-11-15 12:24:31 -08003428 if (in_snd_device != SND_DEVICE_NONE)
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003429 check_and_enable_effect(adev);
3430
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003431 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003432 /* Enable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303433 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003434 voice_check_and_update_aanc_path(adev, out_snd_device, true);
3435
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003436 /* Enable sidetone only if other voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303437 if (voice_is_call_state_active_in_call(adev) ||
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003438 voice_extn_compress_voip_is_started(adev))
3439 voice_set_sidetone(adev, out_snd_device, true);
3440 }
3441
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003442 /* Applicable only on the targets that has external modem.
3443 * Enable device command should be sent to modem only after
3444 * enabling voice call mixer controls
3445 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07003446 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003447 status = platform_switch_voice_call_usecase_route_post(adev->platform,
3448 out_snd_device,
3449 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303450
3451 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003452 struct stream_in *in = adev_get_active_input(adev);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303453 if (usecase->type == VOIP_CALL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003454 if (in != NULL && !in->standby) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303455 if (is_bt_soc_on(adev) == false){
3456 ALOGD("BT SCO MIC disconnected while in connection");
Eric Laurent637e2d42018-11-15 12:24:31 -08003457 if (in->pcm != NULL)
3458 pcm_stop(in->pcm);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303459 }
3460 }
3461 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
3462 && usecase->stream.out->started) {
3463 if (is_bt_soc_on(adev) == false) {
3464 ALOGD("BT SCO/A2DP disconnected while in connection");
3465 out_standby_l(&usecase->stream.out->stream.common);
3466 }
3467 }
3468 } else if ((usecase->stream.out != NULL) &&
3469 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05303470 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
3471 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Weiyin Jiang0d373242019-07-25 13:18:17 +08003472 (usecase->type != PCM_CAPTURE) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303473 usecase->stream.out->started) {
3474 if (is_bt_soc_on(adev) == false) {
3475 ALOGD("BT SCO/A2dp disconnected while in connection");
3476 out_standby_l(&usecase->stream.out->stream.common);
3477 }
3478 }
3479 }
3480
Yung Ti Su70cb8242018-06-22 17:38:47 +08003481 if (usecase->type != PCM_CAPTURE && usecase == voip_usecase) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003482 struct stream_out *voip_out = voip_usecase->stream.out;
3483 audio_extn_utils_send_app_type_gain(adev,
3484 voip_out->app_type_cfg.app_type,
3485 &voip_out->app_type_cfg.gain[0]);
3486 }
3487
Ajender Reddyb940b832021-07-07 11:51:42 +05303488 ALOGD("%s: done",__func__);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303489
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003490 return status;
3491}
3492
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003493static int stop_input_stream(struct stream_in *in)
3494{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303495 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003496 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05303497
3498 if (in == NULL) {
3499 ALOGE("%s: stream_in ptr is NULL", __func__);
3500 return -EINVAL;
3501 }
3502
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003503 struct audio_device *adev = in->dev;
Carter Hsu2e429db2019-05-14 18:50:52 +08003504 struct stream_in *priority_in = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003505
Eric Laurent994a6932013-07-17 11:51:42 -07003506 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003507 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003508 uc_info = get_usecase_from_list(adev, in->usecase);
3509 if (uc_info == NULL) {
3510 ALOGE("%s: Could not find the usecase (%d) in the list",
3511 __func__, in->usecase);
3512 return -EINVAL;
3513 }
Krishna Kishor Jhaaf83fd82022-11-15 17:54:07 +05303514#ifdef SKIP_INPUT_SOURCE_PRIORITY
3515 // Skip (1)fm-virtual-record and (2)echo-reference-external from get-priority-input logic.
3516 // See comment in function select_devices() before call to get_priority_input()
3517 if ((in->usecase == USECASE_AUDIO_RECORD_FM_VIRTUAL || in->usecase == USECASE_AUDIO_RECORD_ECHO_REF_EXT)){
3518 ALOGD("%s: Skipping get_priority_input for use-case-id:%d/%s.", __func__, in->usecase, use_case_table[in->usecase]);
3519 } else {
3520 priority_in = get_priority_input(adev);
3521 }
3522#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003523
Carter Hsu2e429db2019-05-14 18:50:52 +08003524 priority_in = get_priority_input(adev);
3525
Krishna Kishor Jhaaf83fd82022-11-15 17:54:07 +05303526#endif
3527
Derek Chenea197282019-01-07 17:35:01 -08003528 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3529 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003530
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003531 /* Close in-call recording streams */
3532 voice_check_and_stop_incall_rec_usecase(adev, in);
3533
Eric Laurent150dbfe2013-02-27 14:31:02 -08003534 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003535 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003536
3537 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003538 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003539
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003540 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303541 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_PRIMARY);
3542
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003543 list_remove(&uc_info->list);
Zhenlin Lian4f947842022-05-14 15:50:52 +05303544 clear_devices(&uc_info->device_list);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003545 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003546
Carter Hsu2e429db2019-05-14 18:50:52 +08003547 if (priority_in == in) {
3548 priority_in = get_priority_input(adev);
Sujin Panicker110f7942021-08-26 17:01:22 +05303549 if (priority_in) {
3550 if (is_usb_in_device_type(&priority_in->device_list)) {
3551 if (audio_extn_usb_connected(NULL))
3552 select_devices(adev, priority_in->usecase);
3553 } else {
3554 select_devices(adev, priority_in->usecase);
3555 }
3556 }
Carter Hsu2e429db2019-05-14 18:50:52 +08003557 }
3558
Vatsal Buchac09ae062018-11-14 13:25:08 +05303559 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07003560 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003561 return ret;
3562}
3563
3564int start_input_stream(struct stream_in *in)
3565{
3566 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08003567 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003568 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05303569
3570 if (in == NULL) {
3571 ALOGE("%s: stream_in ptr is NULL", __func__);
3572 return -EINVAL;
3573 }
3574
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003575 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07003576 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07003577 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003578
Mingming Yin2664a5b2015-09-03 10:53:11 -07003579 if (get_usecase_from_list(adev, usecase) == NULL)
3580 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303581 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
3582 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003583
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303584 if (CARD_STATUS_OFFLINE == in->card_status||
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05003585 CARD_STATUS_OFFLINE == adev->card_status ||
3586 POWER_POLICY_STATUS_OFFLINE == adev->in_power_policy) {
3587 ALOGW("in->card_status or adev->card_status or adev->input_power offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303588 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303589 goto error_config;
3590 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303591
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003592 if (is_sco_in_device_type(&in->device_list)) {
Lakshman Chaluvaraju87f53aa2021-02-02 15:50:11 +05303593 if (!adev->bt_sco_on || audio_extn_a2dp_source_is_ready()) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303594 ALOGE("%s: SCO profile is not ready, return error", __func__);
3595 ret = -EIO;
3596 goto error_config;
3597 }
3598 }
3599
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003600 /* Check if source matches incall recording usecase criteria */
3601 ret = voice_check_and_set_incall_rec_usecase(adev, in);
3602 if (ret)
3603 goto error_config;
3604 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07003605 ALOGV("%s: usecase(%d)", __func__, in->usecase);
3606
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303607 if (audio_extn_cin_attached_usecase(in))
3608 audio_extn_cin_acquire_usecase(in);
3609
Mingming Yin2664a5b2015-09-03 10:53:11 -07003610 if (get_usecase_from_list(adev, in->usecase) != NULL) {
3611 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
3612 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Weiyin Jiang38c0e612020-09-10 16:10:51 +08003613 ret = -EINVAL;
3614 goto error_config;
Mingming Yin2664a5b2015-09-03 10:53:11 -07003615 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003616
Eric Laurentb23d5282013-05-14 15:27:20 -07003617 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003618 if (in->pcm_device_id < 0) {
3619 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
3620 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08003621 ret = -EINVAL;
3622 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003623 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003624
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003625 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003626
3627 if (!uc_info) {
3628 ret = -ENOMEM;
3629 goto error_config;
3630 }
3631
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003632 uc_info->id = in->usecase;
3633 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003634 uc_info->stream.in = in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003635 list_init(&uc_info->device_list);
3636 assign_devices(&uc_info->device_list, &in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003637 uc_info->in_snd_device = SND_DEVICE_NONE;
3638 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003639
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003640 list_add_tail(&adev->usecase_list, &uc_info->list);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003641 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303642 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3643 adev->perf_lock_opts,
3644 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003645 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003646
Derek Chenea197282019-01-07 17:35:01 -08003647 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3648 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003649
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05303650 android_atomic_acquire_cas(true, false, &(in->capture_stopped));
3651
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303652 if (audio_extn_cin_attached_usecase(in)) {
Manish Dewangan46e07982018-12-13 18:18:59 +05303653 ret = audio_extn_cin_open_input_stream(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303654 if (ret)
3655 goto error_open;
3656 else
3657 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003658 }
3659
Haynes Mathew George16081042017-05-31 17:16:49 -07003660 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003661 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003662 ALOGE("%s: pcm stream not ready", __func__);
3663 goto error_open;
3664 }
3665 ret = pcm_start(in->pcm);
3666 if (ret < 0) {
3667 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3668 goto error_open;
3669 }
3670 } else {
3671 unsigned int flags = PCM_IN | PCM_MONOTONIC;
3672 unsigned int pcm_open_retry_count = 0;
3673
Zhou Song62ea0282020-03-22 19:53:01 +08003674 if ((in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) ||
3675 (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003676 flags |= PCM_MMAP | PCM_NOIRQ;
3677 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
3678 } else if (in->realtime) {
3679 flags |= PCM_MMAP | PCM_NOIRQ;
3680 }
3681
Garmond Leunge2433c32017-09-28 21:51:22 -07003682 if (audio_extn_ffv_get_stream() == in) {
3683 ALOGD("%s: ffv stream, update pcm config", __func__);
3684 audio_extn_ffv_update_pcm_config(&config);
3685 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003686 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3687 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3688
3689 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003690 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07003691 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07003692 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003693 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303694 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303695 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3696 adev->card_status = CARD_STATUS_OFFLINE;
3697 in->card_status = CARD_STATUS_OFFLINE;
3698 ret = -EIO;
3699 goto error_open;
3700 }
3701
Haynes Mathew George16081042017-05-31 17:16:49 -07003702 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3703 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3704 if (in->pcm != NULL) {
3705 pcm_close(in->pcm);
3706 in->pcm = NULL;
3707 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003708 if (pcm_open_retry_count == 0) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003709 ret = -EIO;
3710 goto error_open;
3711 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003712 pcm_open_retry_count--;
Haynes Mathew George16081042017-05-31 17:16:49 -07003713 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3714 continue;
3715 }
3716 break;
3717 }
3718
3719 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003720 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07003721 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003722 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003723 if (ret < 0) {
3724 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3725 pcm_close(in->pcm);
3726 in->pcm = NULL;
3727 goto error_open;
3728 }
Vaibhav Raut5f3bf222023-02-06 17:45:22 +05303729 if (in->flags & (AUDIO_INPUT_FLAG_FAST | AUDIO_INPUT_FLAG_RAW))
Narsinga Rao Chellaa6e1f702021-10-22 13:57:32 +05303730 register_in_stream(in);
Haynes Mathew George16081042017-05-31 17:16:49 -07003731 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003732 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07003733 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003734 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003735 if (ret < 0) {
3736 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003737 pcm_close(in->pcm);
3738 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003739 goto error_open;
3740 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003741 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003742 }
3743
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003744 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07003745 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
3746 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003747
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003748 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303749 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
3750
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303751done_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003752 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303753 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Manisha Agarwal4c2402e2020-10-21 12:02:57 +05303754 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303755 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003756 return ret;
3757
3758error_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003759 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303760 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003761 stop_input_stream(in);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003762
Eric Laurentc8400632013-02-14 19:04:54 -08003763error_config:
Weiyin Jiang38c0e612020-09-10 16:10:51 +08003764 if (audio_extn_cin_attached_usecase(in))
3765 audio_extn_cin_close_input_stream(in);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303766 /*
3767 * sleep 50ms to allow sufficient time for kernel
3768 * drivers to recover incases like SSR.
3769 */
3770 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003771 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303772 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003773 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003774}
3775
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003776void lock_input_stream(struct stream_in *in)
3777{
3778 pthread_mutex_lock(&in->pre_lock);
3779 pthread_mutex_lock(&in->lock);
3780 pthread_mutex_unlock(&in->pre_lock);
3781}
3782
3783void lock_output_stream(struct stream_out *out)
3784{
3785 pthread_mutex_lock(&out->pre_lock);
3786 pthread_mutex_lock(&out->lock);
3787 pthread_mutex_unlock(&out->pre_lock);
3788}
3789
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003790/* must be called with out->lock locked */
3791static int send_offload_cmd_l(struct stream_out* out, int command)
3792{
3793 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
3794
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003795 if (!cmd) {
3796 ALOGE("failed to allocate mem for command 0x%x", command);
3797 return -ENOMEM;
3798 }
3799
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003800 ALOGVV("%s %d", __func__, command);
3801
3802 cmd->cmd = command;
3803 list_add_tail(&out->offload_cmd_list, &cmd->node);
3804 pthread_cond_signal(&out->offload_cond);
3805 return 0;
3806}
3807
Gautam Manam14c198b2020-12-24 14:08:04 +05303808/* must be called with out->lock */
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003809static void stop_compressed_output_l(struct stream_out *out)
3810{
Gautam Manam14c198b2020-12-24 14:08:04 +05303811 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003812 out->offload_state = OFFLOAD_STATE_IDLE;
Gautam Manam14c198b2020-12-24 14:08:04 +05303813 pthread_mutex_unlock(&out->latch_lock);
Weiyin Jiang906db3c2021-03-02 13:17:04 +08003814
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003815 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003816 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003817 if (out->compr != NULL) {
3818 compress_stop(out->compr);
3819 while (out->offload_thread_blocked) {
3820 pthread_cond_wait(&out->cond, &out->lock);
3821 }
3822 }
3823}
3824
Varun Balaraje49253e2017-07-06 19:48:56 +05303825bool is_interactive_usecase(audio_usecase_t uc_id)
3826{
3827 unsigned int i;
3828 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
3829 if (uc_id == interactive_usecases[i])
3830 return true;
3831 }
3832 return false;
3833}
3834
3835static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
3836{
3837 audio_usecase_t ret_uc = USECASE_INVALID;
3838 unsigned int intract_uc_index;
3839 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3840
3841 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
3842 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
3843 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
3844 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
3845 ret_uc = interactive_usecases[intract_uc_index];
3846 break;
3847 }
3848 }
3849
3850 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
3851 return ret_uc;
3852}
3853
3854static void free_interactive_usecase(struct audio_device *adev,
3855 audio_usecase_t uc_id)
3856{
3857 unsigned int interact_uc_index;
3858 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3859
3860 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
3861 if (interactive_usecases[interact_uc_index] == uc_id) {
3862 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
3863 break;
3864 }
3865 }
3866 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
3867}
3868
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003869bool is_offload_usecase(audio_usecase_t uc_id)
3870{
3871 unsigned int i;
3872 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
3873 if (uc_id == offload_usecases[i])
3874 return true;
3875 }
3876 return false;
3877}
3878
Dhananjay Kumarac341582017-02-23 23:42:25 +05303879static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003880{
vivek mehta446c3962015-09-14 10:57:35 -07003881 audio_usecase_t ret_uc = USECASE_INVALID;
3882 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003883 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003884 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05303885 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07003886 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
3887 else
3888 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003889
vivek mehta446c3962015-09-14 10:57:35 -07003890 pthread_mutex_lock(&adev->lock);
3891 if (get_usecase_from_list(adev, ret_uc) != NULL)
3892 ret_uc = USECASE_INVALID;
3893 pthread_mutex_unlock(&adev->lock);
3894
3895 return ret_uc;
3896 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003897
3898 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003899 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3900 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3901 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3902 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003903 break;
3904 }
3905 }
vivek mehta446c3962015-09-14 10:57:35 -07003906
3907 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3908 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003909}
3910
3911static void free_offload_usecase(struct audio_device *adev,
3912 audio_usecase_t uc_id)
3913{
vivek mehta446c3962015-09-14 10:57:35 -07003914 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003915 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003916
3917 if (!adev->multi_offload_enable)
3918 return;
3919
3920 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3921 if (offload_usecases[offload_uc_index] == uc_id) {
3922 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003923 break;
3924 }
3925 }
3926 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3927}
3928
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003929static void *offload_thread_loop(void *context)
3930{
3931 struct stream_out *out = (struct stream_out *) context;
3932 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003933 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003934
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003935 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08003936 set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003937 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3938
3939 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003940 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003941 out->offload_state = OFFLOAD_STATE_IDLE;
3942 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003943 for (;;) {
3944 struct offload_cmd *cmd = NULL;
3945 stream_callback_event_t event;
3946 bool send_callback = false;
3947
3948 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3949 __func__, list_empty(&out->offload_cmd_list),
3950 out->offload_state);
3951 if (list_empty(&out->offload_cmd_list)) {
3952 ALOGV("%s SLEEPING", __func__);
3953 pthread_cond_wait(&out->offload_cond, &out->lock);
3954 ALOGV("%s RUNNING", __func__);
3955 continue;
3956 }
3957
3958 item = list_head(&out->offload_cmd_list);
3959 cmd = node_to_item(item, struct offload_cmd, node);
3960 list_remove(item);
3961
3962 ALOGVV("%s STATE %d CMD %d out->compr %p",
3963 __func__, out->offload_state, cmd->cmd, out->compr);
3964
3965 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3966 free(cmd);
3967 break;
3968 }
3969
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003970 // allow OFFLOAD_CMD_ERROR reporting during standby
3971 // this is needed to handle failures during compress_open
3972 // Note however that on a pause timeout, the stream is closed
3973 // and no offload usecase will be active. Therefore this
3974 // special case is needed for compress_open failures alone
3975 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3976 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003977 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003978 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003979 pthread_cond_signal(&out->cond);
3980 continue;
3981 }
3982 out->offload_thread_blocked = true;
3983 pthread_mutex_unlock(&out->lock);
3984 send_callback = false;
3985 switch(cmd->cmd) {
3986 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003987 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003988 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003989 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003990 send_callback = true;
3991 event = STREAM_CBK_EVENT_WRITE_READY;
3992 break;
3993 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003994 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303995 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003996 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303997 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003998 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303999 if (ret < 0)
4000 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05304001 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05304002 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08004003 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08004004 else
4005 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08004006 if (-ENETRESET != ret && !(-EINTR == ret &&
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05004007 (CARD_STATUS_OFFLINE == out->card_status ||
4008 POWER_POLICY_STATUS_OFFLINE == adev->out_power_policy))) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05304009 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304010 pthread_mutex_lock(&out->lock);
4011 out->send_new_metadata = 1;
4012 out->send_next_track_params = true;
4013 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05304014 event = STREAM_CBK_EVENT_DRAIN_READY;
4015 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
4016 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304017 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004018 break;
4019 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004020 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08004021 ret = compress_drain(out->compr);
4022 ALOGD("copl(%p):out of compress_drain", out);
4023 // EINTR check avoids drain interruption due to SSR
4024 if (-ENETRESET != ret && !(-EINTR == ret &&
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05004025 (CARD_STATUS_OFFLINE == out->card_status ||
4026 POWER_POLICY_STATUS_OFFLINE == adev->out_power_policy))) {
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08004027 send_callback = true;
4028 event = STREAM_CBK_EVENT_DRAIN_READY;
4029 } else
4030 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004031 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304032 case OFFLOAD_CMD_ERROR:
4033 ALOGD("copl(%p): sending error callback to AF", out);
4034 send_callback = true;
4035 event = STREAM_CBK_EVENT_ERROR;
4036 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004037 default:
4038 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
4039 break;
4040 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004041 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004042 out->offload_thread_blocked = false;
4043 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004044 if (send_callback && out->client_callback) {
4045 ALOGVV("%s: sending client_callback event %d", __func__, event);
4046 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07004047 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004048 free(cmd);
4049 }
4050
4051 pthread_cond_signal(&out->cond);
4052 while (!list_empty(&out->offload_cmd_list)) {
4053 item = list_head(&out->offload_cmd_list);
4054 list_remove(item);
4055 free(node_to_item(item, struct offload_cmd, node));
4056 }
4057 pthread_mutex_unlock(&out->lock);
4058
4059 return NULL;
4060}
4061
4062static int create_offload_callback_thread(struct stream_out *out)
4063{
4064 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
4065 list_init(&out->offload_cmd_list);
4066 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
4067 offload_thread_loop, out);
4068 return 0;
4069}
4070
4071static int destroy_offload_callback_thread(struct stream_out *out)
4072{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004073 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004074 stop_compressed_output_l(out);
4075 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
4076
4077 pthread_mutex_unlock(&out->lock);
4078 pthread_join(out->offload_thread, (void **) NULL);
4079 pthread_cond_destroy(&out->offload_cond);
4080
4081 return 0;
4082}
4083
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004084static int stop_output_stream(struct stream_out *out)
4085{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304086 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004087 struct audio_usecase *uc_info;
4088 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08004089 bool has_voip_usecase =
4090 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004091
Eric Laurent994a6932013-07-17 11:51:42 -07004092 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004093 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004094 uc_info = get_usecase_from_list(adev, out->usecase);
4095 if (uc_info == NULL) {
4096 ALOGE("%s: Could not find the usecase (%d) in the list",
4097 __func__, out->usecase);
4098 return -EINVAL;
4099 }
4100
Zhou Songbaddf9f2020-11-20 13:57:39 +08004101 out->a2dp_muted = false;
4102
Derek Chenea197282019-01-07 17:35:01 -08004103 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
4104 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08004105
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004106 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304107 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004108 if (adev->visualizer_stop_output != NULL)
4109 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004110
4111 audio_extn_dts_remove_state_notifier_node(out->usecase);
4112
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004113 if (adev->offload_effects_stop_output != NULL)
4114 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07004115 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
4116 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4117 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004118 }
Eric Laurentc4aef752013-09-12 17:45:53 -07004119
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004120 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
4121 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07004122 voice_set_device_mute_flag(adev, false);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004123 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07004124
Eric Laurent150dbfe2013-02-27 14:31:02 -08004125 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07004126 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004127
4128 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07004129 disable_snd_device(adev, uc_info->out_snd_device);
Zhou Songd9bd9302020-08-04 16:34:45 +08004130 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
4131 disable_snd_device(adev, SND_DEVICE_OUT_HAPTICS);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004132
Aalique Grahame22e49102018-12-18 14:23:57 -08004133 audio_extn_extspk_update(adev->extspk);
4134
Xiaojun Sang785b5da2017-08-03 15:52:29 +08004135 if (is_offload_usecase(out->usecase)) {
4136 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
4137 adev->dsp_bit_width_enforce_mode,
4138 false);
4139 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004140 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07004141 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
4142 false);
4143
4144 if (ret != 0)
4145 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
4146 /* default service interval was successfully updated,
4147 reopen USB backend with new service interval */
4148 ret = 0;
4149 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08004150
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004151 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304152 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004153 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304154 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004155 ALOGV("Disable passthrough , reset mixer to pcm");
4156 /* NO_PASSTHROUGH */
Meng Wang4c32fb42020-01-16 17:57:11 +08004157#ifdef AUDIO_GKI_ENABLED
4158 /* out->compr_config.codec->reserved[0] is for compr_passthr */
4159 out->compr_config.codec->reserved[0] = 0;
4160#else
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004161 out->compr_config.codec->compr_passthr = 0;
Meng Wang4c32fb42020-01-16 17:57:11 +08004162#endif
Mingming Yin21854652016-04-13 11:54:02 -07004163 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004164 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
4165 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07004166
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304167 /* Must be called after removing the usecase from list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004168 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL))
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05304169 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304170
Manish Dewangan21a850a2017-08-14 12:03:55 +05304171 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07004172 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
4173 if (ret < 0)
4174 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
4175 }
4176
Zhou Song642ec432020-12-23 16:11:10 +08004177 /* trigger voip input to reroute when voip output changes to hearing aid */
Aalique Grahame22e49102018-12-18 14:23:57 -08004178 if (has_voip_usecase ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004179 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08004180 struct listnode *node;
4181 struct audio_usecase *usecase;
4182 list_for_each(node, &adev->usecase_list) {
4183 usecase = node_to_item(node, struct audio_usecase, list);
Zhou Song642ec432020-12-23 16:11:10 +08004184 if (usecase->type == PCM_PLAYBACK || usecase == uc_info ||
4185 (usecase->type == PCM_CAPTURE &&
Revathi Uddarajud9f23d92020-07-27 10:55:06 +05304186 usecase->id != USECASE_AUDIO_RECORD_VOIP &&
Zhou Song642ec432020-12-23 16:11:10 +08004187 usecase->id != USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY))
Aalique Grahame22e49102018-12-18 14:23:57 -08004188 continue;
4189
4190 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
4191 __func__, usecase->id, use_case_table[usecase->id],
4192 out->usecase, use_case_table[out->usecase]);
4193 select_devices(adev, usecase->id);
4194 }
4195 }
4196
Zhenlin Lian4f947842022-05-14 15:50:52 +05304197 clear_devices(&uc_info->device_list);
Garmond Leung5fd0b552018-04-17 11:56:12 -07004198 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07004199 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004200 return ret;
4201}
4202
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004203struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
4204 unsigned int flags, unsigned int pcm_open_retry_count,
4205 struct pcm_config *config)
4206{
4207 struct pcm* pcm = NULL;
4208
4209 while (1) {
4210 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
4211 if (pcm == NULL || !pcm_is_ready(pcm)) {
4212 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
4213 if (pcm != NULL) {
4214 pcm_close(pcm);
4215 pcm = NULL;
4216 }
Weiyin Jiang72197252019-10-09 11:49:32 +08004217 if (pcm_open_retry_count == 0)
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004218 return NULL;
4219
Weiyin Jiang72197252019-10-09 11:49:32 +08004220 pcm_open_retry_count--;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004221 usleep(PROXY_OPEN_WAIT_TIME * 1000);
4222 continue;
4223 }
4224 break;
4225 }
4226
4227 if (pcm_is_ready(pcm)) {
4228 int ret = pcm_prepare(pcm);
4229 if (ret < 0) {
4230 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
4231 pcm_close(pcm);
4232 pcm = NULL;
4233 }
4234 }
4235
4236 return pcm;
4237}
4238
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004239int start_output_stream(struct stream_out *out)
4240{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004241 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004242 struct audio_usecase *uc_info;
4243 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004244 char mixer_ctl_name[128];
4245 struct mixer_ctl *ctl = NULL;
4246 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304247 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004248 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004249
Haynes Mathew George380745d2017-10-04 15:27:45 -07004250 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004251 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
4252 ret = -EINVAL;
4253 goto error_config;
4254 }
4255
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004256 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304257 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004258 get_device_types(&out->device_list), is_haptic_usecase);
4259
4260 bool is_speaker_active = compare_device_type(&out->device_list,
4261 AUDIO_DEVICE_OUT_SPEAKER);
4262 bool is_speaker_safe_active = compare_device_type(&out->device_list,
4263 AUDIO_DEVICE_OUT_SPEAKER_SAFE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304264
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304265 if (CARD_STATUS_OFFLINE == out->card_status ||
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05004266 CARD_STATUS_OFFLINE == adev->card_status ||
4267 POWER_POLICY_STATUS_OFFLINE == adev->out_power_policy) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304268 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05304269 ret = -EIO;
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004270 goto error_fatal;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304271 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05304272
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004273 //Update incall music usecase to reflect correct voice session
4274 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
4275 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
4276 if (ret != 0) {
4277 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
4278 __func__, ret);
4279 goto error_config;
4280 }
4281 }
4282
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004283 if (is_a2dp_out_device_type(&out->device_list)) {
Florian Pfister1a84f312018-07-19 14:38:18 +02004284 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004285 if (is_speaker_active || is_speaker_safe_active) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304286 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304287 } else {
Zhou Songd01e7a22020-09-23 22:49:01 +08004288 if (!is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304289 ALOGE("%s: A2DP profile is not ready, return error", __func__);
4290 ret = -EAGAIN;
4291 goto error_config;
4292 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304293 }
4294 }
4295 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004296 if (is_sco_out_device_type(&out->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304297 if (!adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004298 if (is_speaker_active) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304299 //combo usecase just by pass a2dp
4300 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004301 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304302 } else {
4303 ALOGE("%s: SCO profile is not ready, return error", __func__);
4304 ret = -EAGAIN;
4305 goto error_config;
4306 }
4307 }
4308 }
4309
Eric Laurentb23d5282013-05-14 15:27:20 -07004310 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004311 if (out->pcm_device_id < 0) {
4312 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
4313 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004314 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004315 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004316 }
4317
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004318 if (is_haptic_usecase) {
Meng Wang51d8c2a2020-04-27 15:23:21 +08004319 adev->haptic_pcm_device_id = platform_get_pcm_device_id(
4320 USECASE_AUDIO_PLAYBACK_HAPTICS, PCM_PLAYBACK);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004321 if (adev->haptic_pcm_device_id < 0) {
4322 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
4323 __func__, adev->haptic_pcm_device_id, out->usecase);
4324 ret = -EINVAL;
4325 goto error_config;
4326 }
4327 }
4328
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004329 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004330
4331 if (!uc_info) {
4332 ret = -ENOMEM;
4333 goto error_config;
4334 }
4335
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004336 uc_info->id = out->usecase;
4337 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004338 uc_info->stream.out = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004339 list_init(&uc_info->device_list);
4340 assign_devices(&uc_info->device_list, &out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004341 uc_info->in_snd_device = SND_DEVICE_NONE;
4342 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07004343
4344 /* This must be called before adding this usecase to the list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004345 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07004346 audio_extn_usb_check_and_set_svc_int(uc_info, true);
4347 /* USB backend is not reopened immediately.
4348 This is eventually done as part of select_devices */
4349 }
4350
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004351 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004352
Wei Wangf7ca6c92017-11-21 14:51:20 -08004353 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304354 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4355 adev->perf_lock_opts,
4356 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304357
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004358 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05304359 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304360 if (audio_extn_passthru_is_enabled() &&
4361 audio_extn_passthru_is_passthrough_stream(out)) {
4362 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304363 }
4364 }
4365
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004366 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02004367 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304368 if (!a2dp_combo) {
4369 check_a2dp_restore_l(adev, out, false);
4370 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004371 struct listnode dev;
4372 list_init(&dev);
4373 assign_devices(&dev, &out->device_list);
4374 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4375 reassign_device_list(&out->device_list,
4376 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aalique Grahame22e49102018-12-18 14:23:57 -08004377 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004378 reassign_device_list(&out->device_list,
4379 AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304380 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004381 assign_devices(&out->device_list, &dev);
Zhenlin Lian4f947842022-05-14 15:50:52 +05304382 clear_devices(&dev);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304383 }
4384 } else {
Revathi Uddarajub26e3932020-06-10 14:51:02 +05304385 select_devices(adev, out->usecase);
4386 if (is_a2dp_out_device_type(&out->device_list) &&
4387 !adev->a2dp_started) {
4388 if (is_speaker_active || is_speaker_safe_active) {
4389 struct listnode dev;
4390 list_init(&dev);
4391 assign_devices(&dev, &out->device_list);
4392 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4393 reassign_device_list(&out->device_list,
4394 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
4395 else
4396 reassign_device_list(&out->device_list,
4397 AUDIO_DEVICE_OUT_SPEAKER, "");
4398 select_devices(adev, out->usecase);
4399 assign_devices(&out->device_list, &dev);
Zhenlin Lian4f947842022-05-14 15:50:52 +05304400 clear_devices(&dev);
Revathi Uddarajub26e3932020-06-10 14:51:02 +05304401 } else {
4402 ret = -EINVAL;
4403 goto error_open;
4404 }
4405 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304406 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004407
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004408 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
4409 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07004410 voice_set_device_mute_flag(adev, true);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004411 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07004412
Derek Chenea197282019-01-07 17:35:01 -08004413 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
4414 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08004415
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004416 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
4417 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07004418
4419 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07004420 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07004421 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4422 ALOGE("%s: pcm stream not ready", __func__);
4423 goto error_open;
4424 }
4425 ret = pcm_start(out->pcm);
4426 if (ret < 0) {
4427 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
4428 goto error_open;
4429 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07004430 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07004431 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004432 unsigned int flags = PCM_OUT;
4433 unsigned int pcm_open_retry_count = 0;
4434 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
4435 flags |= PCM_MMAP | PCM_NOIRQ;
4436 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004437 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08004438 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004439 } else
4440 flags |= PCM_MONOTONIC;
4441
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004442 if ((adev->vr_audio_mode_enabled) &&
4443 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
4444 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4445 "PCM_Dev %d Topology", out->pcm_device_id);
4446 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4447 if (!ctl) {
4448 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
4449 __func__, mixer_ctl_name);
4450 } else {
4451 //if success use ULLPP
4452 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
4453 __func__, mixer_ctl_name, out->pcm_device_id);
4454 //There is a still a possibility that some sessions
4455 // that request for FAST|RAW when 3D audio is active
4456 //can go through ULLPP. Ideally we expects apps to
4457 //listen to audio focus and stop concurrent playback
4458 //Also, we will look for mode flag (voice_in_communication)
4459 //before enabling the realtime flag.
4460 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
4461 }
4462 }
4463
Vatsal Bucha3f39f222021-06-29 16:16:55 +05304464 platform_set_stream_channel_map(adev->platform, out->channel_mask,
4465 out->pcm_device_id, -1, &out->channel_map_param.channel_map[0]);
Surendar Karka91fa3682018-07-02 18:12:12 +05304466
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004467 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
4468 flags, pcm_open_retry_count,
4469 &(out->config));
4470 if (out->pcm == NULL) {
4471 ret = -EIO;
4472 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004473 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004474
4475 if (is_haptic_usecase) {
4476 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
4477 adev->haptic_pcm_device_id,
4478 flags, pcm_open_retry_count,
4479 &(adev->haptics_config));
4480 // failure to open haptics pcm shouldnt stop audio,
4481 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07004482
4483 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
4484 ALOGD("%s: enable haptic audio synchronization", __func__);
4485 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
4486 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004487 }
4488
Zhou Song2b8f28f2017-09-11 10:51:38 +08004489 // apply volume for voip playback after path is set up
4490 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
4491 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05304492 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
4493 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304494 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
4495 out->apply_volume = false;
Derek Chenf13dd492018-11-13 14:53:51 -08004496 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
4497 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Krishna Kishor Jha10ad39f2022-02-21 17:02:47 +05304498#ifdef SOFT_VOLUME
4499 out_set_soft_volume_params(&out->stream);
4500#endif
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304501 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004502 } else {
Zhou Song79929fe2020-01-20 17:57:43 +08004503 /*
4504 * set custom channel map if:
4505 * 1. neither mono nor stereo clips i.e. channels > 2 OR
4506 * 2. custom channel map has been set by client
4507 * else default channel map of FC/FR/FL can always be set to DSP
4508 */
4509 if (popcount(out->channel_mask) > 2 || out->channel_map_param.channel_map[0])
4510 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Weiyin Jiang810a80d2021-01-18 16:04:31 +08004511 out->pcm_device_id, -1, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08004512 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
4513 adev->dsp_bit_width_enforce_mode,
4514 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004515 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07004516 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004517 out->compr = compress_open(adev->snd_card,
4518 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004519 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004520 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05304521 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05304522 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
4523 adev->card_status = CARD_STATUS_OFFLINE;
4524 out->card_status = CARD_STATUS_OFFLINE;
4525 ret = -EIO;
4526 goto error_open;
4527 }
4528
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004529 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004530 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004531 compress_close(out->compr);
4532 out->compr = NULL;
4533 ret = -EIO;
4534 goto error_open;
4535 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304536 /* compress_open sends params of the track, so reset the flag here */
4537 out->is_compr_metadata_avail = false;
4538
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004539 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004540 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07004541
Fred Oh3f43e742015-03-04 18:42:34 -08004542 /* Since small bufs uses blocking writes, a write will be blocked
4543 for the default max poll time (20s) in the event of an SSR.
4544 Reduce the poll time to observe and deal with SSR faster.
4545 */
Ashish Jain5106d362016-05-11 19:23:33 +05304546 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08004547 compress_set_max_poll_wait(out->compr, 1000);
4548 }
4549
Manish Dewangan69426c82017-01-30 17:35:36 +05304550 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05304551 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05304552
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004553 audio_extn_dts_create_state_notifier_node(out->usecase);
4554 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4555 popcount(out->channel_mask),
4556 out->playback_started);
4557
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004558#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304559 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004560 audio_extn_dolby_send_ddp_endp_params(adev);
4561#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05304562 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
4563 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004564 if (adev->visualizer_start_output != NULL)
4565 adev->visualizer_start_output(out->handle, out->pcm_device_id);
4566 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05304567 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004568 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004569 }
Derek Chenf13dd492018-11-13 14:53:51 -08004570
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004571 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf13dd492018-11-13 14:53:51 -08004572 /* Update cached volume from media to offload/direct stream */
4573 struct listnode *node = NULL;
4574 list_for_each(node, &adev->active_outputs_list) {
4575 streams_output_ctxt_t *out_ctxt = node_to_item(node,
4576 streams_output_ctxt_t,
4577 list);
4578 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
4579 out->volume_l = out_ctxt->output->volume_l;
4580 out->volume_r = out_ctxt->output->volume_r;
4581 }
4582 }
4583 out_set_compr_volume(&out->stream,
4584 out->volume_l, out->volume_r);
4585 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004586 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004587
4588 if (ret == 0) {
Vaibhav Raut5f3bf222023-02-06 17:45:22 +05304589 if (out->flags & (AUDIO_OUTPUT_FLAG_FAST | AUDIO_OUTPUT_FLAG_RAW))
Narsinga Rao Chellaa6e1f702021-10-22 13:57:32 +05304590 register_out_stream(out);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004591 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07004592 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4593 ALOGE("%s: pcm stream not ready", __func__);
4594 goto error_open;
4595 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004596 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004597 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004598 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004599 if (ret < 0)
4600 goto error_open;
4601 }
4602 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004603 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304604 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Jaideep Sharma0fa53812020-09-17 09:00:11 +05304605 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004606
vivek mehtad15d2bf2019-05-17 13:35:10 -07004607 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
4608 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4609 audio_low_latency_hint_start();
4610 }
4611
Manish Dewangan21a850a2017-08-14 12:03:55 +05304612 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07004613 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07004614 if (ret < 0)
4615 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
4616 }
4617
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004618 // consider a scenario where on pause lower layers are tear down.
4619 // so on resume, swap mixer control need to be sent only when
4620 // backend is active, hence rather than sending from enable device
4621 // sending it from start of streamtream
4622
4623 platform_set_swap_channels(adev, true);
4624
Haynes Mathew George380745d2017-10-04 15:27:45 -07004625 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304626 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004627 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004628error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004629 if (adev->haptic_pcm) {
4630 pcm_close(adev->haptic_pcm);
4631 adev->haptic_pcm = NULL;
4632 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004633 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304634 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004635 stop_output_stream(out);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004636error_fatal:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05304637 /*
4638 * sleep 50ms to allow sufficient time for kernel
4639 * drivers to recover incases like SSR.
4640 */
4641 usleep(50000);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004642error_config:
Haynes Mathew George380745d2017-10-04 15:27:45 -07004643 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304644 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004645 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004646}
4647
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004648static int check_input_parameters(uint32_t sample_rate,
4649 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08004650 int channel_count,
4651 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004652{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004653 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004654
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304655 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
4656 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
4657 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07004658 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02004659 !audio_extn_compr_cap_format_supported(format) &&
4660 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004661 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004662
Aalique Grahame22e49102018-12-18 14:23:57 -08004663 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
4664 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
4665 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
4666 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
4667 return -EINVAL;
4668 }
4669
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004670 switch (channel_count) {
4671 case 1:
4672 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304673 case 3:
4674 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004675 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07004676 case 8:
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05304677 case 10:
4678 case 12:
4679 case 14:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004680 break;
4681 default:
4682 ret = -EINVAL;
4683 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004684
4685 switch (sample_rate) {
4686 case 8000:
4687 case 11025:
4688 case 12000:
4689 case 16000:
4690 case 22050:
4691 case 24000:
4692 case 32000:
4693 case 44100:
4694 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004695 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304696 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004697 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304698 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004699 break;
4700 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004701 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004702 }
4703
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004704 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004705}
4706
Naresh Tanniru04f71882018-06-26 17:46:22 +05304707
4708/** Add a value in a list if not already present.
4709 * @return true if value was successfully inserted or already present,
4710 * false if the list is full and does not contain the value.
4711 */
4712static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
4713 for (size_t i = 0; i < list_length; i++) {
4714 if (list[i] == value) return true; // value is already present
4715 if (list[i] == 0) { // no values in this slot
4716 list[i] = value;
4717 return true; // value inserted
4718 }
4719 }
4720 return false; // could not insert value
4721}
4722
4723/** Add channel_mask in supported_channel_masks if not already present.
4724 * @return true if channel_mask was successfully inserted or already present,
4725 * false if supported_channel_masks is full and does not contain channel_mask.
4726 */
4727static void register_channel_mask(audio_channel_mask_t channel_mask,
4728 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
4729 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
4730 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
4731}
4732
4733/** Add format in supported_formats if not already present.
4734 * @return true if format was successfully inserted or already present,
4735 * false if supported_formats is full and does not contain format.
4736 */
4737static void register_format(audio_format_t format,
4738 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
4739 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
4740 "%s: stream can not declare supporting its format %x", __func__, format);
4741}
4742/** Add sample_rate in supported_sample_rates if not already present.
4743 * @return true if sample_rate was successfully inserted or already present,
4744 * false if supported_sample_rates is full and does not contain sample_rate.
4745 */
4746static void register_sample_rate(uint32_t sample_rate,
4747 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
4748 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
4749 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
4750}
4751
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004752static inline uint32_t lcm(uint32_t num1, uint32_t num2)
4753{
4754 uint32_t high = num1, low = num2, temp = 0;
4755
4756 if (!num1 || !num2)
4757 return 0;
4758
4759 if (num1 < num2) {
4760 high = num2;
4761 low = num1;
4762 }
4763
4764 while (low != 0) {
4765 temp = low;
4766 low = high % low;
4767 high = temp;
4768 }
4769 return (num1 * num2)/high;
4770}
4771
4772static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
4773{
4774 uint32_t remainder = 0;
4775
4776 if (!multiplier)
4777 return num;
4778
4779 remainder = num % multiplier;
4780 if (remainder)
4781 num += (multiplier - remainder);
4782
4783 return num;
4784}
4785
Aalique Grahame22e49102018-12-18 14:23:57 -08004786static size_t get_stream_buffer_size(size_t duration_ms,
4787 uint32_t sample_rate,
4788 audio_format_t format,
4789 int channel_count,
4790 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004791{
4792 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004793 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004794
Aalique Grahame22e49102018-12-18 14:23:57 -08004795 size = (sample_rate * duration_ms) / 1000;
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +05304796 if (is_low_latency){
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +05304797#ifndef PLATFORM_AUTO
4798 size = configured_low_latency_capture_period_size;
4799#else
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +05304800 switch(sample_rate) {
4801 case 48000:
4802 size = 240;
4803 break;
4804 case 32000:
4805 size = 160;
4806 break;
4807 case 24000:
4808 size = 120;
4809 break;
4810 case 16000:
4811 size = 80;
4812 break;
4813 case 8000:
4814 size = 40;
4815 break;
4816 default:
4817 size = 240;
4818 }
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +05304819#endif
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +05304820 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304821
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004822 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08004823 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004824
Ralf Herzbd08d632018-09-28 15:50:49 +02004825 /* make sure the size is multiple of 32 bytes and additionally multiple of
4826 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004827 * At 48 kHz mono 16-bit PCM:
4828 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
4829 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004830 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004831 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004832 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07004833
4834 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004835}
4836
Aalique Grahame22e49102018-12-18 14:23:57 -08004837static size_t get_input_buffer_size(uint32_t sample_rate,
4838 audio_format_t format,
4839 int channel_count,
4840 bool is_low_latency)
4841{
Avinash Chandrad7296d42021-08-04 15:07:47 +05304842 bool is_usb_hifi = IS_USB_HIFI;
Aalique Grahame22e49102018-12-18 14:23:57 -08004843 /* Don't know if USB HIFI in this context so use true to be conservative */
4844 if (check_input_parameters(sample_rate, format, channel_count,
Avinash Chandrad7296d42021-08-04 15:07:47 +05304845 is_usb_hifi) != 0)
Aalique Grahame22e49102018-12-18 14:23:57 -08004846 return 0;
4847
4848 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4849 sample_rate,
4850 format,
4851 channel_count,
4852 is_low_latency);
4853}
4854
Derek Chenf6318be2017-06-12 17:16:24 -04004855size_t get_output_period_size(uint32_t sample_rate,
4856 audio_format_t format,
4857 int channel_count,
4858 int duration /*in millisecs*/)
Ashish Jain058165c2016-09-28 23:18:48 +05304859{
4860 size_t size = 0;
4861 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
4862
4863 if ((duration == 0) || (sample_rate == 0) ||
4864 (bytes_per_sample == 0) || (channel_count == 0)) {
4865 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
4866 bytes_per_sample, channel_count);
4867 return -EINVAL;
4868 }
4869
4870 size = (sample_rate *
4871 duration *
4872 bytes_per_sample *
4873 channel_count) / 1000;
4874 /*
4875 * To have same PCM samples for all channels, the buffer size requires to
4876 * be multiple of (number of channels * bytes per sample)
4877 * For writes to succeed, the buffer must be written at address which is multiple of 32
4878 */
4879 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
4880
4881 return (size/(channel_count * bytes_per_sample));
4882}
4883
Zhou Song48453a02018-01-10 17:50:59 +08004884static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05304885{
4886 uint64_t actual_frames_rendered = 0;
Weiyin Jiang4813da12020-05-28 00:37:28 +08004887 uint64_t written_frames = 0;
4888 uint64_t kernel_frames = 0;
4889 uint64_t dsp_frames = 0;
4890 uint64_t signed_frames = 0;
4891 size_t kernel_buffer_size = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304892
4893 /* This adjustment accounts for buffering after app processor.
4894 * It is based on estimated DSP latency per use case, rather than exact.
4895 */
George Gao9ba8a142020-07-23 14:30:03 -07004896 dsp_frames = platform_render_latency(out) *
Weiyin Jiang4813da12020-05-28 00:37:28 +08004897 out->sample_rate / 1000000LL;
Ashish Jain5106d362016-05-11 19:23:33 +05304898
Zhou Song48453a02018-01-10 17:50:59 +08004899 pthread_mutex_lock(&out->position_query_lock);
Weiyin Jiang4813da12020-05-28 00:37:28 +08004900 written_frames = out->written /
4901 (audio_bytes_per_sample(out->hal_ip_format) * popcount(out->channel_mask));
4902
Ashish Jain5106d362016-05-11 19:23:33 +05304903 /* not querying actual state of buffering in kernel as it would involve an ioctl call
4904 * which then needs protection, this causes delay in TS query for pcm_offload usecase
4905 * hence only estimate.
4906 */
Weiyin Jiang4813da12020-05-28 00:37:28 +08004907 kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
4908 kernel_frames = kernel_buffer_size /
4909 (audio_bytes_per_sample(out->hal_op_format) * popcount(out->channel_mask));
Ashish Jain5106d362016-05-11 19:23:33 +05304910
Weiyin Jiang4813da12020-05-28 00:37:28 +08004911 if (written_frames >= (kernel_frames + dsp_frames))
4912 signed_frames = written_frames - kernel_frames - dsp_frames;
Ashish Jain5106d362016-05-11 19:23:33 +05304913
Zhou Song48453a02018-01-10 17:50:59 +08004914 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05304915 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08004916 if (timestamp != NULL )
4917 *timestamp = out->writeAt;
4918 } else if (timestamp != NULL) {
4919 clock_gettime(CLOCK_MONOTONIC, timestamp);
4920 }
4921 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304922
Weiyin Jiang4813da12020-05-28 00:37:28 +08004923 ALOGVV("%s signed frames %lld written frames %lld kernel frames %lld dsp frames %lld",
4924 __func__, signed_frames, written_frames, kernel_frames, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05304925
4926 return actual_frames_rendered;
4927}
4928
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004929static uint32_t out_get_sample_rate(const struct audio_stream *stream)
4930{
4931 struct stream_out *out = (struct stream_out *)stream;
4932
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004933 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004934}
4935
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004936static int out_set_sample_rate(struct audio_stream *stream __unused,
4937 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004938{
4939 return -ENOSYS;
4940}
4941
4942static size_t out_get_buffer_size(const struct audio_stream *stream)
4943{
4944 struct stream_out *out = (struct stream_out *)stream;
4945
Varun Balaraje49253e2017-07-06 19:48:56 +05304946 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05304947 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05304948 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304949 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4950 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
4951 else
4952 return out->compr_config.fragment_size;
4953 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004954 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304955 else if (is_offload_usecase(out->usecase) &&
4956 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304957 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004958
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004959 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004960 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004961}
4962
4963static uint32_t out_get_channels(const struct audio_stream *stream)
4964{
4965 struct stream_out *out = (struct stream_out *)stream;
4966
4967 return out->channel_mask;
4968}
4969
4970static audio_format_t out_get_format(const struct audio_stream *stream)
4971{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004972 struct stream_out *out = (struct stream_out *)stream;
4973
4974 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004975}
4976
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004977static int out_set_format(struct audio_stream *stream __unused,
4978 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004979{
4980 return -ENOSYS;
4981}
4982
4983static int out_standby(struct audio_stream *stream)
4984{
4985 struct stream_out *out = (struct stream_out *)stream;
4986 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07004987 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004988
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304989 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4990 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004991
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004992 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004993 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004994 if (adev->adm_deregister_stream)
4995 adev->adm_deregister_stream(adev->adm_data, out->handle);
4996
Weiyin Jiang280ea742020-09-08 20:28:22 +08004997 if (is_offload_usecase(out->usecase)) {
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004998 stop_compressed_output_l(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08004999 }
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07005000
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08005001 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005002 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08005003 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
5004 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305005 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08005006 pthread_mutex_unlock(&adev->lock);
5007 pthread_mutex_unlock(&out->lock);
5008 ALOGD("VOIP output entered standby");
5009 return 0;
5010 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005011 if (out->pcm) {
5012 pcm_close(out->pcm);
5013 out->pcm = NULL;
5014 }
Meng Wanga09da002020-04-20 12:56:04 +08005015 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
5016 if (adev->haptic_pcm) {
5017 pcm_close(adev->haptic_pcm);
5018 adev->haptic_pcm = NULL;
5019 }
5020
5021 if (adev->haptic_buffer != NULL) {
5022 free(adev->haptic_buffer);
5023 adev->haptic_buffer = NULL;
5024 adev->haptic_buffer_size = 0;
5025 }
5026 adev->haptic_pcm_device_id = 0;
5027 }
5028
Haynes Mathew George16081042017-05-31 17:16:49 -07005029 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5030 do_stop = out->playback_started;
5031 out->playback_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07005032
5033 if (out->mmap_shared_memory_fd >= 0) {
5034 ALOGV("%s: closing mmap_shared_memory_fd = %d",
5035 __func__, out->mmap_shared_memory_fd);
5036 close(out->mmap_shared_memory_fd);
5037 out->mmap_shared_memory_fd = -1;
5038 }
Haynes Mathew George16081042017-05-31 17:16:49 -07005039 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005040 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005041 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305042 out->send_next_track_params = false;
5043 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005044 out->gapless_mdata.encoder_delay = 0;
5045 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005046 if (out->compr != NULL) {
5047 compress_close(out->compr);
5048 out->compr = NULL;
5049 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08005050 }
Haynes Mathew George16081042017-05-31 17:16:49 -07005051 if (do_stop) {
5052 stop_output_stream(out);
5053 }
Lakshman Chaluvaraju06677b42019-06-24 10:04:52 +05305054 // if fm is active route on selected device in UI
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005055 audio_extn_fm_route_on_selected_device(adev, &out->device_list);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005056 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005057 }
5058 pthread_mutex_unlock(&out->lock);
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07005059 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005060 return 0;
5061}
5062
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305063static int out_on_error(struct audio_stream *stream)
5064{
5065 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07005066 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305067
5068 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08005069 // always send CMD_ERROR for offload streams, this
5070 // is needed e.g. when SSR happens within compress_open
5071 // since the stream is active, offload_callback_thread is also active.
5072 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
5073 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07005074 }
5075 pthread_mutex_unlock(&out->lock);
5076
5077 status = out_standby(&out->stream.common);
5078
5079 lock_output_stream(out);
5080 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08005081 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305082 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05305083
5084 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
5085 ALOGD("Setting previous card status if offline");
5086 out->prev_card_status_offline = true;
5087 }
5088
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305089 pthread_mutex_unlock(&out->lock);
5090
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07005091 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305092}
5093
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305094/*
Weiyin Jiang280ea742020-09-08 20:28:22 +08005095 * standby implementation without locks, assumes that the callee already
5096 * has taken adev and out lock.
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305097 */
5098int out_standby_l(struct audio_stream *stream)
5099{
5100 struct stream_out *out = (struct stream_out *)stream;
5101 struct audio_device *adev = out->dev;
5102
5103 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
5104 stream, out->usecase, use_case_table[out->usecase]);
5105
5106 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07005107 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305108 if (adev->adm_deregister_stream)
5109 adev->adm_deregister_stream(adev->adm_data, out->handle);
5110
Weiyin Jiang280ea742020-09-08 20:28:22 +08005111 if (is_offload_usecase(out->usecase)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305112 stop_compressed_output_l(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08005113 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305114
5115 out->standby = true;
5116 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
5117 voice_extn_compress_voip_close_output_stream(stream);
5118 out->started = 0;
5119 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07005120 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305121 return 0;
5122 } else if (!is_offload_usecase(out->usecase)) {
5123 if (out->pcm) {
5124 pcm_close(out->pcm);
5125 out->pcm = NULL;
5126 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005127 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
5128 if (adev->haptic_pcm) {
5129 pcm_close(adev->haptic_pcm);
5130 adev->haptic_pcm = NULL;
5131 }
5132
5133 if (adev->haptic_buffer != NULL) {
5134 free(adev->haptic_buffer);
5135 adev->haptic_buffer = NULL;
5136 adev->haptic_buffer_size = 0;
5137 }
5138 adev->haptic_pcm_device_id = 0;
5139 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305140 } else {
5141 ALOGD("copl(%p):standby", out);
5142 out->send_next_track_params = false;
5143 out->is_compr_metadata_avail = false;
5144 out->gapless_mdata.encoder_delay = 0;
5145 out->gapless_mdata.encoder_padding = 0;
5146 if (out->compr != NULL) {
5147 compress_close(out->compr);
5148 out->compr = NULL;
5149 }
5150 }
5151 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005152 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305153 }
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07005154 ALOGV("%s: exit", __func__);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305155 return 0;
5156}
5157
Aalique Grahame22e49102018-12-18 14:23:57 -08005158static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005159{
Aalique Grahame22e49102018-12-18 14:23:57 -08005160 struct stream_out *out = (struct stream_out *)stream;
5161
5162 // We try to get the lock for consistency,
5163 // but it isn't necessary for these variables.
5164 // If we're not in standby, we may be blocked on a write.
5165 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
5166 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
5167 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
Dechen Chai22768452021-07-30 09:29:16 +05305168#ifndef LINUX_ENABLED
Andy Hunga1f48fa2019-07-01 18:14:53 -07005169 char buffer[256]; // for statistics formatting
5170 if (!is_offload_usecase(out->usecase)) {
5171 simple_stats_to_string(&out->fifo_underruns, buffer, sizeof(buffer));
5172 dprintf(fd, " Fifo frame underruns: %s\n", buffer);
5173 }
5174
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005175 if (out->start_latency_ms.n > 0) {
5176 simple_stats_to_string(&out->start_latency_ms, buffer, sizeof(buffer));
5177 dprintf(fd, " Start latency ms: %s\n", buffer);
5178 }
Dechen Chai22768452021-07-30 09:29:16 +05305179#endif
Aalique Grahame22e49102018-12-18 14:23:57 -08005180 if (locked) {
5181 pthread_mutex_unlock(&out->lock);
5182 }
5183
Dechen Chai22768452021-07-30 09:29:16 +05305184#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -08005185 // dump error info
5186 (void)error_log_dump(
5187 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Dechen Chai22768452021-07-30 09:29:16 +05305188#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005189 return 0;
5190}
5191
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005192static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
5193{
5194 int ret = 0;
5195 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08005196
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005197 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08005198 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005199 return -EINVAL;
5200 }
5201
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05305202 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08005203
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005204 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
5205 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05305206 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005207 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005208 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
5209 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05305210 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005211 }
5212
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005213 ALOGV("%s new encoder delay %u and padding %u", __func__,
5214 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
5215
5216 return 0;
5217}
5218
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005219static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
5220{
5221 return out == adev->primary_output || out == adev->voice_tx_output;
5222}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005223
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305224// note: this call is safe only if the stream_cb is
5225// removed first in close_output_stream (as is done now).
5226static void out_snd_mon_cb(void * stream, struct str_parms * parms)
5227{
5228 if (!stream || !parms)
5229 return;
5230
5231 struct stream_out *out = (struct stream_out *)stream;
5232 struct audio_device *adev = out->dev;
5233
5234 card_status_t status;
5235 int card;
5236 if (parse_snd_card_status(parms, &card, &status) < 0)
5237 return;
5238
5239 pthread_mutex_lock(&adev->lock);
5240 bool valid_cb = (card == adev->snd_card);
5241 pthread_mutex_unlock(&adev->lock);
5242
5243 if (!valid_cb)
5244 return;
5245
5246 lock_output_stream(out);
5247 if (out->card_status != status)
5248 out->card_status = status;
5249 pthread_mutex_unlock(&out->lock);
5250
5251 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
5252 use_case_table[out->usecase],
5253 status == CARD_STATUS_OFFLINE ? "offline" : "online");
5254
Aditya Bavanari59ebed42019-02-05 17:44:57 +05305255 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305256 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05305257 if (voice_is_call_state_active(adev) &&
5258 out == adev->primary_output) {
5259 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
5260 pthread_mutex_lock(&adev->lock);
5261 voice_stop_call(adev);
5262 adev->mode = AUDIO_MODE_NORMAL;
5263 pthread_mutex_unlock(&adev->lock);
5264 }
5265 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305266 return;
5267}
5268
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005269int route_output_stream(struct stream_out *out,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005270 struct listnode *devices)
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005271{
5272 struct audio_device *adev = out->dev;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005273 int ret = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005274 struct listnode new_devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005275 bool bypass_a2dp = false;
5276 bool reconfig = false;
5277 unsigned long service_interval = 0;
5278
5279 ALOGD("%s: enter: usecase(%d: %s) devices %x",
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005280 __func__, out->usecase, use_case_table[out->usecase], get_device_types(devices));
5281
5282 list_init(&new_devices);
5283 assign_devices(&new_devices, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005284
5285 lock_output_stream(out);
5286 pthread_mutex_lock(&adev->lock);
5287
5288 /*
5289 * When HDMI cable is unplugged the music playback is paused and
5290 * the policy manager sends routing=0. But the audioflinger continues
5291 * to write data until standby time (3sec). As the HDMI core is
5292 * turned off, the write gets blocked.
5293 * Avoid this by routing audio to speaker until standby.
5294 */
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08005295 if (is_single_device_type_equal(&out->device_list,
5296 AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005297 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005298 !audio_extn_passthru_is_passthrough_stream(out) &&
5299 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005300 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005301 }
5302 /*
5303 * When A2DP is disconnected the
5304 * music playback is paused and the policy manager sends routing=0
5305 * But the audioflinger continues to write data until standby time
5306 * (3sec). As BT is turned off, the write gets blocked.
5307 * Avoid this by routing audio to speaker until standby.
5308 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005309 if (is_a2dp_out_device_type(&out->device_list) &&
5310 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005311 !audio_extn_a2dp_source_is_ready() &&
5312 !adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005313 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005314 }
5315 /*
Weiyin Jiangabedea32020-12-09 12:49:19 +08005316 * When USB headset is disconnected the music playback paused
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005317 * and the policy manager send routing=0. But if the USB is connected
5318 * back before the standby time, AFE is not closed and opened
5319 * when USB is connected back. So routing to speker will guarantee
5320 * AFE reconfiguration and AFE will be opend once USB is connected again
5321 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005322 if (is_usb_out_device_type(&out->device_list) &&
5323 list_empty(&new_devices) &&
5324 !audio_extn_usb_connected(NULL)) {
Sujin Panicker84d953a2020-11-16 17:39:54 +05305325 if (adev->mode == AUDIO_MODE_IN_CALL || adev->mode == AUDIO_MODE_IN_COMMUNICATION)
5326 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_EARPIECE, "");
5327 else
5328 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005329 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005330 /* To avoid a2dp to sco overlapping / BT device improper state
5331 * check with BT lib about a2dp streaming support before routing
5332 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005333 if (is_a2dp_out_device_type(&new_devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005334 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005335 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER) ||
5336 compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005337 //combo usecase just by pass a2dp
5338 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
5339 bypass_a2dp = true;
5340 } else {
5341 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
5342 /* update device to a2dp and don't route as BT returned error
5343 * However it is still possible a2dp routing called because
5344 * of current active device disconnection (like wired headset)
5345 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005346 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005347 pthread_mutex_unlock(&adev->lock);
5348 pthread_mutex_unlock(&out->lock);
5349 goto error;
5350 }
5351 }
5352 }
5353
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005354 // Workaround: If routing to an non existing usb device, fail gracefully
5355 // The routing request will otherwise block during 10 second
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005356 if (is_usb_out_device_type(&new_devices)) {
5357 struct str_parms *parms =
5358 str_parms_create_str(get_usb_device_address(&new_devices));
5359 if (!parms)
5360 goto error;
Weiyin Jiangabedea32020-12-09 12:49:19 +08005361 if (!audio_extn_usb_connected(NULL)) {
5362 ALOGW("%s: ignoring rerouting to non existing USB card", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005363 pthread_mutex_unlock(&adev->lock);
5364 pthread_mutex_unlock(&out->lock);
5365 str_parms_destroy(parms);
5366 ret = -ENOSYS;
5367 goto error;
5368 }
5369 str_parms_destroy(parms);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005370 }
5371
Weiyin Jiang80c8f9a2020-01-10 20:42:08 +08005372 // Workaround: If routing to an non existing hdmi device, fail gracefully
5373 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
5374 (platform_get_edid_info_v2(adev->platform,
5375 out->extconn.cs.controller,
5376 out->extconn.cs.stream) != 0)) {
5377 ALOGW("out_set_parameters() ignoring rerouting to non existing HDMI/DP");
5378 pthread_mutex_unlock(&adev->lock);
5379 pthread_mutex_unlock(&out->lock);
5380 ret = -ENOSYS;
5381 goto error;
5382 }
5383
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005384 /*
5385 * select_devices() call below switches all the usecases on the same
5386 * backend to the new device. Refer to check_usecases_codec_backend() in
5387 * the select_devices(). But how do we undo this?
5388 *
5389 * For example, music playback is active on headset (deep-buffer usecase)
5390 * and if we go to ringtones and select a ringtone, low-latency usecase
5391 * will be started on headset+speaker. As we can't enable headset+speaker
5392 * and headset devices at the same time, select_devices() switches the music
5393 * playback to headset+speaker while starting low-lateny usecase for ringtone.
5394 * So when the ringtone playback is completed, how do we undo the same?
5395 *
5396 * We are relying on the out_set_parameters() call on deep-buffer output,
5397 * once the ringtone playback is ended.
5398 * NOTE: We should not check if the current devices are same as new devices.
5399 * Because select_devices() must be called to switch back the music
5400 * playback to headset.
5401 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005402 if (!list_empty(&new_devices)) {
5403 bool same_dev = compare_devices(&out->device_list, &new_devices);
5404 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005405
5406 if (output_drives_call(adev, out)) {
5407 if (!voice_is_call_state_active(adev)) {
5408 if (adev->mode == AUDIO_MODE_IN_CALL) {
5409 adev->current_call_output = out;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005410 ret = voice_start_call(adev);
5411 }
5412 } else {
Kunlei Zhang253ad102020-10-14 16:21:28 +08005413 platform_is_volume_boost_supported_device(adev->platform, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005414 adev->current_call_output = out;
5415 voice_update_devices_for_all_voice_usecases(adev);
5416 }
5417 }
5418
Mingshu Pang971ff702020-09-09 15:28:22 +08005419 if (is_usb_out_device_type(&out->device_list)) {
5420 service_interval = audio_extn_usb_find_service_interval(false, true /*playback*/);
5421 audio_extn_usb_set_service_interval(true /*playback*/,
5422 service_interval,
5423 &reconfig);
5424 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
5425 }
5426
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005427 if (!out->standby) {
5428 if (!same_dev) {
5429 ALOGV("update routing change");
5430 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
5431 adev->perf_lock_opts,
5432 adev->perf_lock_opts_size);
5433 if (adev->adm_on_routing_change)
5434 adev->adm_on_routing_change(adev->adm_data,
5435 out->handle);
5436 }
5437 if (!bypass_a2dp) {
5438 select_devices(adev, out->usecase);
5439 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005440 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
5441 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005442 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005443 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005444 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005445 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005446 }
5447
5448 if (!same_dev) {
5449 // on device switch force swap, lower functions will make sure
5450 // to check if swap is allowed or not.
5451 platform_set_swap_channels(adev, true);
5452 audio_extn_perf_lock_release(&adev->perf_lock_handle);
5453 }
Zhou Songbaddf9f2020-11-20 13:57:39 +08005454 pthread_mutex_lock(&out->latch_lock);
5455 if (!is_a2dp_out_device_type(&out->device_list) || audio_extn_a2dp_source_is_ready()) {
5456 if (out->a2dp_muted) {
5457 out->a2dp_muted = false;
5458 if (is_offload_usecase(out->usecase))
5459 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5460 else if (out->usecase != USECASE_AUDIO_PLAYBACK_VOIP)
5461 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Weiyin Jiang280ea742020-09-08 20:28:22 +08005462 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005463 }
Zhou Songbaddf9f2020-11-20 13:57:39 +08005464 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP && !out->a2dp_muted)
5465 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
5466 pthread_mutex_unlock(&out->latch_lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005467 }
5468 }
5469
5470 pthread_mutex_unlock(&adev->lock);
5471 pthread_mutex_unlock(&out->lock);
5472
5473 /*handles device and call state changes*/
5474 audio_extn_extspk_update(adev->extspk);
5475
Revathi Uddaraju4255a632021-12-02 05:11:13 -08005476 clear_devices(&new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005477error:
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005478 ALOGV("%s: exit: code(%d)", __func__, ret);
5479 return ret;
5480}
5481
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005482static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
5483{
5484 struct stream_out *out = (struct stream_out *)stream;
5485 struct audio_device *adev = out->dev;
5486 struct str_parms *parms;
5487 char value[32];
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005488 int ret = 0, err;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005489 int ext_controller = -1;
5490 int ext_stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005491
sangwoobc677242013-08-08 16:53:43 +09005492 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005493 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005494 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305495 if (!parms)
5496 goto error;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005497
5498 err = platform_get_controller_stream_from_params(parms, &ext_controller,
5499 &ext_stream);
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08005500 if (err == 0) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005501 out->extconn.cs.controller = ext_controller;
5502 out->extconn.cs.stream = ext_stream;
5503 ALOGD("%s: usecase(%s) new controller/stream (%d/%d)", __func__,
5504 use_case_table[out->usecase], out->extconn.cs.controller,
5505 out->extconn.cs.stream);
5506 }
5507
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005508 if (out == adev->primary_output) {
5509 pthread_mutex_lock(&adev->lock);
5510 audio_extn_set_parameters(adev, parms);
5511 pthread_mutex_unlock(&adev->lock);
5512 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005513 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005514 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005515 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005516
5517 audio_extn_dts_create_state_notifier_node(out->usecase);
5518 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5519 popcount(out->channel_mask),
5520 out->playback_started);
5521
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08005522 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005523 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005524
Surendar Karkaf51b5842018-04-26 11:28:38 +05305525 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
5526 sizeof(value));
5527 if (err >= 0) {
5528 if (!strncmp("true", value, sizeof("true")) || atoi(value))
5529 audio_extn_send_dual_mono_mixing_coefficients(out);
5530 }
5531
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305532 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5533 if (err >= 0) {
5534 strlcpy(out->profile, value, sizeof(out->profile));
5535 ALOGV("updating stream profile with value '%s'", out->profile);
5536 lock_output_stream(out);
5537 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
5538 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005539 &out->device_list, out->flags,
5540 out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305541 out->sample_rate, out->bit_width,
5542 out->channel_mask, out->profile,
5543 &out->app_type_cfg);
5544 pthread_mutex_unlock(&out->lock);
5545 }
5546
Alexy Joseph98988832017-01-13 14:56:59 -08005547 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005548 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
5549 // and vendor.audio.hal.output.suspend.supported is set to true
5550 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08005551 //check suspend parameter only for low latency and if the property
5552 //is enabled
5553 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
5554 ALOGI("%s: got suspend_playback %s", __func__, value);
5555 lock_output_stream(out);
5556 if (!strncmp(value, "false", 5)) {
5557 //suspend_playback=false is supposed to set QOS value back to 75%
5558 //the mixer control sent with value Enable will achieve that
5559 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5560 } else if (!strncmp (value, "true", 4)) {
5561 //suspend_playback=true is supposed to remove QOS value
5562 //resetting the mixer control will set the default value
5563 //for the mixer control which is Disable and this removes the QOS vote
5564 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5565 } else {
5566 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
5567 " got %s", __func__, value);
5568 ret = -1;
5569 }
5570
5571 if (ret != 0) {
5572 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
5573 __func__, out->pm_qos_mixer_path, ret);
5574 }
5575
5576 pthread_mutex_unlock(&out->lock);
5577 }
5578 }
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005579
Alexy Joseph98988832017-01-13 14:56:59 -08005580 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005581 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305582error:
Eric Laurent994a6932013-07-17 11:51:42 -07005583 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005584 return ret;
5585}
5586
Paul McLeana50b7332018-12-17 08:24:21 -07005587static int in_set_microphone_direction(const struct audio_stream_in *stream,
5588 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07005589 struct stream_in *in = (struct stream_in *)stream;
5590
5591 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
5592
5593 in->direction = dir;
5594
5595 if (in->standby)
5596 return 0;
5597
5598 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07005599}
5600
5601static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07005602 struct stream_in *in = (struct stream_in *)stream;
5603
5604 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
5605
5606 if (zoom > 1.0 || zoom < -1.0)
5607 return -EINVAL;
5608
5609 in->zoom = zoom;
5610
5611 if (in->standby)
5612 return 0;
5613
5614 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07005615}
5616
5617
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005618static bool stream_get_parameter_channels(struct str_parms *query,
5619 struct str_parms *reply,
5620 audio_channel_mask_t *supported_channel_masks) {
5621 int ret = -1;
5622 char value[512];
5623 bool first = true;
5624 size_t i, j;
5625
5626 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
5627 ret = 0;
5628 value[0] = '\0';
5629 i = 0;
5630 while (supported_channel_masks[i] != 0) {
5631 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5632 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
5633 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305634 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005635
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305636 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005637 first = false;
5638 break;
5639 }
5640 }
5641 i++;
5642 }
5643 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5644 }
5645 return ret == 0;
5646}
5647
5648static bool stream_get_parameter_formats(struct str_parms *query,
5649 struct str_parms *reply,
5650 audio_format_t *supported_formats) {
5651 int ret = -1;
5652 char value[256];
5653 size_t i, j;
5654 bool first = true;
5655
5656 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
5657 ret = 0;
5658 value[0] = '\0';
5659 i = 0;
5660 while (supported_formats[i] != 0) {
5661 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5662 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
5663 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305664 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005665 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305666 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005667 first = false;
5668 break;
5669 }
5670 }
5671 i++;
5672 }
5673 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
5674 }
5675 return ret == 0;
5676}
5677
5678static bool stream_get_parameter_rates(struct str_parms *query,
5679 struct str_parms *reply,
5680 uint32_t *supported_sample_rates) {
5681
5682 int i;
5683 char value[256];
5684 int ret = -1;
5685 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
5686 ret = 0;
5687 value[0] = '\0';
5688 i=0;
5689 int cursor = 0;
5690 while (supported_sample_rates[i]) {
5691 int avail = sizeof(value) - cursor;
5692 ret = snprintf(value + cursor, avail, "%s%d",
5693 cursor > 0 ? "|" : "",
5694 supported_sample_rates[i]);
5695 if (ret < 0 || ret >= avail) {
5696 // if cursor is at the last element of the array
5697 // overwrite with \0 is duplicate work as
5698 // snprintf already put a \0 in place.
5699 // else
5700 // we had space to write the '|' at value[cursor]
5701 // (which will be overwritten) or no space to fill
5702 // the first element (=> cursor == 0)
5703 value[cursor] = '\0';
5704 break;
5705 }
5706 cursor += ret;
5707 ++i;
5708 }
5709 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
5710 value);
5711 }
5712 return ret >= 0;
5713}
5714
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005715static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
5716{
5717 struct stream_out *out = (struct stream_out *)stream;
5718 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005719 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005720 char value[256];
5721 struct str_parms *reply = str_parms_create();
5722 size_t i, j;
5723 int ret;
5724 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005725
5726 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005727 if (reply) {
5728 str_parms_destroy(reply);
5729 }
5730 if (query) {
5731 str_parms_destroy(query);
5732 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005733 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
5734 return NULL;
5735 }
5736
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005737 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005738 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
5739 if (ret >= 0) {
5740 value[0] = '\0';
5741 i = 0;
5742 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005743 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5744 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005745 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005746 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005747 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005748 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005749 first = false;
5750 break;
5751 }
5752 }
5753 i++;
5754 }
5755 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5756 str = str_parms_to_str(reply);
5757 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005758 voice_extn_out_get_parameters(out, query, reply);
5759 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005760 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005761
Alexy Joseph62142aa2015-11-16 15:10:34 -08005762
5763 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
5764 if (ret >= 0) {
5765 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05305766 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
5767 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08005768 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305769 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005770 } else {
5771 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05305772 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005773 }
5774 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005775 if (str)
5776 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08005777 str = str_parms_to_str(reply);
5778 }
5779
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005780 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
5781 if (ret >= 0) {
5782 value[0] = '\0';
5783 i = 0;
5784 first = true;
5785 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005786 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5787 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005788 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005789 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005790 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005791 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005792 first = false;
5793 break;
5794 }
5795 }
5796 i++;
5797 }
5798 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005799 if (str)
5800 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005801 str = str_parms_to_str(reply);
5802 }
Mingming Yin3a941d42016-02-17 18:08:05 -08005803
5804 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
5805 if (ret >= 0) {
5806 value[0] = '\0';
5807 i = 0;
5808 first = true;
5809 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005810 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
5811 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005812 if (!first) {
5813 strlcat(value, "|", sizeof(value));
5814 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005815 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08005816 first = false;
5817 break;
5818 }
5819 }
5820 i++;
5821 }
5822 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
5823 if (str)
5824 free(str);
5825 str = str_parms_to_str(reply);
5826 }
5827
Alexy Joseph98988832017-01-13 14:56:59 -08005828 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
5829 //only low latency track supports suspend_resume
5830 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005831 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08005832 if (str)
5833 free(str);
5834 str = str_parms_to_str(reply);
5835 }
5836
5837
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005838 str_parms_destroy(query);
5839 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07005840 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005841 return str;
5842}
5843
5844static uint32_t out_get_latency(const struct audio_stream_out *stream)
5845{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005846 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005847 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08005848 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005849
Alexy Josephaa54c872014-12-03 02:46:47 -08005850 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05305851 lock_output_stream(out);
5852 latency = audio_extn_utils_compress_get_dsp_latency(out);
5853 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005854 } else if ((out->realtime) ||
5855 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005856 // since the buffer won't be filled up faster than realtime,
5857 // return a smaller number
5858 if (out->config.rate)
5859 period_ms = (out->af_period_multiplier * out->config.period_size *
5860 1000) / (out->config.rate);
5861 else
5862 period_ms = 0;
George Gao9ba8a142020-07-23 14:30:03 -07005863 latency = period_ms + platform_render_latency(out) / 1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005864 } else {
5865 latency = (out->config.period_count * out->config.period_size * 1000) /
Mingshu Pangf69a88d2021-04-30 16:14:39 +08005866 (out->config.rate);
pavanisra2d95d82022-02-09 18:55:58 +05305867 if (out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5868 out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY)
Mingshu Pangf69a88d2021-04-30 16:14:39 +08005869 latency += platform_render_latency(out)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005870 }
5871
Zhou Songd2537a02020-06-11 22:04:46 +08005872 if (!out->standby && is_a2dp_out_device_type(&out->device_list))
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08005873 latency += audio_extn_a2dp_get_encoder_latency();
5874
Anish Kumar50ebcbf2014-12-09 04:01:39 +05305875 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08005876 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005877}
5878
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305879static float AmpToDb(float amplification)
5880{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305881 float db = DSD_VOLUME_MIN_DB;
5882 if (amplification > 0) {
5883 db = 20 * log10(amplification);
5884 if(db < DSD_VOLUME_MIN_DB)
5885 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305886 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305887 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305888}
5889
Krishna Kishor Jha10ad39f2022-02-21 17:02:47 +05305890#ifdef SOFT_VOLUME
5891static int out_set_soft_volume_params(struct audio_stream_out *stream)
5892{
5893 struct stream_out *out = (struct stream_out *)stream;
5894 int ret = 0;
5895 char mixer_ctl_name[128];
5896 struct audio_device *adev = out->dev;
5897 struct mixer_ctl *ctl = NULL;
5898 struct soft_step_volume_params *volume_params = NULL;
5899
5900 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5901 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Soft Vol Params", pcm_device_id);
5902 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5903 if (!ctl) {
5904 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5905 return -EINVAL;
5906 }
5907
5908 volume_params =(struct soft_step_volume_params * ) malloc(sizeof(struct soft_step_volume_params));
5909 if (volume_params == NULL){
5910 ALOGE("%s : malloc is failed for volume params", __func__);
5911 return -EINVAL;
5912 } else {
5913 ret = platform_get_soft_step_volume_params(volume_params,out->usecase);
5914 if (ret < 0) {
5915 ALOGE("%s : platform_get_soft_step_volume_params is fialed", __func__);
Karan Naidu28b335a2022-05-18 23:00:08 +05305916 ret = -EINVAL;
5917 goto ERR_EXIT;
Krishna Kishor Jha10ad39f2022-02-21 17:02:47 +05305918 }
5919
5920 }
5921 ret = mixer_ctl_set_array(ctl, volume_params, sizeof(struct soft_step_volume_params)/sizeof(int));
5922 if (ret < 0) {
5923 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
Karan Naidu28b335a2022-05-18 23:00:08 +05305924 ret = -EINVAL;
5925 goto ERR_EXIT;
5926 }
5927
5928 if (volume_params) {
5929 free(volume_params);
Krishna Kishor Jha10ad39f2022-02-21 17:02:47 +05305930 }
5931 return 0;
Karan Naidu28b335a2022-05-18 23:00:08 +05305932
5933ERR_EXIT:
5934 if (volume_params) {
5935 free(volume_params);
5936 }
5937 return ret;
Krishna Kishor Jha10ad39f2022-02-21 17:02:47 +05305938}
5939#endif
5940
Arun Mirpuri5d170872019-03-26 13:21:31 -07005941static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
5942 float right)
5943{
5944 struct stream_out *out = (struct stream_out *)stream;
5945 long volume = 0;
5946 char mixer_ctl_name[128] = "";
5947 struct audio_device *adev = out->dev;
5948 struct mixer_ctl *ctl = NULL;
5949 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5950 PCM_PLAYBACK);
5951
5952 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5953 "Playback %d Volume", pcm_device_id);
5954 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5955 if (!ctl) {
5956 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5957 __func__, mixer_ctl_name);
5958 return -EINVAL;
5959 }
5960 if (left != right)
5961 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
5962 __func__, left, right);
5963 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
5964 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
5965 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
5966 __func__, mixer_ctl_name, volume);
5967 return -EINVAL;
5968 }
5969 return 0;
5970}
5971
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305972static int out_set_compr_volume(struct audio_stream_out *stream, float left,
5973 float right)
5974{
5975 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305976 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305977 char mixer_ctl_name[128];
5978 struct audio_device *adev = out->dev;
5979 struct mixer_ctl *ctl;
5980 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5981 PCM_PLAYBACK);
5982
5983 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5984 "Compress Playback %d Volume", pcm_device_id);
5985 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5986 if (!ctl) {
5987 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5988 __func__, mixer_ctl_name);
5989 return -EINVAL;
5990 }
5991 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
5992 __func__, mixer_ctl_name, left, right);
5993 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
5994 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
5995 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5996
5997 return 0;
5998}
5999
Zhou Song2b8f28f2017-09-11 10:51:38 +08006000static int out_set_voip_volume(struct audio_stream_out *stream, float left,
6001 float right)
6002{
6003 struct stream_out *out = (struct stream_out *)stream;
6004 char mixer_ctl_name[] = "App Type Gain";
6005 struct audio_device *adev = out->dev;
6006 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05306007 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08006008
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07006009 if (!is_valid_volume(left, right)) {
6010 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
6011 __func__, left, right);
6012 return -EINVAL;
6013 }
6014
Zhou Song2b8f28f2017-09-11 10:51:38 +08006015 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
6016 if (!ctl) {
6017 ALOGE("%s: Could not get ctl for mixer cmd - %s",
6018 __func__, mixer_ctl_name);
6019 return -EINVAL;
6020 }
6021
6022 set_values[0] = 0; //0: Rx Session 1:Tx Session
6023 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05306024 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
6025 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08006026
6027 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
6028 return 0;
6029}
6030
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05306031static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
6032 float right)
6033{
6034 struct stream_out *out = (struct stream_out *)stream;
6035 /* Volume control for pcm playback */
6036 if (left != right) {
6037 return -EINVAL;
6038 } else {
6039 char mixer_ctl_name[128];
6040 struct audio_device *adev = out->dev;
6041 struct mixer_ctl *ctl;
6042 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
6043 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
6044 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
6045 if (!ctl) {
6046 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
6047 return -EINVAL;
6048 }
6049
6050 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
6051 int ret = mixer_ctl_set_value(ctl, 0, volume);
6052 if (ret < 0) {
6053 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
6054 return -EINVAL;
6055 }
6056
6057 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
6058
6059 return 0;
6060 }
6061}
6062
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006063static int out_set_volume(struct audio_stream_out *stream, float left,
6064 float right)
6065{
Eric Laurenta9024de2013-04-04 09:19:12 -07006066 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006067 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306068 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006069
Arun Mirpuri5d170872019-03-26 13:21:31 -07006070 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07006071 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
6072 /* only take left channel into account: the API is for stereo anyway */
6073 out->muted = (left == 0.0f);
6074 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006075 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306076 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006077 /*
6078 * Set mute or umute on HDMI passthrough stream.
6079 * Only take left channel into account.
6080 * Mute is 0 and unmute 1
6081 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306082 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306083 } else if (out->format == AUDIO_FORMAT_DSD){
6084 char mixer_ctl_name[128] = "DSD Volume";
6085 struct audio_device *adev = out->dev;
6086 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
6087
6088 if (!ctl) {
6089 ALOGE("%s: Could not get ctl for mixer cmd - %s",
6090 __func__, mixer_ctl_name);
6091 return -EINVAL;
6092 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05306093 volume[0] = (long)(AmpToDb(left));
6094 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306095 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
6096 return 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006097 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS) &&
Derek Chendf05eea2019-08-01 13:57:49 -07006098 (out->car_audio_stream == CAR_AUDIO_STREAM_MEDIA)) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07006099 ALOGD("%s: Overriding offload set volume for media bus stream", __func__);
6100 struct listnode *node = NULL;
6101 list_for_each(node, &adev->active_outputs_list) {
6102 streams_output_ctxt_t *out_ctxt = node_to_item(node,
6103 streams_output_ctxt_t,
6104 list);
6105 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
6106 out->volume_l = out_ctxt->output->volume_l;
6107 out->volume_r = out_ctxt->output->volume_r;
6108 }
6109 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08006110 pthread_mutex_lock(&out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +08006111 if (!out->a2dp_muted) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07006112 ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
6113 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08006114 pthread_mutex_unlock(&out->latch_lock);
Philippe Gravel1c9ac352019-05-28 16:08:37 -07006115 return ret;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006116 } else {
Weiyin Jiang280ea742020-09-08 20:28:22 +08006117 pthread_mutex_lock(&out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +08006118 ALOGV("%s: compress mute %d", __func__, out->a2dp_muted);
6119 if (!out->a2dp_muted)
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306120 ret = out_set_compr_volume(stream, left, right);
6121 out->volume_l = left;
6122 out->volume_r = right;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006123 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306124 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006125 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07006126 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08006127 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
6128 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Songbaddf9f2020-11-20 13:57:39 +08006129 pthread_mutex_lock(&out->latch_lock);
Aalique Grahame22e49102018-12-18 14:23:57 -08006130 if (!out->standby) {
6131 audio_extn_utils_send_app_type_gain(out->dev,
6132 out->app_type_cfg.app_type,
6133 &out->app_type_cfg.gain[0]);
Zhou Songbaddf9f2020-11-20 13:57:39 +08006134 if (!out->a2dp_muted)
6135 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08006136 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08006137 out->volume_l = left;
6138 out->volume_r = right;
Zhou Songbaddf9f2020-11-20 13:57:39 +08006139 pthread_mutex_unlock(&out->latch_lock);
Zhou Song2b8f28f2017-09-11 10:51:38 +08006140 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006141 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
6142 ALOGV("%s: MMAP set volume called", __func__);
6143 if (!out->standby)
6144 ret = out_set_mmap_volume(stream, left, right);
6145 out->volume_l = left;
6146 out->volume_r = right;
6147 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05306148 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05306149 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
6150 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Zhou Songbaddf9f2020-11-20 13:57:39 +08006151 pthread_mutex_lock(&out->latch_lock);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05306152 /* Volume control for pcm playback */
Zhou Songbaddf9f2020-11-20 13:57:39 +08006153 if (!out->standby && !out->a2dp_muted)
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05306154 ret = out_set_pcm_volume(stream, left, right);
6155 else
6156 out->apply_volume = true;
6157
6158 out->volume_l = left;
6159 out->volume_r = right;
Zhou Songbaddf9f2020-11-20 13:57:39 +08006160 pthread_mutex_unlock(&out->latch_lock);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05306161 return ret;
Derek Chenf13dd492018-11-13 14:53:51 -08006162 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
6163 ALOGV("%s: bus device set volume called", __func__);
Zhou Songbaddf9f2020-11-20 13:57:39 +08006164 pthread_mutex_lock(&out->latch_lock);
6165 if (!out->standby && !out->a2dp_muted)
Derek Chenf13dd492018-11-13 14:53:51 -08006166 ret = out_set_pcm_volume(stream, left, right);
6167 out->volume_l = left;
6168 out->volume_r = right;
Zhou Songbaddf9f2020-11-20 13:57:39 +08006169 pthread_mutex_unlock(&out->latch_lock);
Derek Chenf13dd492018-11-13 14:53:51 -08006170 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07006171 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006172
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006173 return -ENOSYS;
6174}
6175
Zhou Songc9672822017-08-16 16:01:39 +08006176static void update_frames_written(struct stream_out *out, size_t bytes)
6177{
6178 size_t bpf = 0;
6179
6180 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
6181 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
6182 bpf = 1;
6183 else if (!is_offload_usecase(out->usecase))
6184 bpf = audio_bytes_per_sample(out->format) *
6185 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08006186
6187 pthread_mutex_lock(&out->position_query_lock);
6188 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08006189 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08006190 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
6191 }
6192 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08006193}
6194
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006195int split_and_write_audio_haptic_data(struct stream_out *out,
6196 const void *buffer, size_t bytes_to_write)
6197{
6198 struct audio_device *adev = out->dev;
6199
6200 int ret = 0;
6201 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
6202 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
6203 size_t frame_size = channel_count * bytes_per_sample;
6204 size_t frame_count = bytes_to_write / frame_size;
6205
6206 bool force_haptic_path =
6207 property_get_bool("vendor.audio.test_haptic", false);
6208
6209 // extract Haptics data from Audio buffer
6210 bool alloc_haptic_buffer = false;
6211 int haptic_channel_count = adev->haptics_config.channels;
6212 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
6213 size_t audio_frame_size = frame_size - haptic_frame_size;
6214 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
6215
6216 if (adev->haptic_buffer == NULL) {
6217 alloc_haptic_buffer = true;
6218 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
6219 free(adev->haptic_buffer);
6220 adev->haptic_buffer_size = 0;
6221 alloc_haptic_buffer = true;
6222 }
6223
6224 if (alloc_haptic_buffer) {
6225 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08006226 if(adev->haptic_buffer == NULL) {
6227 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
6228 return -ENOMEM;
6229 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006230 adev->haptic_buffer_size = total_haptic_buffer_size;
6231 }
6232
6233 size_t src_index = 0, aud_index = 0, hap_index = 0;
6234 uint8_t *audio_buffer = (uint8_t *)buffer;
6235 uint8_t *haptic_buffer = adev->haptic_buffer;
6236
6237 // This is required for testing only. This works for stereo data only.
6238 // One channel is fed to audio stream and other to haptic stream for testing.
6239 if (force_haptic_path)
6240 audio_frame_size = haptic_frame_size = bytes_per_sample;
6241
6242 for (size_t i = 0; i < frame_count; i++) {
6243 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
6244 audio_frame_size);
6245 aud_index += audio_frame_size;
6246 src_index += audio_frame_size;
6247
6248 if (adev->haptic_pcm)
6249 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
6250 haptic_frame_size);
6251 hap_index += haptic_frame_size;
6252 src_index += haptic_frame_size;
6253
6254 // This is required for testing only.
6255 // Discard haptic channel data.
6256 if (force_haptic_path)
6257 src_index += haptic_frame_size;
6258 }
6259
6260 // write to audio pipeline
6261 ret = pcm_write(out->pcm, (void *)audio_buffer,
6262 frame_count * audio_frame_size);
6263
6264 // write to haptics pipeline
6265 if (adev->haptic_pcm)
6266 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
6267 frame_count * haptic_frame_size);
6268
6269 return ret;
6270}
6271
Aalique Grahame22e49102018-12-18 14:23:57 -08006272#ifdef NO_AUDIO_OUT
6273static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
6274 const void *buffer __unused, size_t bytes)
6275{
6276 struct stream_out *out = (struct stream_out *)stream;
6277
6278 /* No Output device supported other than BT for playback.
6279 * Sleep for the amount of buffer duration
6280 */
6281 lock_output_stream(out);
6282 usleep(bytes * 1000000 / audio_stream_out_frame_size(
6283 (const struct audio_stream_out *)&out->stream) /
6284 out_get_sample_rate(&out->stream.common));
6285 pthread_mutex_unlock(&out->lock);
6286 return bytes;
6287}
6288#endif
6289
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006290static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
6291 size_t bytes)
6292{
6293 struct stream_out *out = (struct stream_out *)stream;
6294 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07006295 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05306296 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006297 const size_t frame_size = audio_stream_out_frame_size(stream);
6298 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05306299 struct audio_usecase *usecase = NULL;
Meng Wang4c32fb42020-01-16 17:57:11 +08006300 uint32_t compr_passthr = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006301
Haynes Mathew George380745d2017-10-04 15:27:45 -07006302 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006303 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306304
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05006305 if (CARD_STATUS_OFFLINE == out->card_status ||
6306 POWER_POLICY_STATUS_OFFLINE == adev->out_power_policy) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08006307
Dhananjay Kumarac341582017-02-23 23:42:25 +05306308 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306309 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05306310 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
6311 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006312 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05306313 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05306314 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05306315 ALOGD(" %s: sound card is not active/SSR state", __func__);
6316 ret= -EIO;
6317 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306318 }
6319 }
6320
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306321 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05306322 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05306323 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306324 goto exit;
6325 }
6326
Haynes Mathew George16081042017-05-31 17:16:49 -07006327 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
6328 ret = -EINVAL;
6329 goto exit;
6330 }
6331
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006332 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306333 !out->is_iec61937_info_available) {
6334
6335 if (!audio_extn_passthru_is_passthrough_stream(out)) {
6336 out->is_iec61937_info_available = true;
6337 } else if (audio_extn_passthru_is_enabled()) {
6338 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05306339 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05306340
6341 if((out->format == AUDIO_FORMAT_DTS) ||
6342 (out->format == AUDIO_FORMAT_DTS_HD)) {
6343 ret = audio_extn_passthru_update_dts_stream_configuration(out,
6344 buffer, bytes);
6345 if (ret) {
6346 if (ret != -ENOSYS) {
6347 out->is_iec61937_info_available = false;
6348 ALOGD("iec61937 transmission info not yet updated retry");
6349 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306350 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05306351 /* if stream has started and after that there is
6352 * stream config change (iec transmission config)
6353 * then trigger select_device to update backend configuration.
6354 */
6355 out->stream_config_changed = true;
6356 pthread_mutex_lock(&adev->lock);
6357 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306358 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08006359 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306360 ret = -EINVAL;
6361 goto exit;
6362 }
Manish Dewangan671a4202017-08-18 17:30:46 +05306363 pthread_mutex_unlock(&adev->lock);
6364 out->stream_config_changed = false;
6365 out->is_iec61937_info_available = true;
6366 }
6367 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05306368
Meng Wang4c32fb42020-01-16 17:57:11 +08006369#ifdef AUDIO_GKI_ENABLED
6370 /* out->compr_config.codec->reserved[0] is for compr_passthr */
6371 compr_passthr = out->compr_config.codec->reserved[0];
6372#else
6373 compr_passthr = out->compr_config.codec->compr_passthr;
6374#endif
6375
Garmond Leung317cbf12017-09-13 16:20:50 -07006376 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Meng Wang4c32fb42020-01-16 17:57:11 +08006377 (compr_passthr == PASSTHROUGH) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05306378 (out->is_iec61937_info_available == true)) {
6379 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
6380 ret = -EINVAL;
6381 goto exit;
6382 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05306383 }
6384 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306385
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006386 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02006387 (audio_extn_a2dp_source_is_suspended())) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006388 if (!(compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER) ||
6389 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Zhou Songd01e7a22020-09-23 22:49:01 +08006390 if (!is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306391 ret = -EIO;
6392 goto exit;
6393 }
6394 }
6395 }
6396
Weiyin Jiangabedea32020-12-09 12:49:19 +08006397 if (is_usb_out_device_type(&out->device_list) &&
6398 !audio_extn_usb_connected(NULL)) {
6399 ret = -EIO;
6400 goto exit;
6401 }
6402
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006403 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07006404 out->standby = false;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006405 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
6406
Eric Laurent150dbfe2013-02-27 14:31:02 -08006407 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006408 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
6409 ret = voice_extn_compress_voip_start_output_stream(out);
6410 else
6411 ret = start_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006412 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006413 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07006414 out->standby = true;
Weiyin Jiangac2bae82020-07-29 17:23:53 +08006415 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006416 goto exit;
6417 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306418 out->started = 1;
Andy Hunga1f48fa2019-07-01 18:14:53 -07006419 out->last_fifo_valid = false; // we're coming out of standby, last_fifo isn't valid.
Weiyin Jiangac2bae82020-07-29 17:23:53 +08006420
6421 if ((last_known_cal_step != -1) && (adev->platform != NULL)) {
vivek mehtab72d08d2016-04-29 03:16:47 -07006422 ALOGD("%s: retry previous failed cal level set", __func__);
Weiyin Jiangac2bae82020-07-29 17:23:53 +08006423 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05306424 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07006425 }
Weiyin Jiangac2bae82020-07-29 17:23:53 +08006426 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306427
6428 if ((out->is_iec61937_info_available == true) &&
6429 (audio_extn_passthru_is_passthrough_stream(out))&&
6430 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
6431 ret = -EINVAL;
6432 goto exit;
6433 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05306434 if (out->set_dual_mono)
6435 audio_extn_send_dual_mono_mixing_coefficients(out);
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006436
Dechen Chai22768452021-07-30 09:29:16 +05306437#ifndef LINUX_ENABLED
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006438 // log startup time in ms.
6439 simple_stats_log(
6440 &out->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Dechen Chai22768452021-07-30 09:29:16 +05306441#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006442 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006443
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006444 if (adev->is_channel_status_set == false &&
6445 compare_device_type(&out->device_list,
6446 AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Alexy Josephb1379942016-01-29 15:49:38 -08006447 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05306448 adev->is_channel_status_set = true;
6449 }
6450
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05306451 if ((adev->use_old_pspd_mix_ctrl == true) &&
6452 (out->pspd_coeff_sent == false)) {
6453 /*
6454 * Need to resend pspd coefficients after stream started for
6455 * older kernel version as it does not save the coefficients
6456 * and also stream has to be started for coeff to apply.
6457 */
6458 usecase = get_usecase_from_list(adev, out->usecase);
6459 if (usecase != NULL) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05306460 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05306461 out->pspd_coeff_sent = true;
6462 }
6463 }
6464
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006465 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08006466 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006467 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006468 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006469 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
6470 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05306471 if (out->send_next_track_params && out->is_compr_metadata_avail) {
6472 ALOGD("copl(%p):send next track params in gapless", out);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08006473 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05306474 out->send_next_track_params = false;
6475 out->is_compr_metadata_avail = false;
6476 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006477 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05306478 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306479 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006480
Ashish Jain83a6cc22016-06-28 14:34:17 +05306481 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05306482 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05306483 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05306484 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006485 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05306486 return -EINVAL;
6487 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05306488 audio_format_t dst_format = out->hal_op_format;
6489 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306490
Dieter Luecking5d57def2018-09-07 14:23:37 +02006491 /* prevent division-by-zero */
6492 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
6493 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
6494 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
6495 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05306496 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006497 ATRACE_END();
6498 return -EINVAL;
6499 }
6500
Ashish Jainf1eaa582016-05-23 20:54:24 +05306501 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
6502 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
6503
Ashish Jain83a6cc22016-06-28 14:34:17 +05306504 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05306505 dst_format,
6506 buffer,
6507 src_format,
6508 frames);
6509
Ashish Jain83a6cc22016-06-28 14:34:17 +05306510 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05306511 bytes_to_write);
6512
6513 /*Convert written bytes in audio flinger format*/
6514 if (ret > 0)
6515 ret = ((ret * format_to_bitwidth_table[out->format]) /
6516 format_to_bitwidth_table[dst_format]);
6517 }
6518 } else
6519 ret = compress_write(out->compr, buffer, bytes);
6520
Zhou Songc9672822017-08-16 16:01:39 +08006521 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
6522 update_frames_written(out, bytes);
6523
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306524 if (ret < 0)
6525 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08006526 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05306527 /*msg to cb thread only if non blocking write is enabled*/
6528 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05306529 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006530 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05306531 } else if (-ENETRESET == ret) {
6532 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306533 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05306534 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05306535 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006536 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05306537 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006538 }
Ashish Jain5106d362016-05-11 19:23:33 +05306539
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05306540 /* Call compr start only when non-zero bytes of data is there to be rendered */
6541 if (!out->playback_started && ret > 0) {
6542 int status = compress_start(out->compr);
6543 if (status < 0) {
6544 ret = status;
6545 ALOGE("%s: compr start failed with err %d", __func__, errno);
6546 goto exit;
6547 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07006548 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006549 out->playback_started = 1;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006550 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006551 out->offload_state = OFFLOAD_STATE_PLAYING;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006552 pthread_mutex_unlock(&out->latch_lock);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006553
6554 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6555 popcount(out->channel_mask),
6556 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006557 }
6558 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006559 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006560 return ret;
6561 } else {
6562 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006563 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006564 if (out->muted)
6565 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006566 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
6567 __func__, frames, frame_size, bytes_to_write);
6568
Aalique Grahame22e49102018-12-18 14:23:57 -08006569 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07006570 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
6571 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
6572 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006573 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
6574 int16_t *src = (int16_t *)buffer;
6575 int16_t *dst = (int16_t *)buffer;
6576
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006577 LOG_ALWAYS_FATAL_IF(channel_count > 2 ||
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006578 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08006579 "out_write called for %s use case with wrong properties",
6580 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006581
6582 /*
6583 * FIXME: this can be removed once audio flinger mixer supports
6584 * mono output
6585 */
6586
6587 /*
6588 * Code below goes over each frame in the buffer and adds both
6589 * L and R samples and then divides by 2 to convert to mono
6590 */
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006591 if (channel_count == 2) {
6592 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
6593 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
6594 }
6595 bytes_to_write /= 2;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006596 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006597 }
Andy Hunga1f48fa2019-07-01 18:14:53 -07006598
6599 // Note: since out_get_presentation_position() is called alternating with out_write()
6600 // by AudioFlinger, we can check underruns using the prior timestamp read.
6601 // (Alternately we could check if the buffer is empty using pcm_get_htimestamp().
6602 if (out->last_fifo_valid) {
6603 // compute drain to see if there is an underrun.
6604 const int64_t current_ns = systemTime(SYSTEM_TIME_MONOTONIC); // sys call
Dhananjay Kumara4429632020-07-11 02:53:37 +05306605 int64_t time_diff_ns = current_ns - out->last_fifo_time_ns;
6606 int64_t frames_by_time =
6607 ((time_diff_ns > 0) && (time_diff_ns < (INT64_MAX / out->config.rate))) ?
6608 (time_diff_ns * out->config.rate / NANOS_PER_SECOND) : 0;
Andy Hunga1f48fa2019-07-01 18:14:53 -07006609 const int64_t underrun = frames_by_time - out->last_fifo_frames_remaining;
6610
6611 if (underrun > 0) {
Dechen Chai22768452021-07-30 09:29:16 +05306612#ifndef LINUX_ENABLED
Andy Hunga1f48fa2019-07-01 18:14:53 -07006613 simple_stats_log(&out->fifo_underruns, underrun);
Dechen Chai22768452021-07-30 09:29:16 +05306614#endif
Andy Hunga1f48fa2019-07-01 18:14:53 -07006615
6616 ALOGW("%s: underrun(%lld) "
6617 "frames_by_time(%lld) > out->last_fifo_frames_remaining(%lld)",
6618 __func__,
6619 (long long)out->fifo_underruns.n,
6620 (long long)frames_by_time,
6621 (long long)out->last_fifo_frames_remaining);
6622 }
6623 out->last_fifo_valid = false; // we're writing below, mark fifo info as stale.
6624 }
6625
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306626 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006627
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006628 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006629
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006630 if (out->config.rate)
6631 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
6632 out->config.rate;
6633
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006634 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006635 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
6636
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006637 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006638 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006639 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306640 out->convert_buffer != NULL) {
6641
6642 memcpy_by_audio_format(out->convert_buffer,
6643 out->hal_op_format,
6644 buffer,
6645 out->hal_ip_format,
6646 out->config.period_size * out->config.channels);
6647
6648 ret = pcm_write(out->pcm, out->convert_buffer,
6649 (out->config.period_size *
6650 out->config.channels *
6651 format_to_bitwidth_table[out->hal_op_format]));
6652 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05306653 /*
6654 * To avoid underrun in DSP when the application is not pumping
6655 * data at required rate, check for the no. of bytes and ignore
6656 * pcm_write if it is less than actual buffer size.
6657 * It is a work around to a change in compress VOIP driver.
6658 */
6659 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
6660 bytes < (out->config.period_size * out->config.channels *
6661 audio_bytes_per_sample(out->format))) {
6662 size_t voip_buf_size =
6663 out->config.period_size * out->config.channels *
6664 audio_bytes_per_sample(out->format);
6665 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
6666 __func__, bytes, voip_buf_size);
6667 usleep(((uint64_t)voip_buf_size - bytes) *
6668 1000000 / audio_stream_out_frame_size(stream) /
6669 out_get_sample_rate(&out->stream.common));
6670 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006671 } else {
6672 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
6673 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
6674 else
6675 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
6676 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306677 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006678
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006679 release_out_focus(out);
6680
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306681 if (ret < 0)
6682 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08006683 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05306684 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006685 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006686 }
6687
6688exit:
Zhou Songc9672822017-08-16 16:01:39 +08006689 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306690 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306691 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306692 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006693 pthread_mutex_unlock(&out->lock);
6694
6695 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006696 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08006697 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306698 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306699 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306700 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306701 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306702 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306703 out->standby = true;
6704 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306705 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006706 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
6707 /* prevent division-by-zero */
6708 uint32_t stream_size = audio_stream_out_frame_size(stream);
6709 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006710
Dieter Luecking5d57def2018-09-07 14:23:37 +02006711 if ((stream_size == 0) || (srate == 0)) {
6712 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
6713 ATRACE_END();
6714 return -EINVAL;
6715 }
6716 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
6717 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006718 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05306719 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006720 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006721 return ret;
6722 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006723 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07006724 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006725 return bytes;
6726}
6727
6728static int out_get_render_position(const struct audio_stream_out *stream,
6729 uint32_t *dsp_frames)
6730{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006731 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08006732
6733 if (dsp_frames == NULL)
6734 return -EINVAL;
6735
6736 *dsp_frames = 0;
6737 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08006738 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05306739
6740 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
6741 * this operation and adev_close_output_stream(where out gets reset).
6742 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05306743 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006744 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05306745 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006746 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05306747 return 0;
6748 }
6749
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006750 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05306751 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306752 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006753 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306754 if (ret < 0)
6755 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006756 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05306757 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006758 }
Naresh Tanniru80659832014-06-04 18:17:56 +05306759 if (-ENETRESET == ret) {
6760 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306761 out->card_status = CARD_STATUS_OFFLINE;
6762 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306763 } else if(ret < 0) {
6764 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306765 ret = -EINVAL;
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05006766 } else if (out->card_status == CARD_STATUS_OFFLINE ||
6767 adev->out_power_policy == POWER_POLICY_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05306768 /*
6769 * Handle corner case where compress session is closed during SSR
6770 * and timestamp is queried
6771 */
6772 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306773 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306774 } else if (out->prev_card_status_offline) {
6775 ALOGE("ERROR: previously sound card was offline,return error");
6776 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306777 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306778 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006779 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05306780 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306781 pthread_mutex_unlock(&out->lock);
6782 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08006783 } else if (audio_is_linear_pcm(out->format)) {
6784 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006785 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08006786 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006787 } else
6788 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006789}
6790
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006791static int out_add_audio_effect(const struct audio_stream *stream __unused,
6792 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006793{
6794 return 0;
6795}
6796
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006797static int out_remove_audio_effect(const struct audio_stream *stream __unused,
6798 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006799{
6800 return 0;
6801}
6802
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006803static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
6804 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006805{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05306806 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006807}
6808
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006809static int out_get_presentation_position(const struct audio_stream_out *stream,
6810 uint64_t *frames, struct timespec *timestamp)
6811{
6812 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05306813 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07006814 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006815
Ashish Jain5106d362016-05-11 19:23:33 +05306816 /* below piece of code is not guarded against any lock because audioFliner serializes
6817 * this operation and adev_close_output_stream( where out gets reset).
6818 */
6819 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05306820 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006821 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05306822 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
6823 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
6824 return 0;
6825 }
6826
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006827 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006828
Ashish Jain5106d362016-05-11 19:23:33 +05306829 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
6830 ret = compress_get_tstamp(out->compr, &dsp_frames,
6831 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08006832 // Adjustment accounts for A2dp encoder latency with offload usecases
6833 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006834 if (is_a2dp_out_device_type(&out->device_list)) {
yidongh0515e042017-07-06 15:00:34 +08006835 unsigned long offset =
6836 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
6837 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
6838 }
Ashish Jain5106d362016-05-11 19:23:33 +05306839 ALOGVV("%s rendered frames %ld sample_rate %d",
6840 __func__, dsp_frames, out->sample_rate);
6841 *frames = dsp_frames;
6842 if (ret < 0)
6843 ret = -errno;
6844 if (-ENETRESET == ret) {
6845 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306846 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05306847 ret = -EINVAL;
6848 } else
6849 ret = 0;
6850 /* this is the best we can do */
6851 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07006852 } else {
6853 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08006854 unsigned int avail;
6855 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
George Gao62ebc722019-07-29 16:29:44 -07006856 uint64_t signed_frames = 0;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006857 uint64_t frames_temp = 0;
George Gao62ebc722019-07-29 16:29:44 -07006858
Andy Hunga1f48fa2019-07-01 18:14:53 -07006859 if (out->kernel_buffer_size > avail) {
6860 frames_temp = out->last_fifo_frames_remaining = out->kernel_buffer_size - avail;
6861 } else {
6862 ALOGW("%s: avail:%u > kernel_buffer_size:%zu clamping!",
6863 __func__, avail, out->kernel_buffer_size);
6864 avail = out->kernel_buffer_size;
6865 frames_temp = out->last_fifo_frames_remaining = 0;
6866 }
6867 out->last_fifo_valid = true;
6868 out->last_fifo_time_ns = audio_utils_ns_from_timespec(timestamp);
6869
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006870 if (out->written >= frames_temp)
6871 signed_frames = out->written - frames_temp;
George Gao62ebc722019-07-29 16:29:44 -07006872
Andy Hunga1f48fa2019-07-01 18:14:53 -07006873 ALOGVV("%s: frames:%lld avail:%u kernel_buffer_size:%zu",
6874 __func__, (long long)signed_frames, avail, out->kernel_buffer_size);
6875
Weiyin Jiangd4633762018-03-16 12:05:03 +08006876 // This adjustment accounts for buffering after app processor.
6877 // It is based on estimated DSP latency per use case, rather than exact.
George Gao9ba8a142020-07-23 14:30:03 -07006878 frames_temp = platform_render_latency(out) *
Robert Lee58215542019-07-15 20:55:12 +08006879 out->sample_rate / 1000000LL;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006880 if (signed_frames >= frames_temp)
6881 signed_frames -= frames_temp;
Aniket Kumar Lataff613152017-07-18 18:19:21 -07006882
Weiyin Jiangd4633762018-03-16 12:05:03 +08006883 // Adjustment accounts for A2dp encoder latency with non offload usecases
6884 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006885 if (is_a2dp_out_device_type(&out->device_list)) {
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006886 frames_temp = audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000;
6887 if (signed_frames >= frames_temp)
6888 signed_frames -= frames_temp;
Weiyin Jiangd4633762018-03-16 12:05:03 +08006889 }
6890
6891 // It would be unusual for this value to be negative, but check just in case ...
George Gao62ebc722019-07-29 16:29:44 -07006892 *frames = signed_frames;
6893 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006894 }
Eric Laurenta7a33042019-07-10 16:20:22 -07006895 } else if (out->card_status == CARD_STATUS_OFFLINE ||
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05006896 adev->out_power_policy == POWER_POLICY_STATUS_OFFLINE ||
Eric Laurenta7a33042019-07-10 16:20:22 -07006897 // audioflinger still needs position updates when A2DP is suspended
Jasmine Cha5c2517f2019-09-09 11:07:28 +08006898 (is_a2dp_out_device_type(&out->device_list) && audio_extn_a2dp_source_is_suspended())) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306899 *frames = out->written;
6900 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306901 if (is_offload_usecase(out->usecase))
6902 ret = -EINVAL;
6903 else
6904 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006905 }
6906 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006907 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006908 return ret;
6909}
6910
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006911static int out_set_callback(struct audio_stream_out *stream,
6912 stream_callback_t callback, void *cookie)
6913{
6914 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006915 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006916
6917 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006918 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006919 out->client_callback = callback;
6920 out->client_cookie = cookie;
6921 if (out->adsp_hdlr_stream_handle) {
6922 ret = audio_extn_adsp_hdlr_stream_set_callback(
6923 out->adsp_hdlr_stream_handle,
6924 callback,
6925 cookie);
6926 if (ret)
6927 ALOGW("%s:adsp hdlr callback registration failed %d",
6928 __func__, ret);
6929 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006930 pthread_mutex_unlock(&out->lock);
6931 return 0;
6932}
6933
6934static int out_pause(struct audio_stream_out* stream)
6935{
6936 struct stream_out *out = (struct stream_out *)stream;
6937 int status = -ENOSYS;
6938 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006939 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006940 ALOGD("copl(%p):pause compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306941 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006942 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006943 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006944 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306945 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05306946 status = compress_pause(out->compr);
6947
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006948 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006949
Mingming Yin21854652016-04-13 11:54:02 -07006950 if (audio_extn_passthru_is_active()) {
6951 ALOGV("offload use case, pause passthru");
6952 audio_extn_passthru_on_pause(out);
6953 }
6954
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306955 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006956 audio_extn_dts_notify_playback_state(out->usecase, 0,
6957 out->sample_rate, popcount(out->channel_mask),
6958 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006959 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08006960 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006961 pthread_mutex_unlock(&out->lock);
6962 }
6963 return status;
6964}
6965
6966static int out_resume(struct audio_stream_out* stream)
6967{
6968 struct stream_out *out = (struct stream_out *)stream;
6969 int status = -ENOSYS;
6970 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006971 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006972 ALOGD("copl(%p):resume compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306973 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006974 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006975 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006976 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306977 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306978 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07006979 }
6980 if (!status) {
6981 out->offload_state = OFFLOAD_STATE_PLAYING;
6982 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306983 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006984 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6985 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006986 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08006987 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006988 pthread_mutex_unlock(&out->lock);
6989 }
6990 return status;
6991}
6992
6993static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
6994{
6995 struct stream_out *out = (struct stream_out *)stream;
6996 int status = -ENOSYS;
6997 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006998 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006999 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007000 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
7001 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
7002 else
7003 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
7004 pthread_mutex_unlock(&out->lock);
7005 }
7006 return status;
7007}
7008
7009static int out_flush(struct audio_stream_out* stream)
7010{
7011 struct stream_out *out = (struct stream_out *)stream;
7012 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07007013 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07007014 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007015 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08007016 pthread_mutex_lock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07007017 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
Gautam Manam14c198b2020-12-24 14:08:04 +05307018 pthread_mutex_unlock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07007019 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07007020 } else {
7021 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
Gautam Manam14c198b2020-12-24 14:08:04 +05307022 pthread_mutex_unlock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07007023 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08007024 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007025 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07007026 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007027 return 0;
7028 }
7029 return -ENOSYS;
7030}
7031
Haynes Mathew George16081042017-05-31 17:16:49 -07007032static int out_stop(const struct audio_stream_out* stream)
7033{
7034 struct stream_out *out = (struct stream_out *)stream;
7035 struct audio_device *adev = out->dev;
7036 int ret = -ENOSYS;
7037
7038 ALOGV("%s", __func__);
7039 pthread_mutex_lock(&adev->lock);
7040 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
7041 out->playback_started && out->pcm != NULL) {
7042 pcm_stop(out->pcm);
7043 ret = stop_output_stream(out);
7044 out->playback_started = false;
7045 }
7046 pthread_mutex_unlock(&adev->lock);
7047 return ret;
7048}
7049
7050static int out_start(const struct audio_stream_out* stream)
7051{
7052 struct stream_out *out = (struct stream_out *)stream;
7053 struct audio_device *adev = out->dev;
7054 int ret = -ENOSYS;
7055
7056 ALOGV("%s", __func__);
7057 pthread_mutex_lock(&adev->lock);
7058 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
7059 !out->playback_started && out->pcm != NULL) {
7060 ret = start_output_stream(out);
7061 if (ret == 0) {
7062 out->playback_started = true;
7063 }
7064 }
7065 pthread_mutex_unlock(&adev->lock);
7066 return ret;
7067}
7068
7069/*
7070 * Modify config->period_count based on min_size_frames
7071 */
7072static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
7073{
7074 int periodCountRequested = (min_size_frames + config->period_size - 1)
7075 / config->period_size;
7076 int periodCount = MMAP_PERIOD_COUNT_MIN;
7077
7078 ALOGV("%s original config.period_size = %d config.period_count = %d",
7079 __func__, config->period_size, config->period_count);
7080
7081 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
7082 periodCount *= 2;
7083 }
7084 config->period_count = periodCount;
7085
7086 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
7087}
7088
Phil Burkfe17efd2019-03-25 10:23:35 -07007089// Read offset for the positional timestamp from a persistent vendor property.
7090// This is to workaround apparent inaccuracies in the timing information that
7091// is used by the AAudio timing model. The inaccuracies can cause glitches.
7092static int64_t get_mmap_out_time_offset() {
7093 const int32_t kDefaultOffsetMicros = 0;
7094 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08007095 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07007096 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
7097 return mmap_time_offset_micros * (int64_t)1000;
7098}
7099
Haynes Mathew George16081042017-05-31 17:16:49 -07007100static int out_create_mmap_buffer(const struct audio_stream_out *stream,
7101 int32_t min_size_frames,
7102 struct audio_mmap_buffer_info *info)
7103{
7104 struct stream_out *out = (struct stream_out *)stream;
7105 struct audio_device *adev = out->dev;
7106 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07007107 unsigned int offset1 = 0;
7108 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007109 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07007110 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007111 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07007112
Arun Mirpuri5d170872019-03-26 13:21:31 -07007113 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05307114 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07007115 pthread_mutex_lock(&adev->lock);
7116
Sharad Sanglec6f32552018-05-04 16:15:38 +05307117 if (CARD_STATUS_OFFLINE == out->card_status ||
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05007118 CARD_STATUS_OFFLINE == adev->card_status ||
7119 POWER_POLICY_STATUS_OFFLINE == adev->out_power_policy) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307120 ALOGW("out->card_status or adev->card_status offline, try again");
7121 ret = -EIO;
7122 goto exit;
7123 }
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307124 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07007125 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
7126 ret = -EINVAL;
7127 goto exit;
7128 }
7129 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
7130 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
7131 ret = -ENOSYS;
7132 goto exit;
7133 }
7134 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
7135 if (out->pcm_device_id < 0) {
7136 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
7137 __func__, out->pcm_device_id, out->usecase);
7138 ret = -EINVAL;
7139 goto exit;
7140 }
7141
7142 adjust_mmap_period_count(&out->config, min_size_frames);
7143
Arun Mirpuri5d170872019-03-26 13:21:31 -07007144 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07007145 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
7146 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
7147 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307148 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307149 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7150 out->card_status = CARD_STATUS_OFFLINE;
7151 adev->card_status = CARD_STATUS_OFFLINE;
7152 ret = -EIO;
7153 goto exit;
7154 }
7155
Haynes Mathew George16081042017-05-31 17:16:49 -07007156 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
7157 step = "open";
7158 ret = -ENODEV;
7159 goto exit;
7160 }
7161 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
7162 if (ret < 0) {
7163 step = "begin";
7164 goto exit;
7165 }
juyuchen626833d2019-06-04 16:48:02 +08007166
7167 info->flags = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007168 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07007169 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07007170 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07007171 ret = platform_get_mmap_data_fd(adev->platform,
7172 out->pcm_device_id, 0 /*playback*/,
7173 &info->shared_memory_fd,
7174 &mmap_size);
7175 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07007176 // Fall back to non exclusive mode
7177 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
7178 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07007179 out->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
7180 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, out->mmap_shared_memory_fd);
7181
Arun Mirpuri5d170872019-03-26 13:21:31 -07007182 if (mmap_size < buffer_size) {
7183 step = "mmap";
7184 goto exit;
7185 }
juyuchen626833d2019-06-04 16:48:02 +08007186 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07007187 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007188 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07007189 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07007190
7191 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
7192 if (ret < 0) {
7193 step = "commit";
7194 goto exit;
7195 }
7196
Phil Burkfe17efd2019-03-25 10:23:35 -07007197 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
7198
Haynes Mathew George16081042017-05-31 17:16:49 -07007199 out->standby = false;
7200 ret = 0;
7201
Arun Mirpuri5d170872019-03-26 13:21:31 -07007202 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07007203 __func__, info->shared_memory_address, info->buffer_size_frames);
7204
7205exit:
7206 if (ret != 0) {
7207 if (out->pcm == NULL) {
7208 ALOGE("%s: %s - %d", __func__, step, ret);
7209 } else {
7210 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
7211 pcm_close(out->pcm);
7212 out->pcm = NULL;
7213 }
7214 }
7215 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05307216 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07007217 return ret;
7218}
7219
7220static int out_get_mmap_position(const struct audio_stream_out *stream,
7221 struct audio_mmap_position *position)
7222{
7223 struct stream_out *out = (struct stream_out *)stream;
7224 ALOGVV("%s", __func__);
7225 if (position == NULL) {
7226 return -EINVAL;
7227 }
7228 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08007229 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07007230 return -ENOSYS;
7231 }
7232 if (out->pcm == NULL) {
7233 return -ENOSYS;
7234 }
7235
7236 struct timespec ts = { 0, 0 };
7237 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
7238 if (ret < 0) {
7239 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
7240 return ret;
7241 }
Phil Burkfe17efd2019-03-25 10:23:35 -07007242 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7243 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07007244 return 0;
7245}
7246
7247
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007248/** audio_stream_in implementation **/
7249static uint32_t in_get_sample_rate(const struct audio_stream *stream)
7250{
7251 struct stream_in *in = (struct stream_in *)stream;
7252
7253 return in->config.rate;
7254}
7255
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007256static int in_set_sample_rate(struct audio_stream *stream __unused,
7257 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007258{
7259 return -ENOSYS;
7260}
7261
7262static size_t in_get_buffer_size(const struct audio_stream *stream)
7263{
7264 struct stream_in *in = (struct stream_in *)stream;
7265
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007266 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
7267 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07007268 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
Raghu Bankapur37cbf382022-12-01 09:30:00 +05307269 return audio_extn_compr_cap_get_buffer_size(pcm_format_to_audio_format(in->config.format));
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307270 else if(audio_extn_cin_attached_usecase(in))
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307271 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007272
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007273 return in->config.period_size * in->af_period_multiplier *
7274 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007275}
7276
7277static uint32_t in_get_channels(const struct audio_stream *stream)
7278{
7279 struct stream_in *in = (struct stream_in *)stream;
7280
7281 return in->channel_mask;
7282}
7283
7284static audio_format_t in_get_format(const struct audio_stream *stream)
7285{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007286 struct stream_in *in = (struct stream_in *)stream;
7287
7288 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007289}
7290
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007291static int in_set_format(struct audio_stream *stream __unused,
7292 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007293{
7294 return -ENOSYS;
7295}
7296
7297static int in_standby(struct audio_stream *stream)
7298{
7299 struct stream_in *in = (struct stream_in *)stream;
7300 struct audio_device *adev = in->dev;
7301 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307302 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
7303 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07007304 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307305
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007306 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007307 if (!in->standby && in->is_st_session) {
7308 ALOGD("%s: sound trigger pcm stop lab", __func__);
7309 audio_extn_sound_trigger_stop_lab(in);
George Gao3018ede2019-10-23 13:23:00 -07007310 if (adev->num_va_sessions > 0)
7311 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007312 in->standby = 1;
7313 }
7314
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007315 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007316 if (adev->adm_deregister_stream)
7317 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
7318
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08007319 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007320 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08007321 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08007322 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08007323 voice_extn_compress_voip_close_input_stream(stream);
7324 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07007325 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
7326 do_stop = in->capture_started;
7327 in->capture_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07007328 if (in->mmap_shared_memory_fd >= 0) {
7329 ALOGV("%s: closing mmap_shared_memory_fd = %d",
7330 __func__, in->mmap_shared_memory_fd);
7331 close(in->mmap_shared_memory_fd);
7332 in->mmap_shared_memory_fd = -1;
7333 }
Zhou Songa8895042016-07-05 17:54:22 +08007334 } else {
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307335 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05307336 audio_extn_cin_close_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08007337 }
7338
Arun Mirpuri5d170872019-03-26 13:21:31 -07007339 if (in->pcm) {
7340 ATRACE_BEGIN("pcm_in_close");
7341 pcm_close(in->pcm);
7342 ATRACE_END();
7343 in->pcm = NULL;
7344 }
7345
Carter Hsu2e429db2019-05-14 18:50:52 +08007346 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08007347 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08007348
George Gao3018ede2019-10-23 13:23:00 -07007349 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
7350 if (adev->num_va_sessions > 0)
7351 adev->num_va_sessions--;
7352 }
Quinn Malef6050362019-01-30 15:55:40 -08007353
Eric Laurent150dbfe2013-02-27 14:31:02 -08007354 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007355 }
7356 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07007357 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007358 return status;
7359}
7360
Aalique Grahame22e49102018-12-18 14:23:57 -08007361static int in_dump(const struct audio_stream *stream,
7362 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007363{
Aalique Grahame22e49102018-12-18 14:23:57 -08007364 struct stream_in *in = (struct stream_in *)stream;
7365
7366 // We try to get the lock for consistency,
7367 // but it isn't necessary for these variables.
7368 // If we're not in standby, we may be blocked on a read.
7369 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
7370 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
7371 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
7372 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
Dechen Chai22768452021-07-30 09:29:16 +05307373#ifndef LINUX_ENABLED
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007374 char buffer[256]; // for statistics formatting
7375 if (in->start_latency_ms.n > 0) {
7376 simple_stats_to_string(&in->start_latency_ms, buffer, sizeof(buffer));
7377 dprintf(fd, " Start latency ms: %s\n", buffer);
7378 }
Dechen Chai22768452021-07-30 09:29:16 +05307379#endif
Aalique Grahame22e49102018-12-18 14:23:57 -08007380 if (locked) {
7381 pthread_mutex_unlock(&in->lock);
7382 }
Dechen Chai22768452021-07-30 09:29:16 +05307383#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -08007384 // dump error info
7385 (void)error_log_dump(
7386 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Dechen Chai22768452021-07-30 09:29:16 +05307387#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007388 return 0;
7389}
7390
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307391static void in_snd_mon_cb(void * stream, struct str_parms * parms)
7392{
7393 if (!stream || !parms)
7394 return;
7395
7396 struct stream_in *in = (struct stream_in *)stream;
7397 struct audio_device *adev = in->dev;
7398
7399 card_status_t status;
7400 int card;
7401 if (parse_snd_card_status(parms, &card, &status) < 0)
7402 return;
7403
7404 pthread_mutex_lock(&adev->lock);
7405 bool valid_cb = (card == adev->snd_card);
7406 pthread_mutex_unlock(&adev->lock);
7407
7408 if (!valid_cb)
7409 return;
7410
7411 lock_input_stream(in);
7412 if (in->card_status != status)
7413 in->card_status = status;
7414 pthread_mutex_unlock(&in->lock);
7415
7416 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
7417 use_case_table[in->usecase],
7418 status == CARD_STATUS_OFFLINE ? "offline" : "online");
7419
7420 // a better solution would be to report error back to AF and let
7421 // it put the stream to standby
7422 if (status == CARD_STATUS_OFFLINE)
7423 in_standby(&in->stream.common);
7424
7425 return;
7426}
7427
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007428int route_input_stream(struct stream_in *in,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007429 struct listnode *devices,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007430 audio_source_t source)
7431{
7432 struct audio_device *adev = in->dev;
7433 int ret = 0;
7434
7435 lock_input_stream(in);
7436 pthread_mutex_lock(&adev->lock);
7437
7438 /* no audio source uses val == 0 */
7439 if ((in->source != source) && (source != AUDIO_SOURCE_DEFAULT)) {
7440 in->source = source;
7441 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
7442 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
7443 (voice_extn_compress_voip_is_format_supported(in->format)) &&
7444 (in->config.rate == 8000 || in->config.rate == 16000 ||
7445 in->config.rate == 32000 || in->config.rate == 48000 ) &&
7446 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
7447 ret = voice_extn_compress_voip_open_input_stream(in);
7448 if (ret != 0) {
7449 ALOGE("%s: Compress voip input cannot be opened, error:%d",
7450 __func__, ret);
7451 }
7452 }
7453 }
7454
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007455 if (!compare_devices(&in->device_list, devices) && !list_empty(devices) &&
7456 is_audio_in_device_type(devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007457 // Workaround: If routing to an non existing usb device, fail gracefully
7458 // The routing request will otherwise block during 10 second
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007459 struct str_parms *usb_addr =
7460 str_parms_create_str(get_usb_device_address(devices));
7461 if (is_usb_in_device_type(devices) && usb_addr &&
Weiyin Jiangabedea32020-12-09 12:49:19 +08007462 !audio_extn_usb_connected(NULL)) {
7463 ALOGW("%s: ignoring rerouting to non existing USB", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007464 ret = -ENOSYS;
7465 } else {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007466 /* If recording is in progress, change the tx device to new device */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007467 assign_devices(&in->device_list, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007468 if (!in->standby && !in->is_st_session) {
7469 ALOGV("update input routing change");
7470 // inform adm before actual routing to prevent glitches.
7471 if (adev->adm_on_routing_change) {
7472 adev->adm_on_routing_change(adev->adm_data,
7473 in->capture_handle);
7474 ret = select_devices(adev, in->usecase);
7475 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7476 adev->adm_routing_changed = true;
7477 }
7478 }
7479 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007480 if (usb_addr)
7481 str_parms_destroy(usb_addr);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007482 }
7483 pthread_mutex_unlock(&adev->lock);
7484 pthread_mutex_unlock(&in->lock);
7485
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07007486 ALOGV("%s: exit: status(%d)", __func__, ret);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007487 return ret;
7488}
7489
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007490static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
7491{
7492 struct stream_in *in = (struct stream_in *)stream;
7493 struct audio_device *adev = in->dev;
7494 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007495 char value[32];
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307496 int err = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007497
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307498 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007499 parms = str_parms_create_str(kvpairs);
7500
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307501 if (!parms)
7502 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007503 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08007504 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007505
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307506 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
7507 if (err >= 0) {
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307508 strlcpy(in->profile, value, sizeof(in->profile));
7509 ALOGV("updating stream profile with value '%s'", in->profile);
7510 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
7511 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007512 &in->device_list, in->flags, in->format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307513 in->sample_rate, in->bit_width,
7514 in->profile, &in->app_type_cfg);
7515 }
7516
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007517 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08007518 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007519
7520 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307521error:
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307522 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007523}
7524
7525static char* in_get_parameters(const struct audio_stream *stream,
7526 const char *keys)
7527{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007528 struct stream_in *in = (struct stream_in *)stream;
7529 struct str_parms *query = str_parms_create_str(keys);
7530 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007531 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007532
7533 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08007534 if (reply) {
7535 str_parms_destroy(reply);
7536 }
7537 if (query) {
7538 str_parms_destroy(query);
7539 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007540 ALOGE("in_get_parameters: failed to create query or reply");
7541 return NULL;
7542 }
7543
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007544 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007545
7546 voice_extn_in_get_parameters(in, query, reply);
7547
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007548 stream_get_parameter_channels(query, reply,
7549 &in->supported_channel_masks[0]);
7550 stream_get_parameter_formats(query, reply,
7551 &in->supported_formats[0]);
7552 stream_get_parameter_rates(query, reply,
7553 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007554 str = str_parms_to_str(reply);
7555 str_parms_destroy(query);
7556 str_parms_destroy(reply);
7557
7558 ALOGV("%s: exit: returns - %s", __func__, str);
7559 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007560}
7561
Aalique Grahame22e49102018-12-18 14:23:57 -08007562static int in_set_gain(struct audio_stream_in *stream,
7563 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007564{
Aalique Grahame22e49102018-12-18 14:23:57 -08007565 struct stream_in *in = (struct stream_in *)stream;
7566 char mixer_ctl_name[128];
7567 struct mixer_ctl *ctl;
7568 int ctl_value;
7569
7570 ALOGV("%s: gain %f", __func__, gain);
7571
7572 if (stream == NULL)
7573 return -EINVAL;
7574
7575 /* in_set_gain() only used to silence MMAP capture for now */
7576 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
7577 return -ENOSYS;
7578
7579 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
7580
7581 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
7582 if (!ctl) {
7583 ALOGW("%s: Could not get ctl for mixer cmd - %s",
7584 __func__, mixer_ctl_name);
7585 return -ENOSYS;
7586 }
7587
7588 if (gain < RECORD_GAIN_MIN)
7589 gain = RECORD_GAIN_MIN;
7590 else if (gain > RECORD_GAIN_MAX)
7591 gain = RECORD_GAIN_MAX;
7592 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
7593
7594 mixer_ctl_set_value(ctl, 0, ctl_value);
7595
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007596 return 0;
7597}
7598
7599static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
7600 size_t bytes)
7601{
7602 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05307603
7604 if (in == NULL) {
7605 ALOGE("%s: stream_in ptr is NULL", __func__);
7606 return -EINVAL;
7607 }
7608
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007609 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05307610 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307611 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007612
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007613 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05307614
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007615 if (in->is_st_session) {
7616 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
7617 /* Read from sound trigger HAL */
7618 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08007619 if (in->standby) {
George Gao3018ede2019-10-23 13:23:00 -07007620 if (adev->num_va_sessions < UINT_MAX)
7621 adev->num_va_sessions++;
Quinn Malef6050362019-01-30 15:55:40 -08007622 in->standby = 0;
7623 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007624 pthread_mutex_unlock(&in->lock);
7625 return bytes;
7626 }
7627
Haynes Mathew George16081042017-05-31 17:16:49 -07007628 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
7629 ret = -ENOSYS;
7630 goto exit;
7631 }
7632
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007633 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
7634 !in->standby && adev->adm_routing_changed) {
7635 ret = -ENOSYS;
7636 goto exit;
7637 }
7638
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007639 if (in->standby) {
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007640 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
7641
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007642 pthread_mutex_lock(&adev->lock);
7643 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
7644 ret = voice_extn_compress_voip_start_input_stream(in);
7645 else
7646 ret = start_input_stream(in);
George Gao3018ede2019-10-23 13:23:00 -07007647 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
7648 if (adev->num_va_sessions < UINT_MAX)
7649 adev->num_va_sessions++;
7650 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007651 pthread_mutex_unlock(&adev->lock);
7652 if (ret != 0) {
7653 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007654 }
7655 in->standby = 0;
Dechen Chai22768452021-07-30 09:29:16 +05307656#ifndef LINUX_ENABLED
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007657 // log startup time in ms.
7658 simple_stats_log(
7659 &in->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Dechen Chai22768452021-07-30 09:29:16 +05307660#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007661 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007662
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05307663 /* Avoid read if capture_stopped is set */
7664 if (android_atomic_acquire_load(&(in->capture_stopped)) > 0) {
7665 ALOGD("%s: force stopped catpure session, ignoring read request", __func__);
7666 ret = -EINVAL;
7667 goto exit;
7668 }
7669
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007670 // what's the duration requested by the client?
7671 long ns = 0;
7672
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307673 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007674 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
7675 in->config.rate;
7676
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007677 ret = request_in_focus(in, ns);
7678 if (ret != 0)
7679 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007680 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007681
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307682 if (audio_extn_cin_attached_usecase(in)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307683 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
7684 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307685 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007686 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307687 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07007688 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007689 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007690 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07007691 } else if (audio_extn_ffv_get_stream() == in) {
7692 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307693 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007694 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307695 /* data from DSP comes in 24_8 format, convert it to 8_24 */
7696 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
7697 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
7698 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307699 ret = -EINVAL;
7700 goto exit;
7701 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307702 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307703 ret = -errno;
7704 }
7705 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307706 /* bytes read is always set to bytes for non compress usecases */
7707 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007708 }
7709
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007710 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007711
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007712 /*
Quinn Malef6050362019-01-30 15:55:40 -08007713 * Instead of writing zeroes here, we could trust the hardware to always
7714 * provide zeroes when muted. This is also muted with voice recognition
7715 * usecases so that other clients do not have access to voice recognition
7716 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007717 */
Quinn Malef6050362019-01-30 15:55:40 -08007718 if ((ret == 0 && voice_get_mic_mute(adev) &&
7719 !voice_is_in_call_rec_stream(in) &&
Zhou Song62ea0282020-03-22 19:53:01 +08007720 (in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY &&
Manoj Kumar N D54cab152023-01-27 16:41:55 +05307721 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY2 &&
7722 in->source != AUDIO_SOURCE_FM_TUNER &&
7723 !is_single_device_type_equal(&in->device_list, AUDIO_DEVICE_IN_FM_TUNER))) ||
Quinn Malef6050362019-01-30 15:55:40 -08007724 (adev->num_va_sessions &&
7725 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
7726 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
7727 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007728 memset(buffer, 0, bytes);
7729
7730exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307731 frame_size = audio_stream_in_frame_size(stream);
7732 if (frame_size > 0)
7733 in->frames_read += bytes_read/frame_size;
7734
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007735 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307736 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007737 pthread_mutex_unlock(&in->lock);
7738
7739 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307740 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307741 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307742 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307743 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307744 in->standby = true;
7745 }
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307746 if (!audio_extn_cin_attached_usecase(in)) {
Sharad Sangled17c9122017-03-20 15:58:52 +05307747 bytes_read = bytes;
7748 memset(buffer, 0, bytes);
7749 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007750 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007751 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7752 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007753 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05307754 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05307755 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007756 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307757 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007758}
7759
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007760static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007761{
7762 return 0;
7763}
7764
Aalique Grahame22e49102018-12-18 14:23:57 -08007765static int in_get_capture_position(const struct audio_stream_in *stream,
7766 int64_t *frames, int64_t *time)
7767{
7768 if (stream == NULL || frames == NULL || time == NULL) {
7769 return -EINVAL;
7770 }
7771 struct stream_in *in = (struct stream_in *)stream;
7772 int ret = -ENOSYS;
7773
7774 lock_input_stream(in);
7775 // note: ST sessions do not close the alsa pcm driver synchronously
7776 // on standby. Therefore, we may return an error even though the
7777 // pcm stream is still opened.
7778 if (in->standby) {
7779 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
7780 "%s stream in standby but pcm not NULL for non ST session", __func__);
7781 goto exit;
7782 }
7783 if (in->pcm) {
7784 struct timespec timestamp;
7785 unsigned int avail;
7786 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
7787 *frames = in->frames_read + avail;
Robert Lee58215542019-07-15 20:55:12 +08007788 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec
George Gao9ba8a142020-07-23 14:30:03 -07007789 - platform_capture_latency(in) * 1000LL;
Kakanaboina Ramanjaneyulu8cedb092021-03-15 15:55:29 +05307790 //Adjustment accounts for A2dp decoder latency for recording usecase
7791 // Note: decoder latency is returned in ms, while platform_capture_latency in ns.
7792 if (is_a2dp_in_device_type(&in->device_list))
7793 *time -= audio_extn_a2dp_get_decoder_latency() * 1000000LL;
Aalique Grahame22e49102018-12-18 14:23:57 -08007794 ret = 0;
7795 }
7796 }
7797exit:
7798 pthread_mutex_unlock(&in->lock);
7799 return ret;
7800}
7801
Carter Hsu2e429db2019-05-14 18:50:52 +08007802static int in_update_effect_list(bool add, effect_handle_t effect,
7803 struct listnode *head)
7804{
7805 struct listnode *node;
7806 struct in_effect_list *elist = NULL;
7807 struct in_effect_list *target = NULL;
7808 int ret = 0;
7809
7810 if (!head)
7811 return ret;
7812
7813 list_for_each(node, head) {
7814 elist = node_to_item(node, struct in_effect_list, list);
7815 if (elist->handle == effect) {
7816 target = elist;
7817 break;
7818 }
7819 }
7820
7821 if (add) {
7822 if (target) {
7823 ALOGD("effect %p already exist", effect);
7824 return ret;
7825 }
7826
7827 target = (struct in_effect_list *)
7828 calloc(1, sizeof(struct in_effect_list));
7829
7830 if (!target) {
7831 ALOGE("%s:fail to allocate memory", __func__);
7832 return -ENOMEM;
7833 }
7834
7835 target->handle = effect;
7836 list_add_tail(head, &target->list);
7837 } else {
7838 if (target) {
7839 list_remove(&target->list);
7840 free(target);
7841 }
7842 }
7843
7844 return ret;
7845}
7846
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007847static int add_remove_audio_effect(const struct audio_stream *stream,
7848 effect_handle_t effect,
7849 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007850{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007851 struct stream_in *in = (struct stream_in *)stream;
7852 int status = 0;
7853 effect_descriptor_t desc;
7854
7855 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007856 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
7857
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007858 if (status != 0)
7859 return status;
7860
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007861 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007862 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08007863 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08007864 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
7865 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007866 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08007867
7868 in_update_effect_list(enable, effect, &in->aec_list);
7869 enable = !list_empty(&in->aec_list);
7870 if (enable == in->enable_aec)
7871 goto exit;
7872
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007873 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007874 ALOGD("AEC enable %d", enable);
7875
Aalique Grahame22e49102018-12-18 14:23:57 -08007876 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7877 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
7878 in->dev->enable_voicerx = enable;
7879 struct audio_usecase *usecase;
7880 struct listnode *node;
7881 list_for_each(node, &in->dev->usecase_list) {
7882 usecase = node_to_item(node, struct audio_usecase, list);
7883 if (usecase->type == PCM_PLAYBACK)
7884 select_devices(in->dev, usecase->id);
7885 }
7886 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007887 if (!in->standby) {
7888 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
7889 select_devices(in->dev, in->usecase);
7890 }
7891
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007892 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007893 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
7894
7895 in_update_effect_list(enable, effect, &in->ns_list);
7896 enable = !list_empty(&in->ns_list);
7897 if (enable == in->enable_ns)
7898 goto exit;
7899
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007900 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007901 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007902 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08007903 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Ramu Gottipatifa5be522021-12-28 19:18:21 +05307904 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
kunleizd96526c2018-04-09 11:12:32 +08007905 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007906 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
7907 select_devices(in->dev, in->usecase);
7908 } else
7909 select_devices(in->dev, in->usecase);
7910 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007911 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007912exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007913 pthread_mutex_unlock(&in->dev->lock);
7914 pthread_mutex_unlock(&in->lock);
7915
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007916 return 0;
7917}
7918
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007919static int in_add_audio_effect(const struct audio_stream *stream,
7920 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007921{
Eric Laurent994a6932013-07-17 11:51:42 -07007922 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007923 return add_remove_audio_effect(stream, effect, true);
7924}
7925
7926static int in_remove_audio_effect(const struct audio_stream *stream,
7927 effect_handle_t effect)
7928{
Eric Laurent994a6932013-07-17 11:51:42 -07007929 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007930 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007931}
7932
Haynes Mathew George16081042017-05-31 17:16:49 -07007933static int in_stop(const struct audio_stream_in* stream)
7934{
7935 struct stream_in *in = (struct stream_in *)stream;
7936 struct audio_device *adev = in->dev;
7937
7938 int ret = -ENOSYS;
7939 ALOGV("%s", __func__);
7940 pthread_mutex_lock(&adev->lock);
7941 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7942 in->capture_started && in->pcm != NULL) {
7943 pcm_stop(in->pcm);
7944 ret = stop_input_stream(in);
7945 in->capture_started = false;
7946 }
7947 pthread_mutex_unlock(&adev->lock);
7948 return ret;
7949}
7950
7951static int in_start(const struct audio_stream_in* stream)
7952{
7953 struct stream_in *in = (struct stream_in *)stream;
7954 struct audio_device *adev = in->dev;
7955 int ret = -ENOSYS;
7956
7957 ALOGV("%s in %p", __func__, in);
7958 pthread_mutex_lock(&adev->lock);
7959 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7960 !in->capture_started && in->pcm != NULL) {
7961 if (!in->capture_started) {
7962 ret = start_input_stream(in);
7963 if (ret == 0) {
7964 in->capture_started = true;
7965 }
7966 }
7967 }
7968 pthread_mutex_unlock(&adev->lock);
7969 return ret;
7970}
7971
Phil Burke0a86d12019-02-16 22:28:11 -08007972// Read offset for the positional timestamp from a persistent vendor property.
7973// This is to workaround apparent inaccuracies in the timing information that
7974// is used by the AAudio timing model. The inaccuracies can cause glitches.
7975static int64_t in_get_mmap_time_offset() {
7976 const int32_t kDefaultOffsetMicros = 0;
7977 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08007978 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08007979 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
7980 return mmap_time_offset_micros * (int64_t)1000;
7981}
7982
Haynes Mathew George16081042017-05-31 17:16:49 -07007983static int in_create_mmap_buffer(const struct audio_stream_in *stream,
7984 int32_t min_size_frames,
7985 struct audio_mmap_buffer_info *info)
7986{
7987 struct stream_in *in = (struct stream_in *)stream;
7988 struct audio_device *adev = in->dev;
7989 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07007990 unsigned int offset1 = 0;
7991 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007992 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07007993 uint32_t mmap_size = 0;
7994 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007995
7996 pthread_mutex_lock(&adev->lock);
7997 ALOGV("%s in %p", __func__, in);
7998
Sharad Sanglec6f32552018-05-04 16:15:38 +05307999 if (CARD_STATUS_OFFLINE == in->card_status||
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05008000 CARD_STATUS_OFFLINE == adev->card_status ||
8001 POWER_POLICY_STATUS_OFFLINE == adev->in_power_policy) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05308002 ALOGW("in->card_status or adev->card_status offline, try again");
8003 ret = -EIO;
8004 goto exit;
8005 }
8006
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05308007 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07008008 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
8009 ret = -EINVAL;
8010 goto exit;
8011 }
8012 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
8013 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
8014 ALOGV("%s in %p", __func__, in);
8015 ret = -ENOSYS;
8016 goto exit;
8017 }
8018 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
8019 if (in->pcm_device_id < 0) {
8020 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
8021 __func__, in->pcm_device_id, in->usecase);
8022 ret = -EINVAL;
8023 goto exit;
8024 }
8025
8026 adjust_mmap_period_count(&in->config, min_size_frames);
8027
8028 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
8029 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
8030 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
8031 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05308032 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05308033 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
8034 in->card_status = CARD_STATUS_OFFLINE;
8035 adev->card_status = CARD_STATUS_OFFLINE;
8036 ret = -EIO;
8037 goto exit;
8038 }
8039
Haynes Mathew George16081042017-05-31 17:16:49 -07008040 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
8041 step = "open";
8042 ret = -ENODEV;
8043 goto exit;
8044 }
8045
8046 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
8047 if (ret < 0) {
8048 step = "begin";
8049 goto exit;
8050 }
Haynes Mathew George16081042017-05-31 17:16:49 -07008051
juyuchen626833d2019-06-04 16:48:02 +08008052 info->flags = 0;
Arun Mirpuri5d170872019-03-26 13:21:31 -07008053 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
8054 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
8055 info->burst_size_frames = in->config.period_size;
8056 ret = platform_get_mmap_data_fd(adev->platform,
8057 in->pcm_device_id, 1 /*capture*/,
8058 &info->shared_memory_fd,
8059 &mmap_size);
8060 if (ret < 0) {
8061 // Fall back to non exclusive mode
8062 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
8063 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07008064 in->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
8065 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, in->mmap_shared_memory_fd);
8066
Arun Mirpuri5d170872019-03-26 13:21:31 -07008067 if (mmap_size < buffer_size) {
8068 step = "mmap";
8069 goto exit;
8070 }
juyuchen626833d2019-06-04 16:48:02 +08008071 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Arun Mirpuri5d170872019-03-26 13:21:31 -07008072 }
8073
8074 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07008075
8076 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
8077 if (ret < 0) {
8078 step = "commit";
8079 goto exit;
8080 }
8081
Phil Burke0a86d12019-02-16 22:28:11 -08008082 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
8083
Haynes Mathew George16081042017-05-31 17:16:49 -07008084 in->standby = false;
8085 ret = 0;
8086
8087 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
8088 __func__, info->shared_memory_address, info->buffer_size_frames);
8089
8090exit:
8091 if (ret != 0) {
8092 if (in->pcm == NULL) {
8093 ALOGE("%s: %s - %d", __func__, step, ret);
8094 } else {
8095 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
8096 pcm_close(in->pcm);
8097 in->pcm = NULL;
8098 }
8099 }
8100 pthread_mutex_unlock(&adev->lock);
8101 return ret;
8102}
8103
8104static int in_get_mmap_position(const struct audio_stream_in *stream,
8105 struct audio_mmap_position *position)
8106{
8107 struct stream_in *in = (struct stream_in *)stream;
8108 ALOGVV("%s", __func__);
8109 if (position == NULL) {
8110 return -EINVAL;
8111 }
Gautam Manam34d1f542021-01-05 20:24:37 +05308112 lock_input_stream(in);
Haynes Mathew George16081042017-05-31 17:16:49 -07008113 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
Gautam Manam34d1f542021-01-05 20:24:37 +05308114 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07008115 return -ENOSYS;
8116 }
8117 if (in->pcm == NULL) {
Gautam Manam34d1f542021-01-05 20:24:37 +05308118 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07008119 return -ENOSYS;
8120 }
8121 struct timespec ts = { 0, 0 };
8122 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
8123 if (ret < 0) {
8124 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
Gautam Manam34d1f542021-01-05 20:24:37 +05308125 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07008126 return ret;
8127 }
Phil Burke0a86d12019-02-16 22:28:11 -08008128 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
8129 + in->mmap_time_offset_nanos;
Gautam Manam34d1f542021-01-05 20:24:37 +05308130 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07008131 return 0;
8132}
8133
Naresh Tannirudcb47c52018-06-25 16:23:32 +05308134static int in_get_active_microphones(const struct audio_stream_in *stream,
8135 struct audio_microphone_characteristic_t *mic_array,
8136 size_t *mic_count) {
8137 struct stream_in *in = (struct stream_in *)stream;
8138 struct audio_device *adev = in->dev;
8139 ALOGVV("%s", __func__);
8140
8141 lock_input_stream(in);
8142 pthread_mutex_lock(&adev->lock);
8143 int ret = platform_get_active_microphones(adev->platform,
8144 audio_channel_count_from_in_mask(in->channel_mask),
8145 in->usecase, mic_array, mic_count);
8146 pthread_mutex_unlock(&adev->lock);
8147 pthread_mutex_unlock(&in->lock);
8148
8149 return ret;
8150}
8151
8152static int adev_get_microphones(const struct audio_hw_device *dev,
8153 struct audio_microphone_characteristic_t *mic_array,
8154 size_t *mic_count) {
8155 struct audio_device *adev = (struct audio_device *)dev;
8156 ALOGVV("%s", __func__);
8157
8158 pthread_mutex_lock(&adev->lock);
8159 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
8160 pthread_mutex_unlock(&adev->lock);
8161
8162 return ret;
8163}
juyuchendb308c22019-01-21 11:57:17 -07008164
8165static void in_update_sink_metadata(struct audio_stream_in *stream,
8166 const struct sink_metadata *sink_metadata) {
8167
8168 if (stream == NULL
8169 || sink_metadata == NULL
8170 || sink_metadata->tracks == NULL) {
8171 return;
8172 }
8173
8174 int error = 0;
8175 struct stream_in *in = (struct stream_in *)stream;
8176 struct audio_device *adev = in->dev;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008177 struct listnode devices;
8178
8179 list_init(&devices);
juyuchendb308c22019-01-21 11:57:17 -07008180
8181 if (sink_metadata->track_count != 0)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008182 reassign_device_list(&devices, sink_metadata->tracks->dest_device, "");
juyuchendb308c22019-01-21 11:57:17 -07008183
8184 lock_input_stream(in);
8185 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008186 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, get_device_types(&devices));
juyuchendb308c22019-01-21 11:57:17 -07008187
Zhou Song503196b2021-07-23 17:31:05 +08008188 if ((in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY ||
8189 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2) &&
8190 !list_empty(&devices) &&
8191 adev->voice_tx_output != NULL) {
juyuchendb308c22019-01-21 11:57:17 -07008192 /* Use the rx device from afe-proxy record to route voice call because
8193 there is no routing if tx device is on primary hal and rx device
8194 is on other hal during voice call. */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008195 assign_devices(&adev->voice_tx_output->device_list, &devices);
juyuchendb308c22019-01-21 11:57:17 -07008196
8197 if (!voice_is_call_state_active(adev)) {
8198 if (adev->mode == AUDIO_MODE_IN_CALL) {
8199 adev->current_call_output = adev->voice_tx_output;
8200 error = voice_start_call(adev);
8201 if (error != 0)
8202 ALOGE("%s: start voice call failed %d", __func__, error);
8203 }
8204 } else {
8205 adev->current_call_output = adev->voice_tx_output;
8206 voice_update_devices_for_all_voice_usecases(adev);
8207 }
8208 }
8209
Zhenlin Lian4f947842022-05-14 15:50:52 +05308210 clear_devices(&devices);
juyuchendb308c22019-01-21 11:57:17 -07008211 pthread_mutex_unlock(&adev->lock);
8212 pthread_mutex_unlock(&in->lock);
8213}
8214
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308215int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07008216 audio_io_handle_t handle,
8217 audio_devices_t devices,
8218 audio_output_flags_t flags,
8219 struct audio_config *config,
8220 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04008221 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008222{
8223 struct audio_device *adev = (struct audio_device *)dev;
8224 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05308225 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008226 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008227 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05308228 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008229 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
8230 bool is_usb_dev = audio_is_usb_out_device(devices) &&
8231 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
8232 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008233 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07008234 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
8235 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008236 bool force_haptic_path =
8237 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07008238 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008239#ifdef AUDIO_GKI_ENABLED
8240 __s32 *generic_dec;
8241#endif
Weiyin Jiang906db3c2021-03-02 13:17:04 +08008242 pthread_mutexattr_t latch_attr;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008243
kunleizdff872d2018-08-20 14:40:33 +08008244 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08008245 is_usb_dev = false;
8246 devices = AUDIO_DEVICE_OUT_SPEAKER;
8247 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
8248 __func__, devices);
Mingshu Pangdbd20562019-11-25 18:04:39 +08008249 if (config->format == AUDIO_FORMAT_DEFAULT)
8250 config->format = AUDIO_FORMAT_PCM_16_BIT;
8251 if (config->sample_rate == 0)
8252 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8253 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8254 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
kunleizd6a9e0c2018-07-30 15:38:52 +08008255 }
8256
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008257 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05308258
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008259 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
8260
Mingming Yin3a941d42016-02-17 18:08:05 -08008261 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04008262 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
8263 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308264
8265
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008266 if (!out) {
8267 return -ENOMEM;
8268 }
8269
Haynes Mathew George204045b2015-02-25 20:32:03 -08008270 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07008271 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Weiyin Jiang906db3c2021-03-02 13:17:04 +08008272 pthread_mutexattr_init(&latch_attr);
8273 pthread_mutexattr_settype(&latch_attr, PTHREAD_MUTEX_RECURSIVE);
8274 pthread_mutex_init(&out->latch_lock, &latch_attr);
8275 pthread_mutexattr_destroy(&latch_attr);
Zhou Song48453a02018-01-10 17:50:59 +08008276 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08008277 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
8278
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008279 if (devices == AUDIO_DEVICE_NONE)
8280 devices = AUDIO_DEVICE_OUT_SPEAKER;
8281
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008282 out->flags = flags;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008283 list_init(&out->device_list);
8284 update_device_list(&out->device_list, devices, address, true /* add devices */);
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07008285 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07008286 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008287 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05308288 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05308289 if (out->channel_mask == AUDIO_CHANNEL_NONE)
8290 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
8291 else
8292 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07008293 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07008294 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08008295 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308296 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308297 out->started = 0;
Zhou Songbaddf9f2020-11-20 13:57:39 +08008298 out->a2dp_muted = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008299 out->hal_output_suspend_supported = 0;
8300 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05308301 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05308302 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05308303 out->pspd_coeff_sent = false;
Phil Burkd898ba62019-06-20 12:49:01 -07008304 out->mmap_shared_memory_fd = -1; // not open
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008305
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05308306 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05308307 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07008308 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
8309
Aalique Grahame22e49102018-12-18 14:23:57 -08008310 if (direct_dev &&
8311 (audio_is_linear_pcm(out->format) ||
8312 config->format == AUDIO_FORMAT_DEFAULT) &&
8313 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
8314 audio_format_t req_format = config->format;
8315 audio_channel_mask_t req_channel_mask = config->channel_mask;
8316 uint32_t req_sample_rate = config->sample_rate;
8317
8318 pthread_mutex_lock(&adev->lock);
8319 if (is_hdmi) {
8320 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
8321 ret = read_hdmi_sink_caps(out);
8322 if (config->sample_rate == 0)
8323 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8324 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8325 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
8326 if (config->format == AUDIO_FORMAT_DEFAULT)
8327 config->format = AUDIO_FORMAT_PCM_16_BIT;
8328 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008329 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
8330 &config->format,
8331 &out->supported_formats[0],
8332 MAX_SUPPORTED_FORMATS,
8333 &config->channel_mask,
8334 &out->supported_channel_masks[0],
8335 MAX_SUPPORTED_CHANNEL_MASKS,
8336 &config->sample_rate,
8337 &out->supported_sample_rates[0],
8338 MAX_SUPPORTED_SAMPLE_RATES);
8339 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008340 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008341
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008342 pthread_mutex_unlock(&adev->lock);
8343 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08008344 if (ret == -ENOSYS) {
8345 /* ignore and go with default */
8346 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08008347 }
8348 // For MMAP NO IRQ, allow conversions in ADSP
8349 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
8350 goto error_open;
8351 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008352 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08008353 goto error_open;
8354 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008355
8356 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
8357 config->sample_rate = req_sample_rate;
8358 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
8359 config->channel_mask = req_channel_mask;
8360 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
8361 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08008362 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008363
8364 out->sample_rate = config->sample_rate;
8365 out->channel_mask = config->channel_mask;
8366 out->format = config->format;
8367 if (is_hdmi) {
8368 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
8369 out->config = pcm_config_hdmi_multi;
8370 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8371 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8372 out->config = pcm_config_mmap_playback;
8373 out->stream.start = out_start;
8374 out->stream.stop = out_stop;
8375 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8376 out->stream.get_mmap_position = out_get_mmap_position;
8377 } else {
8378 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
8379 out->config = pcm_config_hifi;
8380 }
8381
8382 out->config.rate = out->sample_rate;
8383 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
8384 if (is_hdmi) {
8385 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
8386 audio_bytes_per_sample(out->format));
8387 }
8388 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08008389 }
8390
Derek Chenf6318be2017-06-12 17:16:24 -04008391 /* validate bus device address */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008392 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008393 /* extract car audio stream index */
8394 out->car_audio_stream =
8395 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
8396 if (out->car_audio_stream < 0) {
8397 ALOGE("%s: invalid car audio stream %x",
8398 __func__, out->car_audio_stream);
8399 ret = -EINVAL;
8400 goto error_open;
8401 }
Derek Chen5f67a942020-02-24 23:08:13 -08008402 ALOGV("%s: car_audio_stream %x", __func__, out->car_audio_stream);
Derek Chenf6318be2017-06-12 17:16:24 -04008403 }
8404
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008405 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07008406 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008407 if (!voice_extn_is_compress_voip_supported()) {
8408 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
8409 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07008410 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
Lakshman Chaluvarajue7fc9482020-05-30 14:29:29 +05308411 config->channel_mask : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008412 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
8413 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07008414 out->volume_l = INVALID_OUT_VOLUME;
8415 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07008416
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008417 out->config = default_pcm_config_voip_copp;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008418 out->config.rate = out->sample_rate;
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07008419 uint32_t channel_count =
8420 audio_channel_count_from_out_mask(out->channel_mask);
Ramjee Singh968858a2020-08-06 16:30:48 +05308421 out->config.channels = channel_count;
8422
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07008423 uint32_t buffer_size = get_stream_buffer_size(DEFAULT_VOIP_BUF_DURATION_MS,
8424 out->sample_rate, out->format,
8425 channel_count, false);
8426 uint32_t frame_size = audio_bytes_per_sample(out->format) * channel_count;
8427 if (frame_size != 0)
8428 out->config.period_size = buffer_size / frame_size;
8429 else
8430 ALOGW("%s: frame size is 0 for format %#x", __func__, out->format);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008431 }
8432 } else {
8433 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
8434 voice_extn_compress_voip_is_active(out->dev)) &&
8435 (voice_extn_compress_voip_is_config_supported(config))) {
8436 ret = voice_extn_compress_voip_open_output_stream(out);
8437 if (ret != 0) {
8438 ALOGE("%s: Compress voip output cannot be opened, error:%d",
8439 __func__, ret);
8440 goto error_open;
8441 }
Sujin Panicker19027262019-09-16 18:28:06 +05308442 } else {
8443 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8444 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008445 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008446 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008447 } else if (audio_is_linear_pcm(out->format) &&
8448 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
8449 out->channel_mask = config->channel_mask;
8450 out->sample_rate = config->sample_rate;
8451 out->format = config->format;
8452 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
8453 // does this change?
8454 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
8455 out->config.rate = config->sample_rate;
8456 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
8457 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
8458 audio_bytes_per_sample(config->format));
8459 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07008460 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308461 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308462 pthread_mutex_lock(&adev->lock);
8463 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
8464 pthread_mutex_unlock(&adev->lock);
8465
8466 // reject offload during card offline to allow
8467 // fallback to s/w paths
8468 if (offline) {
8469 ret = -ENODEV;
8470 goto error_open;
8471 }
vivek mehta0ea887a2015-08-26 14:01:20 -07008472
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008473 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
8474 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
8475 ALOGE("%s: Unsupported Offload information", __func__);
8476 ret = -EINVAL;
8477 goto error_open;
8478 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008479
Atul Khare3fa6e542017-08-09 00:56:17 +05308480 if (config->offload_info.format == 0)
8481 config->offload_info.format = config->format;
8482 if (config->offload_info.sample_rate == 0)
8483 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008484
Mingming Yin90310102013-11-13 16:57:00 -08008485 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308486 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07008487 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008488 ret = -EINVAL;
8489 goto error_open;
8490 }
8491
Ben Romberger0f8c87b2017-05-24 17:41:11 -07008492 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
8493 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
8494 (audio_extn_passthru_is_passthrough_stream(out)) &&
8495 !((config->sample_rate == 48000) ||
8496 (config->sample_rate == 96000) ||
8497 (config->sample_rate == 192000))) {
8498 ALOGE("%s: Unsupported sample rate %d for audio format %x",
8499 __func__, config->sample_rate, config->offload_info.format);
8500 ret = -EINVAL;
8501 goto error_open;
8502 }
8503
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008504 out->compr_config.codec = (struct snd_codec *)
8505 calloc(1, sizeof(struct snd_codec));
8506
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008507 if (!out->compr_config.codec) {
8508 ret = -ENOMEM;
8509 goto error_open;
8510 }
8511
Dhananjay Kumarac341582017-02-23 23:42:25 +05308512 out->stream.pause = out_pause;
8513 out->stream.resume = out_resume;
8514 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05308515 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05308516 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07008517 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05308518 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07008519 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05308520 } else {
8521 out->usecase = get_offload_usecase(adev, false /* is_compress */);
8522 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07008523 }
vivek mehta446c3962015-09-14 10:57:35 -07008524
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308525 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8526 ALOGD("%s: Setting latency mode to true", __func__);
Meng Wang4c32fb42020-01-16 17:57:11 +08008527#ifdef AUDIO_GKI_ENABLED
8528 /* out->compr_config.codec->reserved[1] is for flags */
8529 out->compr_config.codec->reserved[1] |= audio_extn_utils_get_perf_mode_flag();
8530#else
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308531 out->compr_config.codec->flags |= audio_extn_utils_get_perf_mode_flag();
Meng Wang4c32fb42020-01-16 17:57:11 +08008532#endif
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308533 }
8534
vivek mehta446c3962015-09-14 10:57:35 -07008535 if (out->usecase == USECASE_INVALID) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008536 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Mingming Yin3a941d42016-02-17 18:08:05 -08008537 config->format == 0 && config->sample_rate == 0 &&
8538 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07008539 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08008540 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
8541 } else {
8542 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
8543 ret = -EEXIST;
8544 goto error_open;
8545 }
vivek mehta446c3962015-09-14 10:57:35 -07008546 }
8547
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008548 if (config->offload_info.channel_mask)
8549 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008550 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008551 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008552 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008553 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05308554 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008555 ret = -EINVAL;
8556 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008557 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008558
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008559 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008560 out->sample_rate = config->offload_info.sample_rate;
8561
Mingming Yin3ee55c62014-08-04 14:23:35 -07008562 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008563
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308564 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05308565 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308566 audio_extn_dolby_send_ddp_endp_params(adev);
8567 audio_extn_dolby_set_dmid(adev);
8568 }
vivek mehta0ea887a2015-08-26 14:01:20 -07008569
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008570 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08008571 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008572 out->compr_config.codec->bit_rate =
8573 config->offload_info.bit_rate;
8574 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05308575 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008576 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05308577 /* Update bit width only for non passthrough usecases.
8578 * For passthrough usecases, the output will always be opened @16 bit
8579 */
8580 if (!audio_extn_passthru_is_passthrough_stream(out))
8581 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308582
8583 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
Meng Wang4c32fb42020-01-16 17:57:11 +08008584#ifdef AUDIO_GKI_ENABLED
8585 /* out->compr_config.codec->reserved[1] is for flags */
8586 out->compr_config.codec->reserved[1] |= COMPRESSED_TIMESTAMP_FLAG;
8587 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->reserved[1]);
8588#else
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308589 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
8590 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
Meng Wang4c32fb42020-01-16 17:57:11 +08008591#endif
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308592
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008593 /*TODO: Do we need to change it for passthrough */
8594 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008595
Manish Dewangana6fc5442015-08-24 20:30:31 +05308596 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
8597 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308598 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05308599 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308600 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
8601 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308602
8603 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
8604 AUDIO_FORMAT_PCM) {
8605
8606 /*Based on platform support, configure appropriate alsa format for corresponding
8607 *hal input format.
8608 */
8609 out->compr_config.codec->format = hal_format_to_alsa(
8610 config->offload_info.format);
8611
Ashish Jain83a6cc22016-06-28 14:34:17 +05308612 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05308613 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308614 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308615
Dhananjay Kumarac341582017-02-23 23:42:25 +05308616 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05308617 *hal input format and alsa format might differ based on platform support.
8618 */
8619 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05308620 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308621
8622 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
8623
Deeraj Soman93155a62019-09-30 19:00:37 +05308624 if (property_get_bool("vendor.audio.offload.buffer.duration.enabled", false)) {
8625 if ((config->offload_info.duration_us >= MIN_OFFLOAD_BUFFER_DURATION_MS * 1000) &&
8626 (config->offload_info.duration_us <= MAX_OFFLOAD_BUFFER_DURATION_MS * 1000))
8627 out->info.duration_us = (int64_t)config->offload_info.duration_us;
8628 }
Deeraj Soman65358ab2019-02-07 15:40:49 +05308629
Ashish Jainf1eaa582016-05-23 20:54:24 +05308630 /* Check if alsa session is configured with the same format as HAL input format,
8631 * if not then derive correct fragment size needed to accomodate the
8632 * conversion of HAL input format to alsa format.
8633 */
8634 audio_extn_utils_update_direct_pcm_fragment_size(out);
8635
8636 /*if hal input and output fragment size is different this indicates HAL input format is
8637 *not same as the alsa format
8638 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308639 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05308640 /*Allocate a buffer to convert input data to the alsa configured format.
8641 *size of convert buffer is equal to the size required to hold one fragment size
8642 *worth of pcm data, this is because flinger does not write more than fragment_size
8643 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308644 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
8645 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05308646 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
8647 ret = -ENOMEM;
8648 goto error_open;
8649 }
8650 }
8651 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
8652 out->compr_config.fragment_size =
8653 audio_extn_passthru_get_buffer_size(&config->offload_info);
8654 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8655 } else {
8656 out->compr_config.fragment_size =
8657 platform_get_compress_offload_buffer_size(&config->offload_info);
8658 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8659 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008660
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308661 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8662 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
8663 }
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008664 if (config->offload_info.format == AUDIO_FORMAT_FLAC) {
8665#ifdef AUDIO_GKI_ENABLED
8666 generic_dec =
8667 &(out->compr_config.codec->options.generic.reserved[1]);
8668 ((struct snd_generic_dec_flac *)generic_dec)->sample_size =
8669 AUDIO_OUTPUT_BIT_WIDTH;
8670#else
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05308671 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008672#endif
8673 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008674
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05308675 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
8676 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
8677 }
8678
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008679 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
8680 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008681
Manish Dewangan69426c82017-01-30 17:35:36 +05308682 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
8683 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
8684 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
8685 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8686 out->render_mode = RENDER_MODE_AUDIO_MASTER;
8687 } else {
8688 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
8689 }
Alexy Josephaa54c872014-12-03 02:46:47 -08008690
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05308691 memset(&out->channel_map_param, 0,
8692 sizeof(struct audio_out_channel_map_param));
8693
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008694 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05308695 out->send_next_track_params = false;
8696 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008697 out->offload_state = OFFLOAD_STATE_IDLE;
8698 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08008699 out->writeAt.tv_sec = 0;
8700 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008701
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008702 audio_extn_dts_create_state_notifier_node(out->usecase);
8703
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008704 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
8705 __func__, config->offload_info.version,
8706 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05308707
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308708 /* Check if DSD audio format is supported in codec
8709 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308710 */
8711
8712 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308713 (!platform_check_codec_dsd_support(adev->platform) ||
8714 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308715 ret = -EINVAL;
8716 goto error_open;
8717 }
8718
Ashish Jain5106d362016-05-11 19:23:33 +05308719 /* Disable gapless if any of the following is true
8720 * passthrough playback
8721 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05308722 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05308723 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308724 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308725 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07008726 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308727 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308728 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05308729 check_and_set_gapless_mode(adev, false);
8730 } else
8731 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07008732
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308733 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07008734 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
8735 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308736 if (config->format == AUDIO_FORMAT_DSD) {
8737 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
Meng Wang4c32fb42020-01-16 17:57:11 +08008738#ifdef AUDIO_GKI_ENABLED
8739 /* out->compr_config.codec->reserved[0] is for compr_passthr */
8740 out->compr_config.codec->reserved[0] = PASSTHROUGH_DSD;
8741#else
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308742 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
Meng Wang4c32fb42020-01-16 17:57:11 +08008743#endif
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308744 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07008745
8746 create_offload_callback_thread(out);
8747
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008748 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008749 switch (config->sample_rate) {
8750 case 0:
8751 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8752 break;
8753 case 8000:
8754 case 16000:
8755 case 48000:
8756 out->sample_rate = config->sample_rate;
8757 break;
8758 default:
8759 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
8760 config->sample_rate);
8761 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8762 ret = -EINVAL;
8763 goto error_open;
8764 }
8765 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8766 switch (config->channel_mask) {
8767 case AUDIO_CHANNEL_NONE:
8768 case AUDIO_CHANNEL_OUT_STEREO:
8769 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8770 break;
8771 default:
8772 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
8773 config->channel_mask);
8774 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8775 ret = -EINVAL;
8776 goto error_open;
8777 }
8778 switch (config->format) {
8779 case AUDIO_FORMAT_DEFAULT:
8780 case AUDIO_FORMAT_PCM_16_BIT:
8781 out->format = AUDIO_FORMAT_PCM_16_BIT;
8782 break;
8783 default:
8784 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
8785 config->format);
8786 config->format = AUDIO_FORMAT_PCM_16_BIT;
8787 ret = -EINVAL;
8788 goto error_open;
8789 }
8790
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05308791 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008792 if (ret != 0) {
8793 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008794 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008795 goto error_open;
8796 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008797 } else if (is_single_device_type_equal(&out->device_list,
8798 AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08008799 switch (config->sample_rate) {
8800 case 0:
8801 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
8802 break;
8803 case 8000:
8804 case 16000:
8805 case 48000:
8806 out->sample_rate = config->sample_rate;
8807 break;
8808 default:
8809 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
8810 config->sample_rate);
8811 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8812 ret = -EINVAL;
8813 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008814 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008815 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8816 switch (config->channel_mask) {
8817 case AUDIO_CHANNEL_NONE:
8818 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8819 break;
8820 case AUDIO_CHANNEL_OUT_STEREO:
8821 out->channel_mask = config->channel_mask;
8822 break;
8823 default:
8824 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
8825 config->channel_mask);
8826 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8827 ret = -EINVAL;
8828 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008829 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008830 switch (config->format) {
8831 case AUDIO_FORMAT_DEFAULT:
8832 out->format = AUDIO_FORMAT_PCM_16_BIT;
8833 break;
8834 case AUDIO_FORMAT_PCM_16_BIT:
8835 out->format = config->format;
8836 break;
8837 default:
8838 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
8839 config->format);
8840 config->format = AUDIO_FORMAT_PCM_16_BIT;
8841 ret = -EINVAL;
8842 break;
8843 }
8844 if (ret != 0)
8845 goto error_open;
8846
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008847 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
8848 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08008849 out->config.rate = out->sample_rate;
8850 out->config.channels =
8851 audio_channel_count_from_out_mask(out->channel_mask);
8852 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008853 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008854 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05308855 unsigned int channels = 0;
8856 /*Update config params to default if not set by the caller*/
8857 if (config->sample_rate == 0)
8858 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8859 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8860 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8861 if (config->format == AUDIO_FORMAT_DEFAULT)
8862 config->format = AUDIO_FORMAT_PCM_16_BIT;
8863
8864 channels = audio_channel_count_from_out_mask(out->channel_mask);
8865
Varun Balaraje49253e2017-07-06 19:48:56 +05308866 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
8867 out->usecase = get_interactive_usecase(adev);
8868 out->config = pcm_config_low_latency;
8869 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05308870 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008871 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
8872 out->flags);
8873 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07008874 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8875 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8876 out->config = pcm_config_mmap_playback;
8877 out->stream.start = out_start;
8878 out->stream.stop = out_stop;
8879 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8880 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308881 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8882 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008883 out->hal_output_suspend_supported =
8884 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
8885 out->dynamic_pm_qos_config_supported =
8886 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
8887 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08008888 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
8889 } else {
8890 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
8891 //the mixer path will be a string similar to "low-latency-playback resume"
8892 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
8893 strlcat(out->pm_qos_mixer_path,
8894 " resume", MAX_MIXER_PATH_LEN);
8895 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
8896 out->pm_qos_mixer_path);
8897 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308898 out->config = pcm_config_low_latency;
8899 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
8900 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
8901 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05308902 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
8903 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
8904 if (out->config.period_size <= 0) {
8905 ALOGE("Invalid configuration period size is not valid");
8906 ret = -EINVAL;
8907 goto error_open;
8908 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008909 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
8910 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
8911 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008912 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
8913 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
8914 out->config = pcm_config_haptics_audio;
8915 if (force_haptic_path)
8916 adev->haptics_config = pcm_config_haptics_audio;
8917 else
8918 adev->haptics_config = pcm_config_haptics;
8919
Meng Wangd08ce322020-04-02 08:59:20 +08008920 channels =
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008921 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
8922
8923 if (force_haptic_path) {
8924 out->config.channels = 1;
8925 adev->haptics_config.channels = 1;
8926 } else
8927 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 -08008928 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008929 ret = audio_extn_auto_hal_open_output_stream(out);
8930 if (ret) {
8931 ALOGE("%s: Failed to open output stream for bus device", __func__);
8932 ret = -EINVAL;
8933 goto error_open;
8934 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308935 } else {
8936 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008937 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8938 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308939 }
8940 out->hal_ip_format = format = out->format;
8941 out->config.format = hal_format_to_pcm(out->hal_ip_format);
8942 out->hal_op_format = pcm_format_to_hal(out->config.format);
8943 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
8944 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008945 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05308946 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308947 if (out->hal_ip_format != out->hal_op_format) {
8948 uint32_t buffer_size = out->config.period_size *
8949 format_to_bitwidth_table[out->hal_op_format] *
8950 out->config.channels;
8951 out->convert_buffer = calloc(1, buffer_size);
8952 if (out->convert_buffer == NULL){
8953 ALOGE("Allocation failed for convert buffer for size %d",
8954 out->compr_config.fragment_size);
8955 ret = -ENOMEM;
8956 goto error_open;
8957 }
8958 ALOGD("Convert buffer allocated of size %d", buffer_size);
8959 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008960 }
8961
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008962 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
8963 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308964
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008965 /* TODO remove this hardcoding and check why width is zero*/
8966 if (out->bit_width == 0)
8967 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308968 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008969 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008970 &out->device_list, out->flags,
8971 out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05308972 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05308973 &out->app_type_cfg);
Kogara Naveen Kumar65828fe2022-10-14 16:41:04 +05308974 if (((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
8975 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) && (!compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS))) {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08008976 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008977 if(adev->primary_output == NULL)
8978 adev->primary_output = out;
8979 else {
8980 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008981 ret = -EEXIST;
8982 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008983 }
8984 }
8985
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008986 /* Check if this usecase is already existing */
8987 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07008988 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
8989 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008990 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008991 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008992 ret = -EEXIST;
8993 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008994 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008995
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008996 pthread_mutex_unlock(&adev->lock);
8997
8998 out->stream.common.get_sample_rate = out_get_sample_rate;
8999 out->stream.common.set_sample_rate = out_set_sample_rate;
9000 out->stream.common.get_buffer_size = out_get_buffer_size;
9001 out->stream.common.get_channels = out_get_channels;
9002 out->stream.common.get_format = out_get_format;
9003 out->stream.common.set_format = out_set_format;
9004 out->stream.common.standby = out_standby;
9005 out->stream.common.dump = out_dump;
9006 out->stream.common.set_parameters = out_set_parameters;
9007 out->stream.common.get_parameters = out_get_parameters;
9008 out->stream.common.add_audio_effect = out_add_audio_effect;
9009 out->stream.common.remove_audio_effect = out_remove_audio_effect;
9010 out->stream.get_latency = out_get_latency;
9011 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08009012#ifdef NO_AUDIO_OUT
9013 out->stream.write = out_write_for_no_output;
9014#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009015 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08009016#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009017 out->stream.get_render_position = out_get_render_position;
9018 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07009019 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009020
Haynes Mathew George16081042017-05-31 17:16:49 -07009021 if (out->realtime)
9022 out->af_period_multiplier = af_period_multiplier;
9023 else
9024 out->af_period_multiplier = 1;
9025
Andy Hunga1f48fa2019-07-01 18:14:53 -07009026 out->kernel_buffer_size = out->config.period_size * out->config.period_count;
9027
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009028 out->standby = 1;
Zhou Songbaddf9f2020-11-20 13:57:39 +08009029 out->volume_l = PLAYBACK_GAIN_MAX;
9030 out->volume_r = PLAYBACK_GAIN_MAX;
Eric Laurenta9024de2013-04-04 09:19:12 -07009031 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07009032 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009033
9034 config->format = out->stream.common.get_format(&out->stream.common);
9035 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
9036 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05309037 register_format(out->format, out->supported_formats);
9038 register_channel_mask(out->channel_mask, out->supported_channel_masks);
9039 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009040
Dechen Chai22768452021-07-30 09:29:16 +05309041#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -08009042 out->error_log = error_log_create(
9043 ERROR_LOG_ENTRIES,
9044 1000000000 /* aggregate consecutive identical errors within one second in ns */);
Dechen Chai22768452021-07-30 09:29:16 +05309045#endif
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309046 /*
9047 By locking output stream before registering, we allow the callback
9048 to update stream's state only after stream's initial state is set to
9049 adev state.
9050 */
9051 lock_output_stream(out);
9052 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
9053 pthread_mutex_lock(&adev->lock);
9054 out->card_status = adev->card_status;
9055 pthread_mutex_unlock(&adev->lock);
9056 pthread_mutex_unlock(&out->lock);
9057
Aalique Grahame22e49102018-12-18 14:23:57 -08009058 stream_app_type_cfg_init(&out->app_type_cfg);
9059
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009060 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309061 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07009062 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08009063
9064 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
9065 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
9066 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08009067 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05309068 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08009069 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07009070 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05309071 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
9072 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08009073 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
9074 out->usecase, PCM_PLAYBACK);
9075 hdlr_stream_cfg.flags = out->flags;
9076 hdlr_stream_cfg.type = PCM_PLAYBACK;
9077 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
9078 &hdlr_stream_cfg);
9079 if (ret) {
9080 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
9081 out->adsp_hdlr_stream_handle = NULL;
9082 }
9083 }
Gangadhar Sb0210342019-02-22 17:39:41 +05309084 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
9085 is_direct_passthough, false);
9086 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
9087 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07009088 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07009089 if (ret < 0) {
9090 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
9091 out->ip_hdlr_handle = NULL;
9092 }
9093 }
Derek Chenf939fb72018-11-13 13:34:41 -08009094
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009095 ret = io_streams_map_insert(adev, &out->stream.common,
9096 out->handle, AUDIO_PATCH_HANDLE_NONE);
9097 if (ret != 0)
9098 goto error_open;
9099
Susan Wang6dd13092021-01-25 10:27:11 -05009100 out->out_ctxt.output = out;
Derek Chenf939fb72018-11-13 13:34:41 -08009101
9102 pthread_mutex_lock(&adev->lock);
Susan Wang6dd13092021-01-25 10:27:11 -05009103 list_add_tail(&adev->active_outputs_list, &out->out_ctxt.list);
Derek Chenf939fb72018-11-13 13:34:41 -08009104 pthread_mutex_unlock(&adev->lock);
9105
Eric Laurent994a6932013-07-17 11:51:42 -07009106 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009107 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07009108
9109error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05309110 if (out->convert_buffer)
9111 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07009112 free(out);
9113 *stream_out = NULL;
9114 ALOGD("%s: exit: ret %d", __func__, ret);
9115 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009116}
9117
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309118void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009119 struct audio_stream_out *stream)
9120{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07009121 struct stream_out *out = (struct stream_out *)stream;
9122 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009123 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07009124
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009125 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309126
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009127 io_streams_map_remove(adev, out->handle);
9128
Susan Wang6dd13092021-01-25 10:27:11 -05009129 // remove out_ctxt early to prevent the stream
9130 // being opened in a race condition
9131 pthread_mutex_lock(&adev->lock);
9132 list_remove(&out->out_ctxt.list);
9133 pthread_mutex_unlock(&adev->lock);
9134
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309135 // must deregister from sndmonitor first to prevent races
9136 // between the callback and close_stream
9137 audio_extn_snd_mon_unregister_listener(out);
9138
Ben Rombergerd771a7c2017-02-22 18:05:17 -08009139 /* close adsp hdrl session before standby */
9140 if (out->adsp_hdlr_stream_handle) {
9141 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
9142 if (ret)
9143 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
9144 out->adsp_hdlr_stream_handle = NULL;
9145 }
9146
Manish Dewangan21a850a2017-08-14 12:03:55 +05309147 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07009148 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
9149 out->ip_hdlr_handle = NULL;
9150 }
9151
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009152 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309153 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009154 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05309155 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309156 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009157 if(ret != 0)
9158 ALOGE("%s: Compress voip output cannot be closed, error:%d",
9159 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009160 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009161 out_standby(&stream->common);
9162
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07009163 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08009164 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07009165 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07009166 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07009167 if (out->compr_config.codec != NULL)
9168 free(out->compr_config.codec);
9169 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009170
Zhou Songbaddf9f2020-11-20 13:57:39 +08009171 out->a2dp_muted = false;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05309172
Varun Balaraje49253e2017-07-06 19:48:56 +05309173 if (is_interactive_usecase(out->usecase))
9174 free_interactive_usecase(adev, out->usecase);
9175
Ashish Jain83a6cc22016-06-28 14:34:17 +05309176 if (out->convert_buffer != NULL) {
9177 free(out->convert_buffer);
9178 out->convert_buffer = NULL;
9179 }
9180
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009181 if (adev->voice_tx_output == out)
9182 adev->voice_tx_output = NULL;
9183
Dechen Chai22768452021-07-30 09:29:16 +05309184#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -08009185 error_log_destroy(out->error_log);
9186 out->error_log = NULL;
Dechen Chai22768452021-07-30 09:29:16 +05309187#endif
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05309188 if (adev->primary_output == out)
9189 adev->primary_output = NULL;
9190
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07009191 pthread_cond_destroy(&out->cond);
9192 pthread_mutex_destroy(&out->lock);
Weiyin Jiang280ea742020-09-08 20:28:22 +08009193 pthread_mutex_destroy(&out->pre_lock);
9194 pthread_mutex_destroy(&out->latch_lock);
9195 pthread_mutex_destroy(&out->position_query_lock);
Derek Chenf939fb72018-11-13 13:34:41 -08009196
9197 pthread_mutex_lock(&adev->lock);
Zhenlin Lian4f947842022-05-14 15:50:52 +05309198 clear_devices(&out->device_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009199 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08009200 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07009201 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009202}
9203
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05009204void in_set_power_policy(uint8_t enable)
9205{
9206 struct listnode *node;
9207
9208 ALOGD("%s: Enter, state %d", __func__, enable);
9209
9210 pthread_mutex_lock(&adev->lock);
9211 adev->in_power_policy = enable ? POWER_POLICY_STATUS_ONLINE : POWER_POLICY_STATUS_OFFLINE;
9212 pthread_mutex_unlock(&adev->lock);
9213
9214 if (!enable) {
9215 list_for_each(node, &adev->active_inputs_list) {
9216 streams_input_ctxt_t *in_ctxt = node_to_item(node,
9217 streams_input_ctxt_t,
9218 list);
9219 struct stream_in *in = in_ctxt->input;
9220 in_standby(&in->stream.common);
9221 }
9222 }
9223
9224 ALOGD("%s: Exit", __func__);
9225}
9226
9227void out_set_power_policy(uint8_t enable)
9228{
9229 struct listnode *node;
9230
9231 ALOGD("%s: Enter, state %d", __func__, enable);
9232
9233 pthread_mutex_lock(&adev->lock);
E V Ravi317be872022-02-23 19:08:15 +05309234 adev->out_power_policy = enable ? POWER_POLICY_STATUS_ONLINE : POWER_POLICY_STATUS_OFFLINE;
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05009235 pthread_mutex_unlock(&adev->lock);
9236
9237 if (!enable) {
9238 list_for_each(node, &adev->active_outputs_list) {
9239 streams_output_ctxt_t *out_ctxt = node_to_item(node,
9240 streams_output_ctxt_t,
9241 list);
9242 struct stream_out *out = out_ctxt->output;
9243 out_on_error(&out->stream.common);
9244 }
9245 }
9246
9247 ALOGD("%s: Exit", __func__);
9248}
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009249static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
9250{
9251 struct audio_device *adev = (struct audio_device *)dev;
9252 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009253 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07009254 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009255 int ret;
9256 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08009257 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08009258 struct listnode *node;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07009259 int controller = -1, stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009260
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009261 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009262 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009263
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05309264 if (!parms)
9265 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05309266
Derek Chen6f293672019-04-01 01:40:24 -07009267 /* notify adev and input/output streams on the snd card status */
9268 adev_snd_mon_cb((void *)adev, parms);
9269
Weiyin Jiang24f55292020-12-22 14:35:46 +08009270 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
9271 if (ret >= 0) {
9272 list_for_each(node, &adev->active_outputs_list) {
9273 streams_output_ctxt_t *out_ctxt = node_to_item(node,
9274 streams_output_ctxt_t,
9275 list);
9276 out_snd_mon_cb((void *)out_ctxt->output, parms);
9277 }
Derek Chen6f293672019-04-01 01:40:24 -07009278
Weiyin Jiang24f55292020-12-22 14:35:46 +08009279 list_for_each(node, &adev->active_inputs_list) {
9280 streams_input_ctxt_t *in_ctxt = node_to_item(node,
9281 streams_input_ctxt_t,
9282 list);
9283 in_snd_mon_cb((void *)in_ctxt->input, parms);
9284 }
Derek Chen6f293672019-04-01 01:40:24 -07009285 }
9286
Zhou Songd6d71752019-05-21 18:08:51 +08009287 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05309288 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
9289 if (ret >= 0) {
9290 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08009291 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05309292 adev->bt_sco_on = true;
Shalini Manjunatha3a2e06e2021-02-01 12:23:49 +05309293 /*
9294 * When ever BT_SCO=ON arrives, make sure to route
9295 * all use cases to SCO device, otherwise due to delay in
9296 * BT_SCO=ON and lack of synchronization with create audio patch
9297 * request for SCO device, some times use case not routed properly to
9298 * SCO device
9299 */
9300 struct audio_usecase *usecase;
9301 struct listnode *node;
9302 list_for_each(node, &adev->usecase_list) {
9303 usecase = node_to_item(node, struct audio_usecase, list);
Anver sadhiquef0efca32021-09-03 15:25:44 +05309304 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
Anver sadhique93f3c912021-08-11 11:19:45 +05309305 (!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 +05309306 ALOGD("BT_SCO ON, switch all in use case to it");
9307 select_devices(adev, usecase->id);
9308 }
Mingshu Pangef517202021-04-22 10:35:00 +08009309 if (usecase->stream.out && (usecase->type == PCM_PLAYBACK ||
9310 usecase->type == VOICE_CALL) &&
Anver sadhique93f3c912021-08-11 11:19:45 +05309311 (!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 +05309312 ALOGD("BT_SCO ON, switch all out use case to it");
9313 select_devices(adev, usecase->id);
9314 }
9315 }
9316 }
9317 else {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05309318 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08009319 audio_extn_sco_reset_configuration();
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08009320 }
9321 }
9322
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009323 status = voice_set_parameters(adev, parms);
9324 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08009325 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009326
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009327 status = platform_set_parameters(adev->platform, parms);
9328 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08009329 goto done;
9330
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009331 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
9332 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07009333 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009334 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
9335 adev->bluetooth_nrec = true;
9336 else
9337 adev->bluetooth_nrec = false;
9338 }
9339
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009340 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
9341 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009342 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
9343 adev->screen_off = false;
9344 else
9345 adev->screen_off = true;
Quinn Male70f20f32019-06-26 16:50:26 -07009346 audio_extn_sound_trigger_update_screen_status(adev->screen_off);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009347 }
9348
Eric Laurent4b084132018-10-19 17:33:43 -07009349 ret = str_parms_get_int(parms, "rotation", &val);
9350 if (ret >= 0) {
9351 bool reverse_speakers = false;
9352 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
9353 switch (val) {
9354 // FIXME: note that the code below assumes that the speakers are in the correct placement
9355 // relative to the user when the device is rotated 90deg from its default rotation. This
9356 // assumption is device-specific, not platform-specific like this code.
9357 case 270:
9358 reverse_speakers = true;
9359 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
9360 break;
9361 case 0:
9362 case 180:
9363 camera_rotation = CAMERA_ROTATION_PORTRAIT;
9364 break;
9365 case 90:
9366 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
9367 break;
9368 default:
9369 ALOGE("%s: unexpected rotation of %d", __func__, val);
9370 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07009371 }
Eric Laurent4b084132018-10-19 17:33:43 -07009372 if (status == 0) {
9373 // check and set swap
9374 // - check if orientation changed and speaker active
9375 // - set rotation and cache the rotation value
9376 adev->camera_orientation =
9377 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
9378 if (!audio_extn_is_maxx_audio_enabled())
9379 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
9380 }
9381 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07009382
Mingming Yin514a8bc2014-07-29 15:22:21 -07009383 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
9384 if (ret >= 0) {
9385 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
9386 adev->bt_wb_speech_enabled = true;
9387 else
9388 adev->bt_wb_speech_enabled = false;
9389 }
9390
Zhou Song12c29502019-03-16 10:37:18 +08009391 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
9392 if (ret >= 0) {
9393 val = atoi(value);
9394 adev->swb_speech_mode = val;
9395 }
9396
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07009397 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
9398 if (ret >= 0) {
9399 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309400 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08009401 if (audio_is_output_device(val) &&
9402 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07009403 ALOGV("cache new ext disp type and edid");
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07009404 platform_get_controller_stream_from_params(parms, &controller, &stream);
9405 platform_set_ext_display_device_v2(adev->platform, controller, stream);
9406 ret = platform_get_ext_disp_type_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07009407 if (ret < 0) {
9408 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05309409 } else {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07009410 platform_cache_edid_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07009411 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309412 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07009413 /*
9414 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
9415 * Per AudioPolicyManager, USB device is higher priority than WFD.
9416 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
9417 * If WFD use case occupies AFE proxy, it may result unintended behavior while
9418 * starting voice call on USB
9419 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08009420 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309421 if (ret >= 0)
9422 audio_extn_usb_add_device(device, atoi(value));
9423
Zhou Song6f862822017-11-06 17:27:57 +08009424 if (!audio_extn_usb_is_tunnel_supported()) {
9425 ALOGV("detected USB connect .. disable proxy");
9426 adev->allow_afe_proxy_usage = false;
9427 }
Zhou Song503196b2021-07-23 17:31:05 +08009428 } else if (audio_is_hearing_aid_out_device(device) &&
9429 property_get_bool("persist.vendor.audio.ha_proxy.enabled", false)) {
9430 adev->ha_proxy_enable = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07009431 }
9432 }
9433
9434 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
9435 if (ret >= 0) {
9436 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309437 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07009438 /*
9439 * The HDMI / Displayport disconnect handling has been moved to
9440 * audio extension to ensure that its parameters are not
9441 * invalidated prior to updating sysfs of the disconnect event
9442 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
9443 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309444 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08009445 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309446 if (ret >= 0)
9447 audio_extn_usb_remove_device(device, atoi(value));
9448
Zhou Song6f862822017-11-06 17:27:57 +08009449 if (!audio_extn_usb_is_tunnel_supported()) {
9450 ALOGV("detected USB disconnect .. enable proxy");
9451 adev->allow_afe_proxy_usage = true;
9452 }
Zhou Song503196b2021-07-23 17:31:05 +08009453 } else if (audio_is_hearing_aid_out_device(device)) {
9454 adev->ha_proxy_enable = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07009455 }
9456 }
9457
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009458 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08009459
9460 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08009461 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309462 struct audio_usecase *usecase;
9463 struct listnode *node;
9464 list_for_each(node, &adev->usecase_list) {
9465 usecase = node_to_item(node, struct audio_usecase, list);
Weiyin Jiangff56ff32020-05-08 14:32:21 +08009466 if ((usecase->stream.out == NULL) || (usecase->type != PCM_PLAYBACK))
9467 continue;
9468
9469 if (is_a2dp_out_device_type(&usecase->device_list)) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309470 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05309471 audio_extn_a2dp_set_handoff_mode(true);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05309472 ALOGD("Switching to speaker and muting the stream before select_devices");
9473 check_a2dp_restore_l(adev, usecase->stream.out, false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309474 //force device switch to re configure encoder
9475 select_devices(adev, usecase->id);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05309476 ALOGD("Unmuting the stream after select_devices");
Zhou Songbaddf9f2020-11-20 13:57:39 +08009477 check_a2dp_restore_l(adev, usecase->stream.out, true);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05309478 audio_extn_a2dp_set_handoff_mode(false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309479 break;
Zhou Songd01e7a22020-09-23 22:49:01 +08009480 } else if (is_offload_usecase(usecase->stream.out->usecase)) {
Weiyin Jiang280ea742020-09-08 20:28:22 +08009481 pthread_mutex_lock(&usecase->stream.out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +08009482 if (usecase->stream.out->a2dp_muted) {
Weiyin Jiang280ea742020-09-08 20:28:22 +08009483 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
9484 reassign_device_list(&usecase->stream.out->device_list,
9485 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, "");
9486 check_a2dp_restore_l(adev, usecase->stream.out, true);
9487 break;
9488 }
9489 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309490 }
9491 }
9492 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009493
9494 //handle vr audio setparam
9495 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9496 value, sizeof(value));
9497 if (ret >= 0) {
9498 ALOGI("Setting vr mode to be %s", value);
9499 if (!strncmp(value, "true", 4)) {
9500 adev->vr_audio_mode_enabled = true;
9501 ALOGI("Setting vr mode to true");
9502 } else if (!strncmp(value, "false", 5)) {
9503 adev->vr_audio_mode_enabled = false;
9504 ALOGI("Setting vr mode to false");
9505 } else {
9506 ALOGI("wrong vr mode set");
9507 }
9508 }
9509
Eric Laurent4b084132018-10-19 17:33:43 -07009510 //FIXME: to be replaced by proper video capture properties API
9511 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
9512 if (ret >= 0) {
9513 int camera_facing = CAMERA_FACING_BACK;
9514 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
9515 camera_facing = CAMERA_FACING_FRONT;
9516 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
9517 camera_facing = CAMERA_FACING_BACK;
9518 else {
9519 ALOGW("%s: invalid camera facing value: %s", __func__, value);
9520 goto done;
9521 }
9522 adev->camera_orientation =
9523 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
9524 struct audio_usecase *usecase;
9525 struct listnode *node;
9526 list_for_each(node, &adev->usecase_list) {
9527 usecase = node_to_item(node, struct audio_usecase, list);
9528 struct stream_in *in = usecase->stream.in;
9529 if (usecase->type == PCM_CAPTURE && in != NULL &&
9530 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
9531 select_devices(adev, in->usecase);
9532 }
9533 }
9534 }
9535
Tahir Dawson7fabad42022-06-21 12:37:55 -04009536 audio_extn_auto_hal_set_parameters(adev, parms);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05309537 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08009538done:
9539 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009540 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05309541error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009542 ALOGV("%s: exit with code(%d)", __func__, status);
9543 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009544}
9545
9546static char* adev_get_parameters(const struct audio_hw_device *dev,
9547 const char *keys)
9548{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05309549 ALOGD("%s:%s", __func__, keys);
9550
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009551 struct audio_device *adev = (struct audio_device *)dev;
9552 struct str_parms *reply = str_parms_create();
9553 struct str_parms *query = str_parms_create_str(keys);
9554 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05309555 char value[256] = {0};
9556 int ret = 0;
9557
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009558 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08009559 if (reply) {
9560 str_parms_destroy(reply);
9561 }
9562 if (query) {
9563 str_parms_destroy(query);
9564 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009565 ALOGE("adev_get_parameters: failed to create query or reply");
9566 return NULL;
9567 }
9568
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009569 //handle vr audio getparam
9570
9571 ret = str_parms_get_str(query,
9572 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9573 value, sizeof(value));
9574
9575 if (ret >= 0) {
9576 bool vr_audio_enabled = false;
9577 pthread_mutex_lock(&adev->lock);
9578 vr_audio_enabled = adev->vr_audio_mode_enabled;
9579 pthread_mutex_unlock(&adev->lock);
9580
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07009581 ALOGV("getting vr mode to %d", vr_audio_enabled);
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009582
9583 if (vr_audio_enabled) {
9584 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9585 "true");
9586 goto exit;
9587 } else {
9588 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9589 "false");
9590 goto exit;
9591 }
9592 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009593
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009594 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009595 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08009596 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08009597 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009598 platform_get_parameters(adev->platform, query, reply);
justinwengd5395152019-11-04 12:23:09 +08009599 audio_extn_ma_get_parameters(adev, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05309600 pthread_mutex_unlock(&adev->lock);
9601
Naresh Tannirud7205b62014-06-20 02:54:48 +05309602exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009603 str = str_parms_to_str(reply);
9604 str_parms_destroy(query);
9605 str_parms_destroy(reply);
9606
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07009607 ALOGV("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009608 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009609}
9610
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009611static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009612{
9613 return 0;
9614}
9615
9616static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
9617{
Haynes Mathew George5191a852013-09-11 14:19:36 -07009618 int ret;
9619 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08009620
9621 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
9622
Haynes Mathew George5191a852013-09-11 14:19:36 -07009623 pthread_mutex_lock(&adev->lock);
9624 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07009625 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07009626 pthread_mutex_unlock(&adev->lock);
9627 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009628}
9629
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009630static int adev_set_master_volume(struct audio_hw_device *dev __unused,
9631 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009632{
9633 return -ENOSYS;
9634}
9635
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009636static int adev_get_master_volume(struct audio_hw_device *dev __unused,
9637 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009638{
9639 return -ENOSYS;
9640}
9641
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009642static int adev_set_master_mute(struct audio_hw_device *dev __unused,
9643 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009644{
9645 return -ENOSYS;
9646}
9647
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009648static int adev_get_master_mute(struct audio_hw_device *dev __unused,
9649 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009650{
9651 return -ENOSYS;
9652}
9653
9654static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
9655{
9656 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07009657 struct listnode *node;
9658 struct audio_usecase *usecase = NULL;
9659 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08009660
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009661 pthread_mutex_lock(&adev->lock);
9662 if (adev->mode != mode) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309663 ALOGD("%s: mode %d , prev_mode %d \n", __func__, mode , adev->mode);
9664 adev->prev_mode = adev->mode; /* prev_mode is kept to handle voip concurrency*/
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009665 adev->mode = mode;
Weiyin Jiang96b96f72020-09-22 16:48:19 +08009666 if (mode == AUDIO_MODE_CALL_SCREEN) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309667 adev->current_call_output = adev->primary_output;
9668 voice_start_call(adev);
9669 } else if (voice_is_in_call_or_call_screen(adev) &&
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08009670 (mode == AUDIO_MODE_NORMAL ||
9671 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07009672 list_for_each(node, &adev->usecase_list) {
9673 usecase = node_to_item(node, struct audio_usecase, list);
9674 if (usecase->type == VOICE_CALL)
9675 break;
9676 }
9677 if (usecase &&
9678 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
9679 ret = audio_extn_usb_check_and_set_svc_int(usecase,
9680 true);
9681 if (ret != 0) {
9682 /* default service interval was successfully updated,
9683 reopen USB backend with new service interval */
9684 check_usecases_codec_backend(adev,
9685 usecase,
9686 usecase->out_snd_device);
9687 }
9688 }
9689
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009690 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07009691 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009692 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08009693 // restore device for other active usecases after stop call
9694 list_for_each(node, &adev->usecase_list) {
9695 usecase = node_to_item(node, struct audio_usecase, list);
9696 select_devices(adev, usecase->id);
9697 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009698 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009699 }
9700 pthread_mutex_unlock(&adev->lock);
9701 return 0;
9702}
9703
9704static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
9705{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009706 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08009707 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009708
9709 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08009710 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009711 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009712
Derek Chend2530072014-11-24 12:39:14 -08009713 if (adev->ext_hw_plugin)
9714 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009715
9716 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009717 pthread_mutex_unlock(&adev->lock);
9718
9719 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009720}
9721
9722static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
9723{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009724 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009725 return 0;
9726}
9727
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009728static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009729 const struct audio_config *config)
9730{
Avinash Chandrad7296d42021-08-04 15:07:47 +05309731 bool is_usb_hifi = IS_USB_HIFI;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009732 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009733
Aalique Grahame22e49102018-12-18 14:23:57 -08009734 /* Don't know if USB HIFI in this context so use true to be conservative */
9735 if (check_input_parameters(config->sample_rate, config->format, channel_count,
Avinash Chandrad7296d42021-08-04 15:07:47 +05309736 is_usb_hifi) != 0)
Aalique Grahame22e49102018-12-18 14:23:57 -08009737 return 0;
9738
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009739 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
9740 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009741}
9742
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009743static bool adev_input_allow_hifi_record(struct audio_device *adev,
9744 audio_devices_t devices,
9745 audio_input_flags_t flags,
9746 audio_source_t source) {
9747 const bool allowed = true;
9748
9749 if (!audio_is_usb_in_device(devices))
9750 return !allowed;
9751
9752 switch (flags) {
9753 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009754 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07009755 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
9756 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009757 default:
9758 return !allowed;
9759 }
9760
9761 switch (source) {
9762 case AUDIO_SOURCE_DEFAULT:
9763 case AUDIO_SOURCE_MIC:
9764 case AUDIO_SOURCE_UNPROCESSED:
9765 break;
9766 default:
9767 return !allowed;
9768 }
9769
9770 switch (adev->mode) {
9771 case 0:
9772 break;
9773 default:
9774 return !allowed;
9775 }
9776
9777 return allowed;
9778}
9779
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009780static int adev_update_voice_comm_input_stream(struct stream_in *in,
9781 struct audio_config *config)
9782{
9783 bool valid_rate = (config->sample_rate == 8000 ||
9784 config->sample_rate == 16000 ||
9785 config->sample_rate == 32000 ||
9786 config->sample_rate == 48000);
9787 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
9788
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009789 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08009790 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009791 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9792 in->config = default_pcm_config_voip_copp;
9793 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
9794 DEFAULT_VOIP_BUF_DURATION_MS,
9795 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009796 } else {
9797 ALOGW("%s No valid input in voip, use defaults"
9798 "sample rate %u, channel mask 0x%X",
9799 __func__, config->sample_rate, in->channel_mask);
9800 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009801 in->config.rate = config->sample_rate;
9802 in->sample_rate = config->sample_rate;
9803 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009804 //XXX needed for voice_extn_compress_voip_open_input_stream
9805 in->config.rate = config->sample_rate;
9806 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
Shalini Manjunathaa763cc42019-08-23 15:13:46 +05309807 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009808 voice_extn_compress_voip_is_active(in->dev)) &&
9809 (voice_extn_compress_voip_is_format_supported(in->format)) &&
9810 valid_rate && valid_ch) {
9811 voice_extn_compress_voip_open_input_stream(in);
9812 // update rate entries to match config from AF
9813 in->config.rate = config->sample_rate;
9814 in->sample_rate = config->sample_rate;
9815 } else {
9816 ALOGW("%s compress voip not active, use defaults", __func__);
9817 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009818 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009819 return 0;
9820}
9821
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009822static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07009823 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009824 audio_devices_t devices,
9825 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009826 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309827 audio_input_flags_t flags,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009828 const char *address,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009829 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009830{
9831 struct audio_device *adev = (struct audio_device *)dev;
9832 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009833 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009834 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009835 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05309836 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009837 bool is_usb_dev = audio_is_usb_in_device(devices);
9838 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
9839 devices,
9840 flags,
9841 source);
Andy Hung94320602018-10-29 18:31:12 -07009842 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
9843 " sample_rate %u, channel_mask %#x, format %#x",
9844 __func__, flags, is_usb_dev, may_use_hifi_record,
9845 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309846
kunleizdff872d2018-08-20 14:40:33 +08009847 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08009848 is_usb_dev = false;
9849 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
9850 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
9851 __func__, devices);
9852 }
9853
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009854 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009855
9856 if (!(is_usb_dev && may_use_hifi_record)) {
9857 if (config->sample_rate == 0)
9858 config->sample_rate = 48000;
9859 if (config->channel_mask == AUDIO_CHANNEL_NONE)
9860 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9861 if (config->format == AUDIO_FORMAT_DEFAULT)
9862 config->format = AUDIO_FORMAT_PCM_16_BIT;
9863
9864 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
9865
Aalique Grahame22e49102018-12-18 14:23:57 -08009866 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9867 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009868 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05309869 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009870
9871 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009872
9873 if (!in) {
9874 ALOGE("failed to allocate input stream");
9875 return -ENOMEM;
9876 }
9877
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309878 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05309879 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
9880 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009881 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07009882 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009883
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009884 in->stream.common.get_sample_rate = in_get_sample_rate;
9885 in->stream.common.set_sample_rate = in_set_sample_rate;
9886 in->stream.common.get_buffer_size = in_get_buffer_size;
9887 in->stream.common.get_channels = in_get_channels;
9888 in->stream.common.get_format = in_get_format;
9889 in->stream.common.set_format = in_set_format;
9890 in->stream.common.standby = in_standby;
9891 in->stream.common.dump = in_dump;
9892 in->stream.common.set_parameters = in_set_parameters;
9893 in->stream.common.get_parameters = in_get_parameters;
9894 in->stream.common.add_audio_effect = in_add_audio_effect;
9895 in->stream.common.remove_audio_effect = in_remove_audio_effect;
9896 in->stream.set_gain = in_set_gain;
9897 in->stream.read = in_read;
9898 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08009899 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309900 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07009901 in->stream.set_microphone_direction = in_set_microphone_direction;
9902 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07009903 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009904
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009905 list_init(&in->device_list);
9906 update_device_list(&in->device_list, devices, address, true);
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009907 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009908 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009909 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009910 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009911 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07009912 in->bit_width = 16;
9913 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07009914 in->direction = MIC_DIRECTION_UNSPECIFIED;
9915 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08009916 list_init(&in->aec_list);
9917 list_init(&in->ns_list);
Phil Burkd898ba62019-06-20 12:49:01 -07009918 in->mmap_shared_memory_fd = -1; // not open
Haynes Mathew George46740472017-10-27 18:40:12 -07009919
Andy Hung94320602018-10-29 18:31:12 -07009920 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08009921 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
9922 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
9923 /* Force channel config requested to mono if incall
9924 record is being requested for only uplink/downlink */
9925 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
9926 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9927 ret = -EINVAL;
9928 goto err_open;
9929 }
9930 }
9931
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009932 if (is_usb_dev && may_use_hifi_record) {
9933 /* HiFi record selects an appropriate format, channel, rate combo
9934 depending on sink capabilities*/
9935 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
9936 &config->format,
9937 &in->supported_formats[0],
9938 MAX_SUPPORTED_FORMATS,
9939 &config->channel_mask,
9940 &in->supported_channel_masks[0],
9941 MAX_SUPPORTED_CHANNEL_MASKS,
9942 &config->sample_rate,
9943 &in->supported_sample_rates[0],
9944 MAX_SUPPORTED_SAMPLE_RATES);
9945 if (ret != 0) {
9946 ret = -EINVAL;
9947 goto err_open;
9948 }
9949 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009950 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309951 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05309952 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
9953 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
9954 in->config.format = PCM_FORMAT_S32_LE;
9955 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309956 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
9957 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
9958 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
9959 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
9960 bool ret_error = false;
9961 in->bit_width = 24;
9962 /* 24 bit is restricted to UNPROCESSED source only,also format supported
9963 from HAL is 24_packed and 8_24
9964 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
9965 24_packed return error indicating supported format is 24_packed
9966 *> In case of any other source requesting 24 bit or float return error
9967 indicating format supported is 16 bit only.
9968
9969 on error flinger will retry with supported format passed
9970 */
9971 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
9972 (source != AUDIO_SOURCE_CAMCORDER)) {
9973 config->format = AUDIO_FORMAT_PCM_16_BIT;
9974 if (config->sample_rate > 48000)
9975 config->sample_rate = 48000;
9976 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07009977 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
9978 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309979 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
9980 ret_error = true;
9981 }
9982
9983 if (ret_error) {
9984 ret = -EINVAL;
9985 goto err_open;
9986 }
9987 }
9988
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009989 in->channel_mask = config->channel_mask;
9990 in->format = config->format;
9991
9992 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309993
Huicheng Liu1404ba12020-09-11 01:03:25 -04009994 /* validate bus device address */
9995 if (compare_device_type(&in->device_list, AUDIO_DEVICE_IN_BUS)) {
9996 /* extract car audio stream index */
9997 in->car_audio_stream =
9998 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
9999 if (in->car_audio_stream < 0) {
10000 ALOGE("%s: invalid car audio stream %x",
10001 __func__, in->car_audio_stream);
10002 ret = -EINVAL;
10003 goto err_open;
10004 }
10005 ALOGV("%s: car_audio_stream 0x%x", __func__, in->car_audio_stream);
Huicheng Liuea4fd422021-01-12 18:34:50 -050010006 ret = audio_extn_auto_hal_open_input_stream(in);
10007 if (ret) {
10008 ALOGE("%s: Failed to open input stream for bus device", __func__);
10009 ret = -EINVAL;
10010 goto err_open;
10011 }
Huicheng Liu1404ba12020-09-11 01:03:25 -040010012 }
10013
Susan Wange3959562021-03-11 11:50:26 -050010014 /* reassign use case for echo reference stream on automotive platforms */
10015 if (in->source == AUDIO_SOURCE_ECHO_REFERENCE) {
10016 ret = audio_extn_auto_hal_open_echo_reference_stream(in);
10017 }
10018
Kogara Naveen Kumar379ff692022-01-31 11:56:51 +053010019 if ((in->source == AUDIO_SOURCE_FM_TUNER) || (devices == AUDIO_DEVICE_IN_FM_TUNER)) {
Samyak Jain0aa07ab2019-04-04 14:36:32 +053010020 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
10021 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
10022 else {
10023 ret = -EINVAL;
10024 goto err_open;
10025 }
10026 }
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +053010027#ifdef PLATFORM_AUTO
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +053010028 if ((config->sample_rate == 48000 ||
10029 config->sample_rate == 32000 ||
10030 config->sample_rate == 24000 ||
10031 config->sample_rate == 16000 ||
10032 config->sample_rate == 8000)&&
Deeraj Somanfa377bf2019-02-06 12:57:59 +053010033 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
10034 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +053010035 (flags & AUDIO_INPUT_FLAG_FAST) != 0)
10036#else
10037 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
10038 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
10039 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
10040 (flags & AUDIO_INPUT_FLAG_FAST) != 0)
10041#endif
10042{
Haynes Mathew George484e8d22017-07-31 18:55:17 -070010043 is_low_latency = true;
10044#if LOW_LATENCY_CAPTURE_USE_CASE
Revathi Uddarajud9f23d92020-07-27 10:55:06 +053010045 if ((flags & AUDIO_INPUT_FLAG_VOIP_TX) != 0)
10046 in->usecase = USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY;
10047 else
10048 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Haynes Mathew George484e8d22017-07-31 18:55:17 -070010049#endif
10050 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -080010051 if (!in->realtime) {
10052 in->config = pcm_config_audio_capture;
10053 frame_size = audio_stream_in_frame_size(&in->stream);
10054 buffer_size = get_input_buffer_size(config->sample_rate,
10055 config->format,
10056 channel_count,
10057 is_low_latency);
10058 in->config.period_size = buffer_size / frame_size;
10059 in->config.rate = config->sample_rate;
10060 in->af_period_multiplier = 1;
10061 } else {
10062 // period size is left untouched for rt mode playback
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +053010063#ifdef PLATFORM_AUTO
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +053010064 switch(config->sample_rate)
10065 {
10066 case 48000:
10067 in->config = pcm_config_audio_capture_rt_48KHz;
10068 break;
10069 case 32000:
10070 in->config = pcm_config_audio_capture_rt_32KHz;
10071 break;
10072 case 24000:
10073 in->config = pcm_config_audio_capture_rt_24KHz;
10074 break;
10075 case 16000:
10076 in->config = pcm_config_audio_capture_rt_16KHz;
10077 break;
10078 case 8000:
10079 in->config = pcm_config_audio_capture_rt_8KHz;
10080 break;
10081 default:
10082 in->config = pcm_config_audio_capture_rt_48KHz;
10083 }
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +053010084#else
10085 in->config = pcm_config_audio_capture_rt_48KHz;
10086#endif
Aalique Grahame22e49102018-12-18 14:23:57 -080010087 in->af_period_multiplier = af_period_multiplier;
10088 }
Kogara Naveen Kumarc5758232022-11-07 20:25:40 +053010089
10090 /* assign concurrent capture usecase if record has to caried out from
10091 * actual hardware input source */
10092 if (audio_extn_is_concurrent_capture_enabled() &&
10093 !audio_is_virtual_input_source(in->source)) {
10094 /* Acquire lock to avoid two concurrent use cases initialized to
10095 same pcm record use case */
10096 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY) {
10097 pthread_mutex_lock(&adev->lock);
10098 if (!(adev->pcm_low_latency_record_uc_state)) {
10099 ALOGD("%s: using USECASE_AUDIO_RECORD_LOW_LATENCY",__func__);
10100 adev->pcm_low_latency_record_uc_state = 1;
10101 pthread_mutex_unlock(&adev->lock);
10102 } else if (audio_extn_is_concurrent_low_latency_pcm_record_enabled()) {
10103 in->usecase = get_low_latency_record_usecase(adev);
10104 pthread_mutex_unlock(&adev->lock);
10105 } else {
10106 pthread_mutex_unlock(&adev->lock);
10107 /* Assign compress record use case for second record */
10108 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
10109 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
10110 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
10111 if (audio_extn_cin_applicable_stream(in)) {
10112 in->sample_rate = config->sample_rate;
10113 ret = audio_extn_cin_configure_input_stream(in, config);
10114 if (ret)
10115 goto err_open;
10116 }
10117 }
10118 }
10119 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -070010120 }
10121
Susan Wangb803cb52021-10-14 12:03:36 -040010122 /* Additional sample rates added below must also be present
10123 in audio_policy_configuration.xml for mmap_no_irq_in */
10124 bool valid_mmap_record_rate = (config->sample_rate == 8000 ||
10125 config->sample_rate == 16000 ||
Susan Wang89da9042021-10-14 12:03:36 -040010126 config->sample_rate == 24000 ||
Susan Wangb803cb52021-10-14 12:03:36 -040010127 config->sample_rate == 32000 ||
10128 config->sample_rate == 48000);
10129 if (valid_mmap_record_rate &&
10130 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -070010131 in->realtime = 0;
10132 in->usecase = USECASE_AUDIO_RECORD_MMAP;
10133 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -070010134 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -070010135 in->stream.start = in_start;
10136 in->stream.stop = in_stop;
10137 in->stream.create_mmap_buffer = in_create_mmap_buffer;
10138 in->stream.get_mmap_position = in_get_mmap_position;
Ramjee Singhbcb3b6c2021-11-17 13:19:16 +053010139 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -070010140 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
Haynes Mathew George46740472017-10-27 18:40:12 -070010141 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -070010142 in->usecase = USECASE_AUDIO_RECORD_HIFI;
10143 in->config = pcm_config_audio_capture;
10144 frame_size = audio_stream_in_frame_size(&in->stream);
10145 buffer_size = get_input_buffer_size(config->sample_rate,
10146 config->format,
10147 channel_count,
10148 false /*is_low_latency*/);
10149 in->config.period_size = buffer_size / frame_size;
10150 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -070010151 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -070010152 switch (config->format) {
10153 case AUDIO_FORMAT_PCM_32_BIT:
10154 in->bit_width = 32;
10155 break;
10156 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
10157 case AUDIO_FORMAT_PCM_8_24_BIT:
10158 in->bit_width = 24;
10159 break;
10160 default:
10161 in->bit_width = 16;
10162 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010163 } else if (is_single_device_type_equal(&in->device_list,
10164 AUDIO_DEVICE_IN_TELEPHONY_RX) ||
10165 is_single_device_type_equal(&in->device_list,
10166 AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070010167 if (config->sample_rate == 0)
10168 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
10169 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
10170 config->sample_rate != 8000) {
10171 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
10172 ret = -EINVAL;
10173 goto err_open;
10174 }
10175 if (config->format == AUDIO_FORMAT_DEFAULT)
10176 config->format = AUDIO_FORMAT_PCM_16_BIT;
10177 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
10178 config->format = AUDIO_FORMAT_PCM_16_BIT;
10179 ret = -EINVAL;
10180 goto err_open;
10181 }
10182
10183 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
Zhou Song62ea0282020-03-22 19:53:01 +080010184 if (adev->ha_proxy_enable &&
10185 is_single_device_type_equal(&in->device_list,
10186 AUDIO_DEVICE_IN_TELEPHONY_RX))
10187 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY2;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070010188 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070010189 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -080010190 in->af_period_multiplier = 1;
10191 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
Shalini Manjunathaac412b32020-01-03 15:00:14 +053010192 (!voice_extn_is_compress_voip_supported()) &&
Aalique Grahame22e49102018-12-18 14:23:57 -080010193 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
10194 (config->sample_rate == 8000 ||
10195 config->sample_rate == 16000 ||
10196 config->sample_rate == 32000 ||
10197 config->sample_rate == 48000) &&
10198 channel_count == 1) {
10199 in->usecase = USECASE_AUDIO_RECORD_VOIP;
10200 in->config = pcm_config_audio_capture;
10201 frame_size = audio_stream_in_frame_size(&in->stream);
10202 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
10203 config->sample_rate,
10204 config->format,
10205 channel_count, false /*is_low_latency*/);
10206 in->config.period_size = buffer_size / frame_size;
10207 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
10208 in->config.rate = config->sample_rate;
10209 in->af_period_multiplier = 1;
Mingshu Pangc2d65042021-01-14 16:19:10 +080010210 } else if (in->realtime) {
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +053010211#ifdef PLATFORM_AUTO
Kogara Naveen Kumara688a812022-04-27 16:45:59 +053010212 switch(config->sample_rate)
10213 {
10214 case 48000:
10215 in->config = pcm_config_audio_capture_rt_48KHz;
10216 break;
10217 case 32000:
10218 in->config = pcm_config_audio_capture_rt_32KHz;
10219 break;
10220 case 24000:
10221 in->config = pcm_config_audio_capture_rt_24KHz;
10222 break;
10223 case 16000:
10224 in->config = pcm_config_audio_capture_rt_16KHz;
10225 break;
10226 case 8000:
10227 in->config = pcm_config_audio_capture_rt_8KHz;
10228 break;
10229 default:
10230 in->config = pcm_config_audio_capture_rt_48KHz;
10231 }
Mingshu Pangc2d65042021-01-14 16:19:10 +080010232 in->config.format = pcm_format_from_audio_format(config->format);
10233 in->af_period_multiplier = af_period_multiplier;
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +053010234#else
10235 in->config = pcm_config_audio_capture_rt_48KHz;
10236#endif
10237} else {
Revathi Uddarajud2634032017-12-07 14:42:34 +053010238 int ret_val;
10239 pthread_mutex_lock(&adev->lock);
10240 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
10241 in, config, &channel_mask_updated);
10242 pthread_mutex_unlock(&adev->lock);
10243
10244 if (!ret_val) {
10245 if (channel_mask_updated == true) {
10246 ALOGD("%s: return error to retry with updated channel mask (%#x)",
10247 __func__, config->channel_mask);
10248 ret = -EINVAL;
10249 goto err_open;
10250 }
10251 ALOGD("%s: created multi-channel session succesfully",__func__);
10252 } else if (audio_extn_compr_cap_enabled() &&
10253 audio_extn_compr_cap_format_supported(config->format) &&
10254 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
10255 audio_extn_compr_cap_init(in);
10256 } else if (audio_extn_cin_applicable_stream(in)) {
Deeraj Soman14230922019-01-30 16:39:30 +053010257 ret = audio_extn_cin_configure_input_stream(in, config);
Revathi Uddarajud2634032017-12-07 14:42:34 +053010258 if (ret)
10259 goto err_open;
10260 } else {
10261 in->config = pcm_config_audio_capture;
10262 in->config.rate = config->sample_rate;
10263 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +053010264 in->format = config->format;
10265 frame_size = audio_stream_in_frame_size(&in->stream);
10266 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -070010267 config->format,
10268 channel_count,
10269 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +020010270 /* prevent division-by-zero */
10271 if (frame_size == 0) {
10272 ALOGE("%s: Error frame_size==0", __func__);
10273 ret = -EINVAL;
10274 goto err_open;
10275 }
10276
Revathi Uddarajud2634032017-12-07 14:42:34 +053010277 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -080010278 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -080010279
Revathi Uddarajud2634032017-12-07 14:42:34 +053010280 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
10281 /* optionally use VOIP usecase depending on config(s) */
10282 ret = adev_update_voice_comm_input_stream(in, config);
10283 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -080010284
Revathi Uddarajud2634032017-12-07 14:42:34 +053010285 if (ret) {
10286 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
10287 goto err_open;
10288 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -080010289 }
Jaideep Sharmad305a4a2020-02-27 14:29:04 +053010290
10291 /* assign concurrent capture usecase if record has to caried out from
10292 * actual hardware input source */
10293 if (audio_extn_is_concurrent_capture_enabled() &&
10294 !audio_is_virtual_input_source(in->source)) {
Samyak Jainc37062f2019-04-25 18:41:06 +053010295 /* Acquire lock to avoid two concurrent use cases initialized to
10296 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +080010297
Samyak Jainc37062f2019-04-25 18:41:06 +053010298 if (in->usecase == USECASE_AUDIO_RECORD) {
10299 pthread_mutex_lock(&adev->lock);
10300 if (!(adev->pcm_record_uc_state)) {
10301 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
10302 adev->pcm_record_uc_state = 1;
10303 pthread_mutex_unlock(&adev->lock);
Krishna Kishor Jha0f4d8482022-02-18 10:56:05 +053010304 } else if (audio_extn_is_concurrent_pcm_record_enabled()) {
10305 in->usecase = get_record_usecase(adev);
10306 pthread_mutex_unlock(&adev->lock);
Samyak Jainc37062f2019-04-25 18:41:06 +053010307 } else {
10308 pthread_mutex_unlock(&adev->lock);
10309 /* Assign compress record use case for second record */
10310 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
10311 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
10312 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
10313 if (audio_extn_cin_applicable_stream(in)) {
10314 in->sample_rate = config->sample_rate;
Deeraj Soman14230922019-01-30 16:39:30 +053010315 ret = audio_extn_cin_configure_input_stream(in, config);
Samyak Jainc37062f2019-04-25 18:41:06 +053010316 if (ret)
10317 goto err_open;
10318 }
10319 }
10320 }
kunleiz28c73e72019-03-27 17:24:04 +080010321 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -070010322 }
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +053010323
Ramjee Singh82fd0c12019-08-21 16:31:33 +053010324 if (audio_extn_ssr_get_stream() != in)
10325 in->config.channels = channel_count;
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -070010326
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -070010327 in->sample_rate = in->config.rate;
10328
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010329 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
10330 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010331 &in->device_list, flags, in->format,
Haynes Mathew George4ffef292017-11-21 15:08:02 -080010332 in->sample_rate, in->bit_width,
10333 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +053010334 register_format(in->format, in->supported_formats);
10335 register_channel_mask(in->channel_mask, in->supported_channel_masks);
10336 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010337
Dechen Chai22768452021-07-30 09:29:16 +053010338#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -080010339 in->error_log = error_log_create(
10340 ERROR_LOG_ENTRIES,
10341 1000000000 /* aggregate consecutive identical errors within one second */);
Dechen Chai22768452021-07-30 09:29:16 +053010342#endif
Aalique Grahame22e49102018-12-18 14:23:57 -080010343
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010344 /* This stream could be for sound trigger lab,
10345 get sound trigger pcm if present */
10346 audio_extn_sound_trigger_check_and_get_session(in);
10347
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010348 lock_input_stream(in);
10349 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
10350 pthread_mutex_lock(&adev->lock);
10351 in->card_status = adev->card_status;
10352 pthread_mutex_unlock(&adev->lock);
10353 pthread_mutex_unlock(&in->lock);
10354
Aalique Grahame22e49102018-12-18 14:23:57 -080010355 stream_app_type_cfg_init(&in->app_type_cfg);
10356
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010357 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -080010358
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010359 ret = io_streams_map_insert(adev, &in->stream.common,
10360 handle, AUDIO_PATCH_HANDLE_NONE);
10361 if (ret != 0)
10362 goto err_open;
10363
Susan Wang6dd13092021-01-25 10:27:11 -050010364 in->in_ctxt.input = in;
Derek Chenf939fb72018-11-13 13:34:41 -080010365
10366 pthread_mutex_lock(&adev->lock);
Susan Wang6dd13092021-01-25 10:27:11 -050010367 list_add_tail(&adev->active_inputs_list, &in->in_ctxt.list);
Derek Chenf939fb72018-11-13 13:34:41 -080010368 pthread_mutex_unlock(&adev->lock);
10369
Eric Laurent994a6932013-07-17 11:51:42 -070010370 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -080010371 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010372
10373err_open:
Krishna Kishor Jha0f4d8482022-02-18 10:56:05 +053010374 if (audio_extn_is_concurrent_pcm_record_enabled() && is_pcm_record_usecase(in->usecase)) {
10375 free_record_usecase(adev, in->usecase);
10376 } else if (in->usecase == USECASE_AUDIO_RECORD) {
Samyak Jainc37062f2019-04-25 18:41:06 +053010377 pthread_mutex_lock(&adev->lock);
10378 adev->pcm_record_uc_state = 0;
10379 pthread_mutex_unlock(&adev->lock);
10380 }
Kogara Naveen Kumarc5758232022-11-07 20:25:40 +053010381 if (audio_extn_is_concurrent_low_latency_pcm_record_enabled() && is_pcm_low_latency_record_usecase(in->usecase)) {
10382 free_low_latency_record_usecase(adev, in->usecase);
10383 } else if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY) {
10384 pthread_mutex_lock(&adev->lock);
10385 adev->pcm_low_latency_record_uc_state = 0;
10386 pthread_mutex_unlock(&adev->lock);
10387 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010388 free(in);
10389 *stream_in = NULL;
10390 return ret;
10391}
10392
10393static void adev_close_input_stream(struct audio_hw_device *dev,
10394 struct audio_stream_in *stream)
10395{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080010396 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -070010397 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -070010398 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +053010399
Sidipotu Ashokf43018c2014-05-02 16:21:50 +053010400 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080010401
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010402 if (in == NULL) {
10403 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
10404 return;
10405 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010406 io_streams_map_remove(adev, in->capture_handle);
10407
Susan Wang6dd13092021-01-25 10:27:11 -050010408 // remove out_ctxt early to prevent the stream
10409 // being opened in a race condition
10410 pthread_mutex_lock(&adev->lock);
10411 list_remove(&in->in_ctxt.list);
10412 pthread_mutex_unlock(&adev->lock);
10413
kunleiz70e57612018-12-28 17:50:23 +080010414 /* must deregister from sndmonitor first to prevent races
10415 * between the callback and close_stream
10416 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010417 audio_extn_snd_mon_unregister_listener(stream);
10418
kunleiz70e57612018-12-28 17:50:23 +080010419 /* Disable echo reference if there are no active input, hfp call
10420 * and sound trigger while closing input stream
10421 */
Eric Laurent637e2d42018-11-15 12:24:31 -080010422 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +080010423 !audio_extn_hfp_is_active(adev) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010424 !audio_extn_sound_trigger_check_ec_ref_enable()) {
10425 struct listnode out_devices;
10426 list_init(&out_devices);
10427 platform_set_echo_reference(adev, false, &out_devices);
Zhenlin Lian4f947842022-05-14 15:50:52 +053010428 clear_devices(&out_devices);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010429 } else
kunleiz70e57612018-12-28 17:50:23 +080010430 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +053010431
Dechen Chai22768452021-07-30 09:29:16 +053010432#ifndef LINUX_ENABLED
Weiyin Jiang2995f662019-04-17 14:25:12 +080010433 error_log_destroy(in->error_log);
10434 in->error_log = NULL;
Dechen Chai22768452021-07-30 09:29:16 +053010435#endif
Pallavid7c7a272018-01-16 11:22:55 +053010436
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080010437 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +053010438 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080010439 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +053010440 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080010441 if (ret != 0)
10442 ALOGE("%s: Compress voip input cannot be closed, error:%d",
10443 __func__, ret);
10444 } else
10445 in_standby(&stream->common);
10446
Weiyin Jiang280ea742020-09-08 20:28:22 +080010447 pthread_mutex_destroy(&in->lock);
10448 pthread_mutex_destroy(&in->pre_lock);
10449
Revathi Uddarajud2634032017-12-07 14:42:34 +053010450 pthread_mutex_lock(&adev->lock);
Krishna Kishor Jha0f4d8482022-02-18 10:56:05 +053010451 if (audio_extn_is_concurrent_pcm_record_enabled() && is_pcm_record_usecase(in->usecase)) {
10452 free_record_usecase(adev, in->usecase);
10453 } else if (in->usecase == USECASE_AUDIO_RECORD) {
Samyak Jain15fda662018-12-18 16:40:52 +053010454 adev->pcm_record_uc_state = 0;
10455 }
10456
Kogara Naveen Kumarc5758232022-11-07 20:25:40 +053010457 if (audio_extn_is_concurrent_low_latency_pcm_record_enabled() && is_pcm_low_latency_record_usecase(in->usecase)) {
10458 free_low_latency_record_usecase(adev, in->usecase);
10459 } else if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY) {
10460 adev->pcm_low_latency_record_uc_state = 0;
10461 }
10462
Kunlei Zhang5d5d8d92020-02-26 15:00:59 +080010463 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
10464 adev->enable_voicerx = false;
10465 }
10466
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -070010467 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -070010468 audio_extn_ssr_deinit();
10469 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010470
Garmond Leunge2433c32017-09-28 21:51:22 -070010471 if (audio_extn_ffv_get_stream() == in) {
10472 audio_extn_ffv_stream_deinit();
10473 }
10474
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010475 if (audio_extn_compr_cap_enabled() &&
Subhadra Jagadeesan63a1e832023-01-13 11:26:38 +053010476 audio_extn_compr_cap_format_supported(pcm_format_to_audio_format((in->config).format)))
Mingming Yine62d7842013-10-25 16:26:03 -070010477 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +053010478
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +053010479 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +053010480 audio_extn_cin_free_input_stream_resources(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010481
Mingming Yinfd7607b2016-01-22 12:48:44 -080010482 if (in->is_st_session) {
10483 ALOGV("%s: sound trigger pcm stop lab", __func__);
10484 audio_extn_sound_trigger_stop_lab(in);
10485 }
Zhenlin Lian4f947842022-05-14 15:50:52 +053010486 clear_devices(&in->device_list);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010487 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +053010488 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010489 return;
10490}
10491
Aalique Grahame22e49102018-12-18 14:23:57 -080010492/* verifies input and output devices and their capabilities.
10493 *
10494 * This verification is required when enabling extended bit-depth or
10495 * sampling rates, as not all qcom products support it.
10496 *
10497 * Suitable for calling only on initialization such as adev_open().
10498 * It fills the audio_device use_case_table[] array.
10499 *
10500 * Has a side-effect that it needs to configure audio routing / devices
10501 * in order to power up the devices and read the device parameters.
10502 * It does not acquire any hw device lock. Should restore the devices
10503 * back to "normal state" upon completion.
10504 */
10505static int adev_verify_devices(struct audio_device *adev)
10506{
10507 /* enumeration is a bit difficult because one really wants to pull
10508 * the use_case, device id, etc from the hidden pcm_device_table[].
10509 * In this case there are the following use cases and device ids.
10510 *
10511 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
10512 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
10513 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
10514 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
10515 * [USECASE_AUDIO_RECORD] = {0, 0},
10516 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
10517 * [USECASE_VOICE_CALL] = {2, 2},
10518 *
10519 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
10520 * USECASE_VOICE_CALL omitted, but possible for either input or output.
10521 */
10522
10523 /* should be the usecases enabled in adev_open_input_stream() */
10524 static const int test_in_usecases[] = {
10525 USECASE_AUDIO_RECORD,
10526 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
10527 };
10528 /* should be the usecases enabled in adev_open_output_stream()*/
10529 static const int test_out_usecases[] = {
10530 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
10531 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
10532 };
10533 static const usecase_type_t usecase_type_by_dir[] = {
10534 PCM_PLAYBACK,
10535 PCM_CAPTURE,
10536 };
10537 static const unsigned flags_by_dir[] = {
10538 PCM_OUT,
10539 PCM_IN,
10540 };
10541
10542 size_t i;
10543 unsigned dir;
10544 const unsigned card_id = adev->snd_card;
10545
10546 for (dir = 0; dir < 2; ++dir) {
10547 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
10548 const unsigned flags_dir = flags_by_dir[dir];
10549 const size_t testsize =
10550 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
10551 const int *testcases =
10552 dir ? test_in_usecases : test_out_usecases;
10553 const audio_devices_t audio_device =
10554 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
10555
10556 for (i = 0; i < testsize; ++i) {
10557 const audio_usecase_t audio_usecase = testcases[i];
10558 int device_id;
10559 struct pcm_params **pparams;
10560 struct stream_out out;
10561 struct stream_in in;
10562 struct audio_usecase uc_info;
10563 int retval;
10564
10565 pparams = &adev->use_case_table[audio_usecase];
10566 pcm_params_free(*pparams); /* can accept null input */
10567 *pparams = NULL;
10568
10569 /* find the device ID for the use case (signed, for error) */
10570 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
10571 if (device_id < 0)
10572 continue;
10573
10574 /* prepare structures for device probing */
10575 memset(&uc_info, 0, sizeof(uc_info));
10576 uc_info.id = audio_usecase;
10577 uc_info.type = usecase_type;
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010578 list_init(&uc_info.device_list);
Aalique Grahame22e49102018-12-18 14:23:57 -080010579 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -080010580 memset(&in, 0, sizeof(in));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010581 list_init(&in.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010582 update_device_list(&in.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -080010583 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
10584 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -080010585 }
10586 memset(&out, 0, sizeof(out));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010587 list_init(&out.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010588 update_device_list(&out.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -080010589 uc_info.stream.out = &out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010590 update_device_list(&uc_info.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -080010591 uc_info.in_snd_device = SND_DEVICE_NONE;
10592 uc_info.out_snd_device = SND_DEVICE_NONE;
10593 list_add_tail(&adev->usecase_list, &uc_info.list);
10594
10595 /* select device - similar to start_(in/out)put_stream() */
10596 retval = select_devices(adev, audio_usecase);
10597 if (retval >= 0) {
10598 *pparams = pcm_params_get(card_id, device_id, flags_dir);
10599#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -070010600 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -080010601 if (*pparams) {
10602 ALOGV("%s: (%s) card %d device %d", __func__,
10603 dir ? "input" : "output", card_id, device_id);
10604 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
10605 } else {
10606 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
10607 }
10608#endif
10609 }
10610
10611 /* deselect device - similar to stop_(in/out)put_stream() */
10612 /* 1. Get and set stream specific mixer controls */
10613 retval = disable_audio_route(adev, &uc_info);
10614 /* 2. Disable the rx device */
10615 retval = disable_snd_device(adev,
10616 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
10617 list_remove(&uc_info.list);
10618 }
10619 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010620 return 0;
10621}
10622
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010623int update_patch(unsigned int num_sources,
10624 const struct audio_port_config *sources,
10625 unsigned int num_sinks,
10626 const struct audio_port_config *sinks,
10627 audio_patch_handle_t handle,
10628 struct audio_patch_info *p_info,
10629 patch_type_t patch_type, bool new_patch)
10630{
Aniket Kumar Latad13758f2020-08-06 15:11:36 -070010631 ALOGV("%s: enter", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010632
10633 if (p_info == NULL) {
10634 ALOGE("%s: Invalid patch pointer", __func__);
10635 return -EINVAL;
10636 }
10637
10638 if (new_patch) {
10639 p_info->patch = (struct audio_patch *) calloc(1, sizeof(struct audio_patch));
10640 if (p_info->patch == NULL) {
10641 ALOGE("%s: Could not allocate patch", __func__);
10642 return -ENOMEM;
10643 }
10644 }
10645
10646 p_info->patch->id = handle;
10647 p_info->patch->num_sources = num_sources;
10648 p_info->patch->num_sinks = num_sinks;
10649
10650 for (int i = 0; i < num_sources; i++)
10651 p_info->patch->sources[i] = sources[i];
10652 for (int i = 0; i < num_sinks; i++)
10653 p_info->patch->sinks[i] = sinks[i];
10654
10655 p_info->patch_type = patch_type;
10656 return 0;
10657}
10658
10659audio_patch_handle_t generate_patch_handle()
10660{
10661 static audio_patch_handle_t patch_handle = AUDIO_PATCH_HANDLE_NONE;
10662 if (++patch_handle < 0)
10663 patch_handle = AUDIO_PATCH_HANDLE_NONE + 1;
10664 return patch_handle;
10665}
10666
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010667int adev_create_audio_patch(struct audio_hw_device *dev,
10668 unsigned int num_sources,
10669 const struct audio_port_config *sources,
10670 unsigned int num_sinks,
10671 const struct audio_port_config *sinks,
10672 audio_patch_handle_t *handle)
10673{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010674 int ret = 0;
10675 struct audio_device *adev = (struct audio_device *)dev;
10676 struct audio_patch_info *p_info = NULL;
10677 patch_type_t patch_type = PATCH_NONE;
10678 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10679 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
10680 struct audio_stream_info *s_info = NULL;
10681 struct audio_stream *stream = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010682 struct listnode devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010683 audio_devices_t device_type = AUDIO_DEVICE_NONE;
10684 bool new_patch = false;
10685 char addr[AUDIO_DEVICE_MAX_ADDRESS_LEN];
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010686
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010687 ALOGD("%s: enter: num sources %d, num_sinks %d, handle %d", __func__,
10688 num_sources, num_sinks, *handle);
10689
10690 if (num_sources == 0 || num_sources > AUDIO_PATCH_PORTS_MAX ||
10691 num_sinks == 0 || num_sinks > AUDIO_PATCH_PORTS_MAX) {
10692 ALOGE("%s: Invalid patch arguments", __func__);
10693 ret = -EINVAL;
10694 goto done;
10695 }
10696
10697 if (num_sources > 1) {
10698 ALOGE("%s: Multiple sources are not supported", __func__);
10699 ret = -EINVAL;
10700 goto done;
10701 }
10702
10703 if (sources == NULL || sinks == NULL) {
10704 ALOGE("%s: Invalid sources or sinks port config", __func__);
10705 ret = -EINVAL;
10706 goto done;
10707 }
10708
10709 ALOGV("%s: source role %d, source type %d", __func__,
10710 sources[0].type, sources[0].role);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010711 list_init(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010712
10713 // Populate source/sink information and fetch stream info
10714 switch (sources[0].type) {
10715 case AUDIO_PORT_TYPE_DEVICE: // Patch for audio capture or loopback
10716 device_type = sources[0].ext.device.type;
10717 strlcpy(&addr[0], &sources[0].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010718 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010719 if (sinks[0].type == AUDIO_PORT_TYPE_MIX) {
10720 patch_type = PATCH_CAPTURE;
10721 io_handle = sinks[0].ext.mix.handle;
10722 input_source = sinks[0].ext.mix.usecase.source;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010723 ALOGD("%s: Capture patch from device %x to mix %d",
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010724 __func__, device_type, io_handle);
10725 } else {
10726 // Device to device patch is not implemented.
10727 // This space will need changes if audio HAL
10728 // handles device to device patches in the future.
10729 patch_type = PATCH_DEVICE_LOOPBACK;
10730 }
10731 break;
10732 case AUDIO_PORT_TYPE_MIX: // Patch for audio playback
10733 io_handle = sources[0].ext.mix.handle;
10734 for (int i = 0; i < num_sinks; i++) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010735 device_type = sinks[i].ext.device.type;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010736 strlcpy(&addr[0], &sinks[i].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010737 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010738 }
10739 patch_type = PATCH_PLAYBACK;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010740 ALOGD("%s: Playback patch from mix handle %d to device %x",
10741 __func__, io_handle, get_device_types(&devices));
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010742 break;
10743 case AUDIO_PORT_TYPE_SESSION:
10744 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010745 ALOGE("%s: Unsupported source type %d", __func__, sources[0].type);
10746 ret = -EINVAL;
10747 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010748 }
10749
10750 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010751
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010752 // Generate patch info and update patch
10753 if (*handle == AUDIO_PATCH_HANDLE_NONE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010754 *handle = generate_patch_handle();
10755 p_info = (struct audio_patch_info *)
10756 calloc(1, sizeof(struct audio_patch_info));
10757 if (p_info == NULL) {
10758 ALOGE("%s: Failed to allocate memory", __func__);
10759 pthread_mutex_unlock(&adev->lock);
10760 ret = -ENOMEM;
10761 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010762 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010763 new_patch = true;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010764 } else {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010765 p_info = fetch_patch_info_l(adev, *handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010766 if (p_info == NULL) {
10767 ALOGE("%s: Unable to fetch patch for received patch handle %d",
10768 __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010769 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010770 ret = -EINVAL;
10771 goto done;
10772 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010773 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010774 update_patch(num_sources, sources, num_sinks, sinks,
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010775 *handle, p_info, patch_type, new_patch);
10776
10777 // Fetch stream info of associated mix for playback or capture patches
10778 if (p_info->patch_type == PATCH_PLAYBACK ||
10779 p_info->patch_type == PATCH_CAPTURE) {
10780 s_info = hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10781 if (s_info == NULL) {
10782 ALOGE("%s: Failed to obtain stream info", __func__);
10783 if (new_patch)
10784 free(p_info);
10785 pthread_mutex_unlock(&adev->lock);
10786 ret = -EINVAL;
10787 goto done;
10788 }
10789 ALOGV("%s: Fetched stream info with io_handle %d", __func__, io_handle);
10790 s_info->patch_handle = *handle;
10791 stream = s_info->stream;
10792 }
10793 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010794
10795 // Update routing for stream
10796 if (stream != NULL) {
Revathi Uddaraju4255a632021-12-02 05:11:13 -080010797 if (p_info->patch_type == PATCH_PLAYBACK) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010798 ret = route_output_stream((struct stream_out *) stream, &devices);
Revathi Uddaraju4255a632021-12-02 05:11:13 -080010799 } else if (p_info->patch_type == PATCH_CAPTURE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010800 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Revathi Uddaraju4255a632021-12-02 05:11:13 -080010801 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010802 if (ret < 0) {
10803 pthread_mutex_lock(&adev->lock);
10804 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10805 if (new_patch)
10806 free(p_info);
10807 pthread_mutex_unlock(&adev->lock);
10808 ALOGE("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10809 goto done;
10810 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010811 }
10812
10813 // Add new patch to patch map
10814 if (!ret && new_patch) {
10815 pthread_mutex_lock(&adev->lock);
10816 hashmapPut(adev->patch_map, (void *) (intptr_t) *handle, (void *) p_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010817 ALOGD("%s: Added a new patch with handle %d", __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010818 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010819 }
10820
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010821done:
Zhenlin Lian4f947842022-05-14 15:50:52 +053010822 clear_devices(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010823 audio_extn_hw_loopback_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010824 num_sources,
10825 sources,
10826 num_sinks,
10827 sinks,
10828 handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010829 audio_extn_auto_hal_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010830 num_sources,
10831 sources,
10832 num_sinks,
10833 sinks,
10834 handle);
10835 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010836}
10837
10838int adev_release_audio_patch(struct audio_hw_device *dev,
10839 audio_patch_handle_t handle)
10840{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010841 struct audio_device *adev = (struct audio_device *) dev;
10842 int ret = 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010843 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010844 struct audio_stream *stream = NULL;
Derek Chenf939fb72018-11-13 13:34:41 -080010845
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010846 if (handle == AUDIO_PATCH_HANDLE_NONE) {
10847 ALOGE("%s: Invalid patch handle %d", __func__, handle);
10848 ret = -EINVAL;
10849 goto done;
10850 }
10851
10852 ALOGD("%s: Remove patch with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010853 pthread_mutex_lock(&adev->lock);
10854 struct audio_patch_info *p_info = fetch_patch_info_l(adev, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010855 if (p_info == NULL) {
10856 ALOGE("%s: Patch info not found with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010857 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010858 ret = -EINVAL;
10859 goto done;
10860 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010861 struct audio_patch *patch = p_info->patch;
10862 if (patch == NULL) {
10863 ALOGE("%s: Patch not found for handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010864 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010865 ret = -EINVAL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010866 goto done;
10867 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010868 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10869 switch (patch->sources[0].type) {
10870 case AUDIO_PORT_TYPE_MIX:
10871 io_handle = patch->sources[0].ext.mix.handle;
10872 break;
10873 case AUDIO_PORT_TYPE_DEVICE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010874 if (p_info->patch_type == PATCH_CAPTURE)
10875 io_handle = patch->sinks[0].ext.mix.handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010876 break;
10877 case AUDIO_PORT_TYPE_SESSION:
10878 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010879 pthread_mutex_unlock(&adev->lock);
10880 ret = -EINVAL;
10881 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010882 }
10883
10884 // Remove patch and reset patch handle in stream info
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010885 patch_type_t patch_type = p_info->patch_type;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010886 patch_map_remove_l(adev, handle);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010887 if (patch_type == PATCH_PLAYBACK ||
10888 patch_type == PATCH_CAPTURE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010889 struct audio_stream_info *s_info =
10890 hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10891 if (s_info == NULL) {
10892 ALOGE("%s: stream for io_handle %d is not available", __func__, io_handle);
10893 pthread_mutex_unlock(&adev->lock);
10894 goto done;
10895 }
10896 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10897 stream = s_info->stream;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010898 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010899 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010900
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010901 if (stream != NULL) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010902 struct listnode devices;
10903 list_init(&devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010904 if (patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010905 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010906 else if (patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010907 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Zhenlin Lian4f947842022-05-14 15:50:52 +053010908 clear_devices(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010909 }
10910
10911 if (ret < 0)
10912 ALOGW("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10913
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010914done:
10915 audio_extn_hw_loopback_release_audio_patch(dev, handle);
10916 audio_extn_auto_hal_release_audio_patch(dev, handle);
10917
10918 ALOGV("%s: Successfully released patch %d", __func__, handle);
Derek Chenf939fb72018-11-13 13:34:41 -080010919 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010920}
10921
10922int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
10923{
Derek Chenf13dd492018-11-13 14:53:51 -080010924 int ret = 0;
10925
10926 ret = audio_extn_hw_loopback_get_audio_port(dev, config);
10927 ret |= audio_extn_auto_hal_get_audio_port(dev, config);
10928 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010929}
10930
10931int adev_set_audio_port_config(struct audio_hw_device *dev,
10932 const struct audio_port_config *config)
10933{
Derek Chenf13dd492018-11-13 14:53:51 -080010934 int ret = 0;
10935
10936 ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
10937 ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
10938 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010939}
10940
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -070010941static int adev_dump(const audio_hw_device_t *device __unused,
10942 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010943{
10944 return 0;
10945}
10946
10947static int adev_close(hw_device_t *device)
10948{
Aalique Grahame22e49102018-12-18 14:23:57 -080010949 size_t i;
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010950 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -070010951
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010952 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -070010953 return 0;
10954
10955 pthread_mutex_lock(&adev_init_lock);
10956
10957 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +053010958 if (audio_extn_spkr_prot_is_enabled())
10959 audio_extn_spkr_prot_deinit();
Jaideep Sharmaa2b49672019-09-10 20:37:03 +053010960 audio_extn_battery_properties_listener_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010961 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010962 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -080010963 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010964 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -080010965 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010966 audio_extn_utils_release_streams_cfg_lists(
10967 &adev->streams_output_cfg_list,
10968 &adev->streams_input_cfg_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010969 if (audio_extn_qap_is_enabled())
10970 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010971 if (audio_extn_qaf_is_enabled())
10972 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -070010973 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +080010974 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -070010975 free(adev->snd_dev_ref_cnt);
10976 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010977 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
10978 pcm_params_free(adev->use_case_table[i]);
10979 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010980 if (adev->adm_deinit)
10981 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010982 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010983 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010984 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010985 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010986 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010987 if (adev->device_cfg_params) {
10988 free(adev->device_cfg_params);
10989 adev->device_cfg_params = NULL;
10990 }
Derek Chend2530072014-11-24 12:39:14 -080010991 if(adev->ext_hw_plugin)
10992 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -080010993 audio_extn_auto_hal_deinit();
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010994 free_map(adev->patch_map);
10995 free_map(adev->io_streams_map);
Kiran Kandi910e1862013-10-29 13:29:42 -070010996 free(device);
10997 adev = NULL;
10998 }
10999 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +053011000 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011001 return 0;
11002}
11003
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070011004/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
11005 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
11006 * just that it _might_ work.
11007 */
11008static int period_size_is_plausible_for_low_latency(int period_size)
11009{
11010 switch (period_size) {
11011 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -070011012 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070011013 case 240:
11014 case 320:
11015 case 480:
11016 return 1;
11017 default:
11018 return 0;
11019 }
11020}
11021
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053011022static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
11023{
11024 bool is_snd_card_status = false;
11025 bool is_ext_device_status = false;
11026 char value[32];
11027 int card = -1;
11028 card_status_t status;
11029
11030 if (cookie != adev || !parms)
11031 return;
11032
11033 if (!parse_snd_card_status(parms, &card, &status)) {
11034 is_snd_card_status = true;
11035 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
11036 is_ext_device_status = true;
11037 } else {
11038 // not a valid event
11039 return;
11040 }
11041
11042 pthread_mutex_lock(&adev->lock);
11043 if (card == adev->snd_card || is_ext_device_status) {
11044 if (is_snd_card_status && adev->card_status != status) {
Jaideep Sharmacb402512020-09-24 17:51:07 +053011045 ALOGD("%s card_status %d", __func__, status);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053011046 adev->card_status = status;
11047 platform_snd_card_update(adev->platform, status);
11048 audio_extn_fm_set_parameters(adev, parms);
Derek Chend6f371d2019-03-01 13:45:58 -080011049 audio_extn_auto_hal_set_parameters(adev, parms);
Zhou Song4f43e352019-07-02 00:32:23 +080011050 if (status == CARD_STATUS_OFFLINE)
11051 audio_extn_sco_reset_configuration();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053011052 } else if (is_ext_device_status) {
11053 platform_set_parameters(adev->platform, parms);
11054 }
11055 }
11056 pthread_mutex_unlock(&adev->lock);
11057 return;
11058}
11059
Weiyin Jiang280ea742020-09-08 20:28:22 +080011060/* adev lock held */
11061int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011062{
11063 struct audio_usecase *uc_info;
Zhou Song407e5aa2020-12-27 19:13:04 +080011064 struct audio_usecase *usecase;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080011065 struct listnode devices;
Zhou Song407e5aa2020-12-27 19:13:04 +080011066 struct listnode *node;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011067
11068 uc_info = get_usecase_from_list(adev, out->usecase);
11069 if (uc_info == NULL) {
11070 ALOGE("%s: Could not find the usecase (%d) in the list",
11071 __func__, out->usecase);
11072 return -EINVAL;
11073 }
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080011074 list_init(&devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011075
Zhou Songbaddf9f2020-11-20 13:57:39 +080011076 ALOGD("%s: enter: usecase(%d: %s), a2dp muted %d", __func__,
11077 out->usecase, use_case_table[out->usecase], out->a2dp_muted);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011078
11079 if (restore) {
Weiyin Jiang280ea742020-09-08 20:28:22 +080011080 pthread_mutex_lock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011081 // restore A2DP device for active usecases and unmute if required
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080011082 if (is_a2dp_out_device_type(&out->device_list)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011083 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
Zhou Songe5225132019-09-26 15:33:36 +080011084 if (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)
11085 select_devices(adev, uc_info->id);
Zhou Songbaddf9f2020-11-20 13:57:39 +080011086
11087 if (is_offload_usecase(out->usecase)) {
11088 if (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)
Weiyin Jiang280ea742020-09-08 20:28:22 +080011089 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
Zhou Songbaddf9f2020-11-20 13:57:39 +080011090 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
11091 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
11092 } else {
11093 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011094 }
Zhou Songbaddf9f2020-11-20 13:57:39 +080011095 out->a2dp_muted = false;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011096 }
Weiyin Jiang280ea742020-09-08 20:28:22 +080011097 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011098 } else {
Weiyin Jiang280ea742020-09-08 20:28:22 +080011099 pthread_mutex_lock(&out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +080011100 // mute stream and switch to speaker if suspended
11101 if (!out->a2dp_muted && !out->standby) {
Zhou Songbaddf9f2020-11-20 13:57:39 +080011102 assign_devices(&devices, &out->device_list);
11103 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Zhou Song407e5aa2020-12-27 19:13:04 +080011104 list_for_each(node, &adev->usecase_list) {
11105 usecase = node_to_item(node, struct audio_usecase, list);
Zhou Songe63b6fe2021-04-15 13:54:46 +080011106 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
11107 !is_a2dp_out_device_type(&usecase->stream.out->device_list) &&
Zhou Songcf77af02021-05-14 18:21:14 +080011108 !is_sco_out_device_type(&usecase->stream.out->device_list) &&
Zhou Songe63b6fe2021-04-15 13:54:46 +080011109 platform_check_backends_match(SND_DEVICE_OUT_SPEAKER,
11110 usecase->out_snd_device)) {
Zhou Song407e5aa2020-12-27 19:13:04 +080011111 assign_devices(&out->device_list, &usecase->stream.out->device_list);
11112 break;
11113 }
11114 }
Zhou Songcf77af02021-05-14 18:21:14 +080011115 if ((is_a2dp_out_device_type(&devices) && list_length(&devices) == 1) ||
11116 (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)) {
Zhou Song8edbbdb2021-01-14 16:48:03 +080011117 out->a2dp_muted = true;
11118 if (is_offload_usecase(out->usecase)) {
11119 if (out->offload_state == OFFLOAD_STATE_PLAYING)
11120 compress_pause(out->compr);
11121 out_set_compr_volume(&out->stream, (float)0, (float)0);
Zhou Song8edbbdb2021-01-14 16:48:03 +080011122 } else {
Weiyin Jiang906db3c2021-03-02 13:17:04 +080011123 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
11124 out_set_voip_volume(&out->stream, (float)0, (float)0);
11125 else
11126 out_set_pcm_volume(&out->stream, (float)0, (float)0);
11127
Zhou Song8edbbdb2021-01-14 16:48:03 +080011128 /* wait for stale pcm drained before switching to speaker */
11129 uint32_t latency =
11130 (out->config.period_count * out->config.period_size * 1000) /
11131 (out->config.rate);
11132 usleep(latency * 1000);
11133 }
Zhou Songbaddf9f2020-11-20 13:57:39 +080011134 }
11135 select_devices(adev, out->usecase);
Zhou Song8edbbdb2021-01-14 16:48:03 +080011136 ALOGD("%s: switched to device:%s and stream muted:%d", __func__,
11137 platform_get_snd_device_name(uc_info->out_snd_device), out->a2dp_muted);
Zhou Songbaddf9f2020-11-20 13:57:39 +080011138 if (is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011139 if (out->offload_state == OFFLOAD_STATE_PLAYING)
11140 compress_resume(out->compr);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011141 }
Zhou Songbaddf9f2020-11-20 13:57:39 +080011142 assign_devices(&out->device_list, &devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011143 }
Weiyin Jiang280ea742020-09-08 20:28:22 +080011144 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011145 }
Zhenlin Lian4f947842022-05-14 15:50:52 +053011146 clear_devices(&devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011147 ALOGV("%s: exit", __func__);
11148 return 0;
11149}
11150
Haynes Mathew George01156f92018-04-13 15:29:54 -070011151void adev_on_battery_status_changed(bool charging)
11152{
11153 pthread_mutex_lock(&adev->lock);
11154 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
11155 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +080011156 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -070011157 pthread_mutex_unlock(&adev->lock);
11158}
11159
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011160static int adev_open(const hw_module_t *module, const char *name,
11161 hw_device_t **device)
11162{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053011163 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -080011164 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053011165 char mixer_ctl_name[128] = {0};
11166 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053011167
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080011168 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011169 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
11170
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070011171 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -070011172 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070011173 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -070011174 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070011175 ALOGD("%s: returning existing instance of adev", __func__);
11176 ALOGD("%s: exit", __func__);
11177 pthread_mutex_unlock(&adev_init_lock);
11178 return 0;
11179 }
11180
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011181 adev = calloc(1, sizeof(struct audio_device));
11182
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -070011183 if (!adev) {
11184 pthread_mutex_unlock(&adev_init_lock);
11185 return -ENOMEM;
11186 }
11187
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -070011188 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
11189
Weiyin Jiange6ce6312019-01-28 18:28:22 +080011190 // register audio ext hidl at the earliest
11191 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053011192#ifdef DYNAMIC_LOG_ENABLED
11193 register_for_dynamic_logging("hal");
11194#endif
11195
Derek Chenf939fb72018-11-13 13:34:41 -080011196 /* default audio HAL major version */
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011197 uint32_t maj_version = 3;
Derek Chenf939fb72018-11-13 13:34:41 -080011198 if(property_get("vendor.audio.hal.maj.version", value, NULL))
11199 maj_version = atoi(value);
11200
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011201 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -080011202 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011203 adev->device.common.module = (struct hw_module_t *)module;
11204 adev->device.common.close = adev_close;
11205
11206 adev->device.init_check = adev_init_check;
11207 adev->device.set_voice_volume = adev_set_voice_volume;
11208 adev->device.set_master_volume = adev_set_master_volume;
11209 adev->device.get_master_volume = adev_get_master_volume;
11210 adev->device.set_master_mute = adev_set_master_mute;
11211 adev->device.get_master_mute = adev_get_master_mute;
11212 adev->device.set_mode = adev_set_mode;
11213 adev->device.set_mic_mute = adev_set_mic_mute;
11214 adev->device.get_mic_mute = adev_get_mic_mute;
11215 adev->device.set_parameters = adev_set_parameters;
11216 adev->device.get_parameters = adev_get_parameters;
11217 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
11218 adev->device.open_output_stream = adev_open_output_stream;
11219 adev->device.close_output_stream = adev_close_output_stream;
11220 adev->device.open_input_stream = adev_open_input_stream;
11221 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053011222 adev->device.create_audio_patch = adev_create_audio_patch;
11223 adev->device.release_audio_patch = adev_release_audio_patch;
11224 adev->device.get_audio_port = adev_get_audio_port;
11225 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011226 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +053011227 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011228
11229 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011230 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -080011231 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011232 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011233 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -080011234 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -070011235 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +053011236 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -070011237 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -070011238 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -070011239 /* Init audio and voice feature */
11240 audio_extn_feature_init();
11241 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070011242 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -080011243 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -080011244 list_init(&adev->active_inputs_list);
11245 list_init(&adev->active_outputs_list);
Rahul Sharma99770982019-03-06 17:05:26 +053011246 list_init(&adev->audio_patch_record_list);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011247 adev->io_streams_map = hashmapCreate(AUDIO_IO_PORTS_MAX, audio_extn_utils_hash_fn,
11248 audio_extn_utils_hash_eq);
11249 if (!adev->io_streams_map) {
11250 ALOGE("%s: Could not create io streams map", __func__);
11251 ret = -ENOMEM;
11252 goto adev_open_err;
11253 }
11254 adev->patch_map = hashmapCreate(AUDIO_PATCH_PORTS_MAX, audio_extn_utils_hash_fn,
11255 audio_extn_utils_hash_eq);
11256 if (!adev->patch_map) {
11257 ALOGE("%s: Could not create audio patch map", __func__);
11258 ret = -ENOMEM;
11259 goto adev_open_err;
11260 }
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -080011261 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -070011262 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +053011263 adev->pcm_record_uc_state = 0;
Kogara Naveen Kumarc5758232022-11-07 20:25:40 +053011264 adev->pcm_low_latency_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +053011265 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +053011266 adev->perf_lock_opts[0] = 0x101;
11267 adev->perf_lock_opts[1] = 0x20E;
11268 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +080011269 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -070011270 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053011271 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070011272 adev->adm_routing_changed = false;
Revathi Uddarajub26e3932020-06-10 14:51:02 +053011273 adev->a2dp_started = false;
Zhou Song503196b2021-07-23 17:31:05 +080011274 adev->ha_proxy_enable = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +053011275
Zhou Song68ebc352019-12-05 17:11:15 +080011276 audio_extn_perf_lock_init();
11277
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011278 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -070011279 adev->platform = platform_init(adev);
11280 if (!adev->platform) {
Eric Laurentb23d5282013-05-14 15:27:20 -070011281 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011282 ret = -EINVAL;
11283 goto adev_open_err;
Eric Laurentb23d5282013-05-14 15:27:20 -070011284 }
Eric Laurentc4aef752013-09-12 17:45:53 -070011285
Aalique Grahame22e49102018-12-18 14:23:57 -080011286 adev->extspk = audio_extn_extspk_init(adev);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053011287 if (audio_extn_qap_is_enabled()) {
11288 ret = audio_extn_qap_init(adev);
11289 if (ret < 0) {
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053011290 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011291 goto adev_open_err;
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053011292 }
11293 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
11294 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
11295 }
Aalique Grahame22e49102018-12-18 14:23:57 -080011296
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053011297 if (audio_extn_qaf_is_enabled()) {
11298 ret = audio_extn_qaf_init(adev);
11299 if (ret < 0) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053011300 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011301 goto adev_open_err;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053011302 }
11303
11304 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
11305 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
11306 }
11307
Derek Chenae7b0342019-02-08 15:17:04 -080011308 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -080011309 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
11310
Eric Laurentc4aef752013-09-12 17:45:53 -070011311 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
11312 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
11313 if (adev->visualizer_lib == NULL) {
11314 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
11315 } else {
11316 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
11317 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080011318 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070011319 "visualizer_hal_start_output");
11320 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080011321 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070011322 "visualizer_hal_stop_output");
11323 }
11324 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +053011325 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080011326 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -080011327 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +080011328 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +053011329 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070011330 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -070011331
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080011332 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
11333 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
11334 if (adev->offload_effects_lib == NULL) {
11335 ALOGE("%s: DLOPEN failed for %s", __func__,
11336 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
11337 } else {
11338 ALOGV("%s: DLOPEN successful for %s", __func__,
11339 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
11340 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +053011341 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080011342 "offload_effects_bundle_hal_start_output");
11343 adev->offload_effects_stop_output =
11344 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
11345 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080011346 adev->offload_effects_set_hpx_state =
11347 (int (*)(bool))dlsym(adev->offload_effects_lib,
11348 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +053011349 adev->offload_effects_get_parameters =
11350 (void (*)(struct str_parms *, struct str_parms *))
11351 dlsym(adev->offload_effects_lib,
11352 "offload_effects_bundle_get_parameters");
11353 adev->offload_effects_set_parameters =
11354 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
11355 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080011356 }
11357 }
11358
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070011359 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
11360 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
11361 if (adev->adm_lib == NULL) {
11362 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
11363 } else {
11364 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
11365 adev->adm_init = (adm_init_t)
11366 dlsym(adev->adm_lib, "adm_init");
11367 adev->adm_deinit = (adm_deinit_t)
11368 dlsym(adev->adm_lib, "adm_deinit");
11369 adev->adm_register_input_stream = (adm_register_input_stream_t)
11370 dlsym(adev->adm_lib, "adm_register_input_stream");
11371 adev->adm_register_output_stream = (adm_register_output_stream_t)
11372 dlsym(adev->adm_lib, "adm_register_output_stream");
11373 adev->adm_deregister_stream = (adm_deregister_stream_t)
11374 dlsym(adev->adm_lib, "adm_deregister_stream");
11375 adev->adm_request_focus = (adm_request_focus_t)
11376 dlsym(adev->adm_lib, "adm_request_focus");
11377 adev->adm_abandon_focus = (adm_abandon_focus_t)
11378 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -070011379 adev->adm_set_config = (adm_set_config_t)
11380 dlsym(adev->adm_lib, "adm_set_config");
11381 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
11382 dlsym(adev->adm_lib, "adm_request_focus_v2");
11383 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
11384 dlsym(adev->adm_lib, "adm_is_noirq_avail");
11385 adev->adm_on_routing_change = (adm_on_routing_change_t)
11386 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070011387 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
11388 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070011389 }
11390 }
11391
Aalique Grahame22e49102018-12-18 14:23:57 -080011392 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070011393 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +080011394 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Kunlei Zhanga3c4cb02021-03-05 16:03:54 +080011395 adev->fluence_nn_usecase_id = USECASE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -080011396 //initialize this to false for now,
11397 //this will be set to true through set param
11398 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070011399
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -070011400 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011401 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -080011402
11403 if (k_enable_extended_precision)
11404 adev_verify_devices(adev);
11405
Xiaojun Sang785b5da2017-08-03 15:52:29 +080011406 adev->dsp_bit_width_enforce_mode =
11407 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011408
Dhananjay Kumard6d32152016-10-13 16:11:03 +053011409 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
11410 &adev->streams_output_cfg_list,
11411 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070011412
Kiran Kandi910e1862013-10-29 13:29:42 -070011413 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070011414
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070011415 int trial;
Manisha Agarwalc75a0202019-12-06 18:48:25 +053011416 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070011417 trial = atoi(value);
11418 if (period_size_is_plausible_for_low_latency(trial)) {
11419 pcm_config_low_latency.period_size = trial;
11420 pcm_config_low_latency.start_threshold = trial / 4;
11421 pcm_config_low_latency.avail_min = trial / 4;
11422 configured_low_latency_capture_period_size = trial;
11423 }
11424 }
ronghuiz93177262021-04-21 19:58:13 +080011425 if (property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070011426 trial = atoi(value);
11427 if (period_size_is_plausible_for_low_latency(trial)) {
11428 configured_low_latency_capture_period_size = trial;
11429 }
11430 }
11431
Vignesh Kulothungan7d374312018-02-21 17:12:00 -080011432 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
11433
Eric Laurent4b084132018-10-19 17:33:43 -070011434 adev->camera_orientation = CAMERA_DEFAULT;
11435
Manisha Agarwalc75a0202019-12-06 18:48:25 +053011436 if (property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -070011437 af_period_multiplier = atoi(value);
11438 if (af_period_multiplier < 0)
11439 af_period_multiplier = 2;
11440 else if (af_period_multiplier > 4)
11441 af_period_multiplier = 4;
11442
11443 ALOGV("new period_multiplier = %d", af_period_multiplier);
11444 }
11445
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080011446 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080011447
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -070011448 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070011449 pthread_mutex_unlock(&adev_init_lock);
11450
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070011451 if (adev->adm_init)
11452 adev->adm_data = adev->adm_init();
11453
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053011454 qahwi_init(*device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080011455 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053011456
11457 audio_extn_snd_mon_init();
11458 pthread_mutex_lock(&adev->lock);
11459 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
11460 adev->card_status = CARD_STATUS_ONLINE;
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -050011461 adev->out_power_policy = POWER_POLICY_STATUS_ONLINE;
11462 adev->in_power_policy = POWER_POLICY_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -070011463 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
11464 /*
11465 * if the battery state callback happens before charging can be queried,
11466 * it will be guarded with the adev->lock held in the cb function and so
11467 * the callback value will reflect the latest state
11468 */
11469 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053011470 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +080011471 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -070011472 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +080011473 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053011474 /* Allocate memory for Device config params */
11475 adev->device_cfg_params = (struct audio_device_config_param*)
11476 calloc(platform_get_max_codec_backend(),
11477 sizeof(struct audio_device_config_param));
11478 if (adev->device_cfg_params == NULL)
11479 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053011480
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053011481 /*
11482 * Check if new PSPD matrix mixer control is supported. If not
11483 * supported, then set flag so that old mixer ctrl is sent while
11484 * sending pspd coefficients on older kernel version. Query mixer
11485 * control for default pcm id and channel value one.
11486 */
11487 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
11488 "AudStr %d ChMixer Weight Ch %d", 0, 1);
11489
11490 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
11491 if (!ctl) {
11492 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
11493 __func__, mixer_ctl_name);
11494 adev->use_old_pspd_mix_ctrl = true;
11495 }
11496
Jaideep Sharma0fa53812020-09-17 09:00:11 +053011497 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011498 return 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011499
11500adev_open_err:
11501 free_map(adev->patch_map);
11502 free_map(adev->io_streams_map);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080011503 free(adev->snd_dev_ref_cnt);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011504 pthread_mutex_destroy(&adev->lock);
11505 free(adev);
11506 adev = NULL;
11507 *device = NULL;
11508 pthread_mutex_unlock(&adev_init_lock);
11509 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011510}
11511
11512static struct hw_module_methods_t hal_module_methods = {
11513 .open = adev_open,
11514};
11515
11516struct audio_module HAL_MODULE_INFO_SYM = {
11517 .common = {
11518 .tag = HARDWARE_MODULE_TAG,
11519 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
11520 .hal_api_version = HARDWARE_HAL_API_VERSION,
11521 .id = AUDIO_HARDWARE_MODULE_ID,
11522 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -080011523 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011524 .methods = &hal_module_methods,
11525 },
11526};