blob: d4d121837a64d9338415d7e1f7578e9c3cd30ed8 [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 &
Kogara Naveen Kumare88ee942022-12-22 17:01:12 +05303358 (audio_output_flags_t)AUDIO_OUTPUT_FLAG_PHONE) || (usecase->stream.out->flags &
3359 (audio_output_flags_t)AUDIO_OUTPUT_FLAG_NAV_GUIDANCE) || (usecase->stream.out->flags &
3360 (audio_output_flags_t)AUDIO_OUTPUT_FLAG_ALERTS)))) {
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +05303361 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3362 }
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +05303363#else
3364 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3365#endif
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003366 }
Weiyin Jiangcdece202019-07-08 16:13:16 +08003367 }
3368 enable_audio_route(adev, usecase);
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003369
Shalini Manjunatha5e610912020-12-29 13:02:25 +05303370 if (uc_id == USECASE_AUDIO_PLAYBACK_VOIP) {
3371 struct stream_in *voip_in = get_voice_communication_input(adev);
3372 struct audio_usecase *voip_in_usecase = NULL;
3373 voip_in_usecase = get_usecase_from_list(adev, USECASE_AUDIO_RECORD_VOIP);
3374 if (voip_in != NULL &&
3375 voip_in_usecase != NULL &&
3376 !(out_snd_device == AUDIO_DEVICE_OUT_SPEAKER ||
3377 out_snd_device == AUDIO_DEVICE_OUT_SPEAKER_SAFE) &&
3378 (voip_in_usecase->in_snd_device ==
3379 platform_get_input_snd_device(adev->platform, voip_in,
3380 &usecase->stream.out->device_list,usecase->type))) {
3381 /*
3382 * if VOIP TX is enabled before VOIP RX, needs to re-route the TX path
3383 * for enabling echo-reference-voip with correct port
3384 */
3385 ALOGD("%s: VOIP TX is enabled before VOIP RX,needs to re-route the TX path",__func__);
3386 disable_audio_route(adev, voip_in_usecase);
3387 disable_snd_device(adev, voip_in_usecase->in_snd_device);
3388 enable_snd_device(adev, voip_in_usecase->in_snd_device);
3389 enable_audio_route(adev, voip_in_usecase);
3390 }
3391 }
Ramjee Singhcdf67af2021-09-29 14:20:27 +05303392 if (voice_extn_compress_voip_is_active(adev)) {
3393 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
3394 USECASE_COMPRESS_VOIP_CALL);
3395 /*
3396 * If only compress voip input is opened voip out will be primary out.
3397 * Need to consider re-routing to select correct i/p pair
3398 */
3399 if ((voip_usecase != NULL) &&
3400 (usecase->type == PCM_PLAYBACK) &&
3401 (usecase->stream.out == voip_usecase->stream.out)) {
3402 in_snd_device = platform_get_input_snd_device(adev->platform,
3403 NULL,
3404 &usecase->stream.out->device_list,
3405 usecase->type);
3406 if (voip_usecase->in_snd_device != in_snd_device ) {
3407 ALOGD("%s:Re routing compress voip tx snd device matching voip rx pair",
3408 __func__);
3409 disable_audio_route(adev, voip_usecase);
3410 disable_snd_device(adev, voip_usecase->in_snd_device);
3411 voip_usecase->in_snd_device = in_snd_device;
3412 voip_usecase->out_snd_device = usecase->out_snd_device;
3413 /* Route all TX usecase to Compress voip BE */
3414 check_usecases_capture_codec_backend(adev, voip_usecase, in_snd_device);
3415 enable_snd_device(adev, in_snd_device);
3416 /* Send Voice related calibration for RX /TX pair */
3417 status = platform_switch_voice_call_device_post(adev->platform,
3418 out_snd_device,
3419 in_snd_device);
3420 enable_audio_route(adev, voip_usecase);
3421 }
3422 }
3423 }
Shalini Manjunatha5e610912020-12-29 13:02:25 +05303424
3425
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08003426 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08003427
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003428 /* If input stream is already running then effect needs to be
3429 applied on the new input device that's being enabled here. */
Eric Laurent637e2d42018-11-15 12:24:31 -08003430 if (in_snd_device != SND_DEVICE_NONE)
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003431 check_and_enable_effect(adev);
3432
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003433 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003434 /* Enable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303435 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003436 voice_check_and_update_aanc_path(adev, out_snd_device, true);
3437
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003438 /* Enable sidetone only if other voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303439 if (voice_is_call_state_active_in_call(adev) ||
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003440 voice_extn_compress_voip_is_started(adev))
3441 voice_set_sidetone(adev, out_snd_device, true);
3442 }
3443
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003444 /* Applicable only on the targets that has external modem.
3445 * Enable device command should be sent to modem only after
3446 * enabling voice call mixer controls
3447 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07003448 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003449 status = platform_switch_voice_call_usecase_route_post(adev->platform,
3450 out_snd_device,
3451 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303452
3453 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003454 struct stream_in *in = adev_get_active_input(adev);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303455 if (usecase->type == VOIP_CALL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003456 if (in != NULL && !in->standby) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303457 if (is_bt_soc_on(adev) == false){
3458 ALOGD("BT SCO MIC disconnected while in connection");
Eric Laurent637e2d42018-11-15 12:24:31 -08003459 if (in->pcm != NULL)
3460 pcm_stop(in->pcm);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303461 }
3462 }
3463 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
3464 && usecase->stream.out->started) {
3465 if (is_bt_soc_on(adev) == false) {
3466 ALOGD("BT SCO/A2DP disconnected while in connection");
3467 out_standby_l(&usecase->stream.out->stream.common);
3468 }
3469 }
3470 } else if ((usecase->stream.out != NULL) &&
3471 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05303472 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
3473 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Weiyin Jiang0d373242019-07-25 13:18:17 +08003474 (usecase->type != PCM_CAPTURE) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303475 usecase->stream.out->started) {
3476 if (is_bt_soc_on(adev) == false) {
3477 ALOGD("BT SCO/A2dp disconnected while in connection");
3478 out_standby_l(&usecase->stream.out->stream.common);
3479 }
3480 }
3481 }
3482
Yung Ti Su70cb8242018-06-22 17:38:47 +08003483 if (usecase->type != PCM_CAPTURE && usecase == voip_usecase) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003484 struct stream_out *voip_out = voip_usecase->stream.out;
3485 audio_extn_utils_send_app_type_gain(adev,
3486 voip_out->app_type_cfg.app_type,
3487 &voip_out->app_type_cfg.gain[0]);
3488 }
3489
Ajender Reddyb940b832021-07-07 11:51:42 +05303490 ALOGD("%s: done",__func__);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303491
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003492 return status;
3493}
3494
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003495static int stop_input_stream(struct stream_in *in)
3496{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303497 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003498 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05303499
3500 if (in == NULL) {
3501 ALOGE("%s: stream_in ptr is NULL", __func__);
3502 return -EINVAL;
3503 }
3504
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003505 struct audio_device *adev = in->dev;
Carter Hsu2e429db2019-05-14 18:50:52 +08003506 struct stream_in *priority_in = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003507
Eric Laurent994a6932013-07-17 11:51:42 -07003508 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003509 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003510 uc_info = get_usecase_from_list(adev, in->usecase);
3511 if (uc_info == NULL) {
3512 ALOGE("%s: Could not find the usecase (%d) in the list",
3513 __func__, in->usecase);
3514 return -EINVAL;
3515 }
Krishna Kishor Jhaaf83fd82022-11-15 17:54:07 +05303516#ifdef SKIP_INPUT_SOURCE_PRIORITY
3517 // Skip (1)fm-virtual-record and (2)echo-reference-external from get-priority-input logic.
3518 // See comment in function select_devices() before call to get_priority_input()
3519 if ((in->usecase == USECASE_AUDIO_RECORD_FM_VIRTUAL || in->usecase == USECASE_AUDIO_RECORD_ECHO_REF_EXT)){
3520 ALOGD("%s: Skipping get_priority_input for use-case-id:%d/%s.", __func__, in->usecase, use_case_table[in->usecase]);
3521 } else {
3522 priority_in = get_priority_input(adev);
3523 }
3524#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003525
Carter Hsu2e429db2019-05-14 18:50:52 +08003526 priority_in = get_priority_input(adev);
3527
Krishna Kishor Jhaaf83fd82022-11-15 17:54:07 +05303528#endif
3529
Derek Chenea197282019-01-07 17:35:01 -08003530 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3531 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003532
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003533 /* Close in-call recording streams */
3534 voice_check_and_stop_incall_rec_usecase(adev, in);
3535
Eric Laurent150dbfe2013-02-27 14:31:02 -08003536 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003537 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003538
3539 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003540 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003541
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003542 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303543 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_PRIMARY);
3544
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003545 list_remove(&uc_info->list);
Zhenlin Lian4f947842022-05-14 15:50:52 +05303546 clear_devices(&uc_info->device_list);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003547 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003548
Carter Hsu2e429db2019-05-14 18:50:52 +08003549 if (priority_in == in) {
3550 priority_in = get_priority_input(adev);
Sujin Panicker110f7942021-08-26 17:01:22 +05303551 if (priority_in) {
3552 if (is_usb_in_device_type(&priority_in->device_list)) {
3553 if (audio_extn_usb_connected(NULL))
3554 select_devices(adev, priority_in->usecase);
3555 } else {
3556 select_devices(adev, priority_in->usecase);
3557 }
3558 }
Carter Hsu2e429db2019-05-14 18:50:52 +08003559 }
3560
Vatsal Buchac09ae062018-11-14 13:25:08 +05303561 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07003562 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003563 return ret;
3564}
3565
3566int start_input_stream(struct stream_in *in)
3567{
3568 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08003569 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003570 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05303571
3572 if (in == NULL) {
3573 ALOGE("%s: stream_in ptr is NULL", __func__);
3574 return -EINVAL;
3575 }
3576
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003577 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07003578 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07003579 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003580
Mingming Yin2664a5b2015-09-03 10:53:11 -07003581 if (get_usecase_from_list(adev, usecase) == NULL)
3582 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303583 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
3584 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003585
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303586 if (CARD_STATUS_OFFLINE == in->card_status||
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05003587 CARD_STATUS_OFFLINE == adev->card_status ||
3588 POWER_POLICY_STATUS_OFFLINE == adev->in_power_policy) {
3589 ALOGW("in->card_status or adev->card_status or adev->input_power offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303590 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303591 goto error_config;
3592 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303593
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003594 if (is_sco_in_device_type(&in->device_list)) {
Lakshman Chaluvaraju87f53aa2021-02-02 15:50:11 +05303595 if (!adev->bt_sco_on || audio_extn_a2dp_source_is_ready()) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303596 ALOGE("%s: SCO profile is not ready, return error", __func__);
3597 ret = -EIO;
3598 goto error_config;
3599 }
3600 }
3601
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003602 /* Check if source matches incall recording usecase criteria */
3603 ret = voice_check_and_set_incall_rec_usecase(adev, in);
3604 if (ret)
3605 goto error_config;
3606 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07003607 ALOGV("%s: usecase(%d)", __func__, in->usecase);
3608
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303609 if (audio_extn_cin_attached_usecase(in))
3610 audio_extn_cin_acquire_usecase(in);
3611
Mingming Yin2664a5b2015-09-03 10:53:11 -07003612 if (get_usecase_from_list(adev, in->usecase) != NULL) {
3613 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
3614 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Weiyin Jiang38c0e612020-09-10 16:10:51 +08003615 ret = -EINVAL;
3616 goto error_config;
Mingming Yin2664a5b2015-09-03 10:53:11 -07003617 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003618
Eric Laurentb23d5282013-05-14 15:27:20 -07003619 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003620 if (in->pcm_device_id < 0) {
3621 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
3622 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08003623 ret = -EINVAL;
3624 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003625 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003626
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003627 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003628
3629 if (!uc_info) {
3630 ret = -ENOMEM;
3631 goto error_config;
3632 }
3633
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003634 uc_info->id = in->usecase;
3635 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003636 uc_info->stream.in = in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003637 list_init(&uc_info->device_list);
3638 assign_devices(&uc_info->device_list, &in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003639 uc_info->in_snd_device = SND_DEVICE_NONE;
3640 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003641
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003642 list_add_tail(&adev->usecase_list, &uc_info->list);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003643 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303644 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3645 adev->perf_lock_opts,
3646 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003647 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003648
Derek Chenea197282019-01-07 17:35:01 -08003649 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3650 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003651
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05303652 android_atomic_acquire_cas(true, false, &(in->capture_stopped));
3653
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303654 if (audio_extn_cin_attached_usecase(in)) {
Manish Dewangan46e07982018-12-13 18:18:59 +05303655 ret = audio_extn_cin_open_input_stream(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303656 if (ret)
3657 goto error_open;
3658 else
3659 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003660 }
3661
Haynes Mathew George16081042017-05-31 17:16:49 -07003662 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003663 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003664 ALOGE("%s: pcm stream not ready", __func__);
3665 goto error_open;
3666 }
3667 ret = pcm_start(in->pcm);
3668 if (ret < 0) {
3669 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3670 goto error_open;
3671 }
3672 } else {
3673 unsigned int flags = PCM_IN | PCM_MONOTONIC;
3674 unsigned int pcm_open_retry_count = 0;
3675
Zhou Song62ea0282020-03-22 19:53:01 +08003676 if ((in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) ||
3677 (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003678 flags |= PCM_MMAP | PCM_NOIRQ;
3679 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
3680 } else if (in->realtime) {
3681 flags |= PCM_MMAP | PCM_NOIRQ;
3682 }
3683
Garmond Leunge2433c32017-09-28 21:51:22 -07003684 if (audio_extn_ffv_get_stream() == in) {
3685 ALOGD("%s: ffv stream, update pcm config", __func__);
3686 audio_extn_ffv_update_pcm_config(&config);
3687 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003688 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3689 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3690
3691 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003692 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07003693 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07003694 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003695 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303696 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303697 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3698 adev->card_status = CARD_STATUS_OFFLINE;
3699 in->card_status = CARD_STATUS_OFFLINE;
3700 ret = -EIO;
3701 goto error_open;
3702 }
3703
Haynes Mathew George16081042017-05-31 17:16:49 -07003704 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3705 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3706 if (in->pcm != NULL) {
3707 pcm_close(in->pcm);
3708 in->pcm = NULL;
3709 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003710 if (pcm_open_retry_count == 0) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003711 ret = -EIO;
3712 goto error_open;
3713 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003714 pcm_open_retry_count--;
Haynes Mathew George16081042017-05-31 17:16:49 -07003715 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3716 continue;
3717 }
3718 break;
3719 }
3720
3721 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003722 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07003723 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003724 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003725 if (ret < 0) {
3726 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3727 pcm_close(in->pcm);
3728 in->pcm = NULL;
3729 goto error_open;
3730 }
Vaibhav Raut5f3bf222023-02-06 17:45:22 +05303731 if (in->flags & (AUDIO_INPUT_FLAG_FAST | AUDIO_INPUT_FLAG_RAW))
Narsinga Rao Chellaa6e1f702021-10-22 13:57:32 +05303732 register_in_stream(in);
Haynes Mathew George16081042017-05-31 17:16:49 -07003733 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003734 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07003735 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003736 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003737 if (ret < 0) {
3738 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003739 pcm_close(in->pcm);
3740 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003741 goto error_open;
3742 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003743 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003744 }
3745
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003746 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07003747 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
3748 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003749
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003750 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303751 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
3752
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303753done_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003754 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303755 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Manisha Agarwal4c2402e2020-10-21 12:02:57 +05303756 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303757 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003758 return ret;
3759
3760error_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003761 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303762 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003763 stop_input_stream(in);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003764
Eric Laurentc8400632013-02-14 19:04:54 -08003765error_config:
Weiyin Jiang38c0e612020-09-10 16:10:51 +08003766 if (audio_extn_cin_attached_usecase(in))
3767 audio_extn_cin_close_input_stream(in);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303768 /*
3769 * sleep 50ms to allow sufficient time for kernel
3770 * drivers to recover incases like SSR.
3771 */
3772 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003773 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303774 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003775 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003776}
3777
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003778void lock_input_stream(struct stream_in *in)
3779{
3780 pthread_mutex_lock(&in->pre_lock);
3781 pthread_mutex_lock(&in->lock);
3782 pthread_mutex_unlock(&in->pre_lock);
3783}
3784
3785void lock_output_stream(struct stream_out *out)
3786{
3787 pthread_mutex_lock(&out->pre_lock);
3788 pthread_mutex_lock(&out->lock);
3789 pthread_mutex_unlock(&out->pre_lock);
3790}
3791
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003792/* must be called with out->lock locked */
3793static int send_offload_cmd_l(struct stream_out* out, int command)
3794{
3795 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
3796
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003797 if (!cmd) {
3798 ALOGE("failed to allocate mem for command 0x%x", command);
3799 return -ENOMEM;
3800 }
3801
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003802 ALOGVV("%s %d", __func__, command);
3803
3804 cmd->cmd = command;
3805 list_add_tail(&out->offload_cmd_list, &cmd->node);
3806 pthread_cond_signal(&out->offload_cond);
3807 return 0;
3808}
3809
Gautam Manam14c198b2020-12-24 14:08:04 +05303810/* must be called with out->lock */
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003811static void stop_compressed_output_l(struct stream_out *out)
3812{
Gautam Manam14c198b2020-12-24 14:08:04 +05303813 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003814 out->offload_state = OFFLOAD_STATE_IDLE;
Gautam Manam14c198b2020-12-24 14:08:04 +05303815 pthread_mutex_unlock(&out->latch_lock);
Weiyin Jiang906db3c2021-03-02 13:17:04 +08003816
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003817 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003818 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003819 if (out->compr != NULL) {
3820 compress_stop(out->compr);
3821 while (out->offload_thread_blocked) {
3822 pthread_cond_wait(&out->cond, &out->lock);
3823 }
3824 }
3825}
3826
Varun Balaraje49253e2017-07-06 19:48:56 +05303827bool is_interactive_usecase(audio_usecase_t uc_id)
3828{
3829 unsigned int i;
3830 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
3831 if (uc_id == interactive_usecases[i])
3832 return true;
3833 }
3834 return false;
3835}
3836
3837static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
3838{
3839 audio_usecase_t ret_uc = USECASE_INVALID;
3840 unsigned int intract_uc_index;
3841 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3842
3843 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
3844 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
3845 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
3846 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
3847 ret_uc = interactive_usecases[intract_uc_index];
3848 break;
3849 }
3850 }
3851
3852 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
3853 return ret_uc;
3854}
3855
3856static void free_interactive_usecase(struct audio_device *adev,
3857 audio_usecase_t uc_id)
3858{
3859 unsigned int interact_uc_index;
3860 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3861
3862 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
3863 if (interactive_usecases[interact_uc_index] == uc_id) {
3864 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
3865 break;
3866 }
3867 }
3868 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
3869}
3870
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003871bool is_offload_usecase(audio_usecase_t uc_id)
3872{
3873 unsigned int i;
3874 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
3875 if (uc_id == offload_usecases[i])
3876 return true;
3877 }
3878 return false;
3879}
3880
Dhananjay Kumarac341582017-02-23 23:42:25 +05303881static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003882{
vivek mehta446c3962015-09-14 10:57:35 -07003883 audio_usecase_t ret_uc = USECASE_INVALID;
3884 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003885 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003886 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05303887 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07003888 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
3889 else
3890 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003891
vivek mehta446c3962015-09-14 10:57:35 -07003892 pthread_mutex_lock(&adev->lock);
3893 if (get_usecase_from_list(adev, ret_uc) != NULL)
3894 ret_uc = USECASE_INVALID;
3895 pthread_mutex_unlock(&adev->lock);
3896
3897 return ret_uc;
3898 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003899
3900 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003901 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3902 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3903 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3904 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003905 break;
3906 }
3907 }
vivek mehta446c3962015-09-14 10:57:35 -07003908
3909 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3910 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003911}
3912
3913static void free_offload_usecase(struct audio_device *adev,
3914 audio_usecase_t uc_id)
3915{
vivek mehta446c3962015-09-14 10:57:35 -07003916 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003917 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003918
3919 if (!adev->multi_offload_enable)
3920 return;
3921
3922 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3923 if (offload_usecases[offload_uc_index] == uc_id) {
3924 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003925 break;
3926 }
3927 }
3928 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3929}
3930
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003931static void *offload_thread_loop(void *context)
3932{
3933 struct stream_out *out = (struct stream_out *) context;
3934 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003935 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003936
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003937 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08003938 set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003939 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3940
3941 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003942 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003943 out->offload_state = OFFLOAD_STATE_IDLE;
3944 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003945 for (;;) {
3946 struct offload_cmd *cmd = NULL;
3947 stream_callback_event_t event;
3948 bool send_callback = false;
3949
3950 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3951 __func__, list_empty(&out->offload_cmd_list),
3952 out->offload_state);
3953 if (list_empty(&out->offload_cmd_list)) {
3954 ALOGV("%s SLEEPING", __func__);
3955 pthread_cond_wait(&out->offload_cond, &out->lock);
3956 ALOGV("%s RUNNING", __func__);
3957 continue;
3958 }
3959
3960 item = list_head(&out->offload_cmd_list);
3961 cmd = node_to_item(item, struct offload_cmd, node);
3962 list_remove(item);
3963
3964 ALOGVV("%s STATE %d CMD %d out->compr %p",
3965 __func__, out->offload_state, cmd->cmd, out->compr);
3966
3967 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3968 free(cmd);
3969 break;
3970 }
3971
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003972 // allow OFFLOAD_CMD_ERROR reporting during standby
3973 // this is needed to handle failures during compress_open
3974 // Note however that on a pause timeout, the stream is closed
3975 // and no offload usecase will be active. Therefore this
3976 // special case is needed for compress_open failures alone
3977 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3978 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003979 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003980 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003981 pthread_cond_signal(&out->cond);
3982 continue;
3983 }
3984 out->offload_thread_blocked = true;
3985 pthread_mutex_unlock(&out->lock);
3986 send_callback = false;
3987 switch(cmd->cmd) {
3988 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003989 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003990 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003991 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003992 send_callback = true;
3993 event = STREAM_CBK_EVENT_WRITE_READY;
3994 break;
3995 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003996 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303997 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003998 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303999 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004000 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05304001 if (ret < 0)
4002 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05304003 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05304004 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08004005 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08004006 else
4007 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08004008 if (-ENETRESET != ret && !(-EINTR == ret &&
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05004009 (CARD_STATUS_OFFLINE == out->card_status ||
4010 POWER_POLICY_STATUS_OFFLINE == adev->out_power_policy))) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05304011 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304012 pthread_mutex_lock(&out->lock);
4013 out->send_new_metadata = 1;
4014 out->send_next_track_params = true;
4015 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05304016 event = STREAM_CBK_EVENT_DRAIN_READY;
4017 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
4018 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304019 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004020 break;
4021 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004022 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08004023 ret = compress_drain(out->compr);
4024 ALOGD("copl(%p):out of compress_drain", out);
4025 // EINTR check avoids drain interruption due to SSR
4026 if (-ENETRESET != ret && !(-EINTR == ret &&
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05004027 (CARD_STATUS_OFFLINE == out->card_status ||
4028 POWER_POLICY_STATUS_OFFLINE == adev->out_power_policy))) {
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08004029 send_callback = true;
4030 event = STREAM_CBK_EVENT_DRAIN_READY;
4031 } else
4032 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004033 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304034 case OFFLOAD_CMD_ERROR:
4035 ALOGD("copl(%p): sending error callback to AF", out);
4036 send_callback = true;
4037 event = STREAM_CBK_EVENT_ERROR;
4038 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004039 default:
4040 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
4041 break;
4042 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004043 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004044 out->offload_thread_blocked = false;
4045 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004046 if (send_callback && out->client_callback) {
4047 ALOGVV("%s: sending client_callback event %d", __func__, event);
4048 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07004049 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004050 free(cmd);
4051 }
4052
4053 pthread_cond_signal(&out->cond);
4054 while (!list_empty(&out->offload_cmd_list)) {
4055 item = list_head(&out->offload_cmd_list);
4056 list_remove(item);
4057 free(node_to_item(item, struct offload_cmd, node));
4058 }
4059 pthread_mutex_unlock(&out->lock);
4060
4061 return NULL;
4062}
4063
4064static int create_offload_callback_thread(struct stream_out *out)
4065{
4066 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
4067 list_init(&out->offload_cmd_list);
4068 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
4069 offload_thread_loop, out);
4070 return 0;
4071}
4072
4073static int destroy_offload_callback_thread(struct stream_out *out)
4074{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004075 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004076 stop_compressed_output_l(out);
4077 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
4078
4079 pthread_mutex_unlock(&out->lock);
4080 pthread_join(out->offload_thread, (void **) NULL);
4081 pthread_cond_destroy(&out->offload_cond);
4082
4083 return 0;
4084}
4085
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004086static int stop_output_stream(struct stream_out *out)
4087{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304088 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004089 struct audio_usecase *uc_info;
4090 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08004091 bool has_voip_usecase =
4092 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004093
Eric Laurent994a6932013-07-17 11:51:42 -07004094 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004095 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004096 uc_info = get_usecase_from_list(adev, out->usecase);
4097 if (uc_info == NULL) {
4098 ALOGE("%s: Could not find the usecase (%d) in the list",
4099 __func__, out->usecase);
4100 return -EINVAL;
4101 }
4102
Zhou Songbaddf9f2020-11-20 13:57:39 +08004103 out->a2dp_muted = false;
4104
Derek Chenea197282019-01-07 17:35:01 -08004105 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
4106 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08004107
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004108 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304109 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004110 if (adev->visualizer_stop_output != NULL)
4111 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004112
4113 audio_extn_dts_remove_state_notifier_node(out->usecase);
4114
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004115 if (adev->offload_effects_stop_output != NULL)
4116 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07004117 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
4118 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4119 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004120 }
Eric Laurentc4aef752013-09-12 17:45:53 -07004121
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004122 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
4123 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07004124 voice_set_device_mute_flag(adev, false);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004125 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07004126
Eric Laurent150dbfe2013-02-27 14:31:02 -08004127 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07004128 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004129
4130 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07004131 disable_snd_device(adev, uc_info->out_snd_device);
Zhou Songd9bd9302020-08-04 16:34:45 +08004132 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
4133 disable_snd_device(adev, SND_DEVICE_OUT_HAPTICS);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004134
Aalique Grahame22e49102018-12-18 14:23:57 -08004135 audio_extn_extspk_update(adev->extspk);
4136
Xiaojun Sang785b5da2017-08-03 15:52:29 +08004137 if (is_offload_usecase(out->usecase)) {
4138 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
4139 adev->dsp_bit_width_enforce_mode,
4140 false);
4141 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004142 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07004143 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
4144 false);
4145
4146 if (ret != 0)
4147 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
4148 /* default service interval was successfully updated,
4149 reopen USB backend with new service interval */
4150 ret = 0;
4151 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08004152
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004153 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304154 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004155 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304156 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004157 ALOGV("Disable passthrough , reset mixer to pcm");
4158 /* NO_PASSTHROUGH */
Meng Wang4c32fb42020-01-16 17:57:11 +08004159#ifdef AUDIO_GKI_ENABLED
4160 /* out->compr_config.codec->reserved[0] is for compr_passthr */
4161 out->compr_config.codec->reserved[0] = 0;
4162#else
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004163 out->compr_config.codec->compr_passthr = 0;
Meng Wang4c32fb42020-01-16 17:57:11 +08004164#endif
Mingming Yin21854652016-04-13 11:54:02 -07004165 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004166 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
4167 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07004168
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304169 /* Must be called after removing the usecase from list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004170 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL))
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05304171 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304172
Manish Dewangan21a850a2017-08-14 12:03:55 +05304173 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07004174 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
4175 if (ret < 0)
4176 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
4177 }
4178
Zhou Song642ec432020-12-23 16:11:10 +08004179 /* trigger voip input to reroute when voip output changes to hearing aid */
Aalique Grahame22e49102018-12-18 14:23:57 -08004180 if (has_voip_usecase ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004181 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08004182 struct listnode *node;
4183 struct audio_usecase *usecase;
4184 list_for_each(node, &adev->usecase_list) {
4185 usecase = node_to_item(node, struct audio_usecase, list);
Zhou Song642ec432020-12-23 16:11:10 +08004186 if (usecase->type == PCM_PLAYBACK || usecase == uc_info ||
4187 (usecase->type == PCM_CAPTURE &&
Revathi Uddarajud9f23d92020-07-27 10:55:06 +05304188 usecase->id != USECASE_AUDIO_RECORD_VOIP &&
Zhou Song642ec432020-12-23 16:11:10 +08004189 usecase->id != USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY))
Aalique Grahame22e49102018-12-18 14:23:57 -08004190 continue;
4191
4192 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
4193 __func__, usecase->id, use_case_table[usecase->id],
4194 out->usecase, use_case_table[out->usecase]);
4195 select_devices(adev, usecase->id);
4196 }
4197 }
4198
Zhenlin Lian4f947842022-05-14 15:50:52 +05304199 clear_devices(&uc_info->device_list);
Garmond Leung5fd0b552018-04-17 11:56:12 -07004200 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07004201 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004202 return ret;
4203}
4204
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004205struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
4206 unsigned int flags, unsigned int pcm_open_retry_count,
4207 struct pcm_config *config)
4208{
4209 struct pcm* pcm = NULL;
4210
4211 while (1) {
4212 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
4213 if (pcm == NULL || !pcm_is_ready(pcm)) {
4214 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
4215 if (pcm != NULL) {
4216 pcm_close(pcm);
4217 pcm = NULL;
4218 }
Weiyin Jiang72197252019-10-09 11:49:32 +08004219 if (pcm_open_retry_count == 0)
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004220 return NULL;
4221
Weiyin Jiang72197252019-10-09 11:49:32 +08004222 pcm_open_retry_count--;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004223 usleep(PROXY_OPEN_WAIT_TIME * 1000);
4224 continue;
4225 }
4226 break;
4227 }
4228
4229 if (pcm_is_ready(pcm)) {
4230 int ret = pcm_prepare(pcm);
4231 if (ret < 0) {
4232 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
4233 pcm_close(pcm);
4234 pcm = NULL;
4235 }
4236 }
4237
4238 return pcm;
4239}
4240
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004241int start_output_stream(struct stream_out *out)
4242{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004243 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004244 struct audio_usecase *uc_info;
4245 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004246 char mixer_ctl_name[128];
4247 struct mixer_ctl *ctl = NULL;
4248 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304249 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004250 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004251
Haynes Mathew George380745d2017-10-04 15:27:45 -07004252 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004253 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
4254 ret = -EINVAL;
4255 goto error_config;
4256 }
4257
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004258 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304259 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004260 get_device_types(&out->device_list), is_haptic_usecase);
4261
4262 bool is_speaker_active = compare_device_type(&out->device_list,
4263 AUDIO_DEVICE_OUT_SPEAKER);
4264 bool is_speaker_safe_active = compare_device_type(&out->device_list,
4265 AUDIO_DEVICE_OUT_SPEAKER_SAFE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304266
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304267 if (CARD_STATUS_OFFLINE == out->card_status ||
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05004268 CARD_STATUS_OFFLINE == adev->card_status ||
4269 POWER_POLICY_STATUS_OFFLINE == adev->out_power_policy) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304270 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05304271 ret = -EIO;
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004272 goto error_fatal;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304273 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05304274
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004275 //Update incall music usecase to reflect correct voice session
4276 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
4277 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
4278 if (ret != 0) {
4279 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
4280 __func__, ret);
4281 goto error_config;
4282 }
4283 }
4284
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004285 if (is_a2dp_out_device_type(&out->device_list)) {
Florian Pfister1a84f312018-07-19 14:38:18 +02004286 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004287 if (is_speaker_active || is_speaker_safe_active) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304288 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304289 } else {
Zhou Songd01e7a22020-09-23 22:49:01 +08004290 if (!is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304291 ALOGE("%s: A2DP profile is not ready, return error", __func__);
4292 ret = -EAGAIN;
4293 goto error_config;
4294 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304295 }
4296 }
4297 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004298 if (is_sco_out_device_type(&out->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304299 if (!adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004300 if (is_speaker_active) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304301 //combo usecase just by pass a2dp
4302 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004303 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304304 } else {
4305 ALOGE("%s: SCO profile is not ready, return error", __func__);
4306 ret = -EAGAIN;
4307 goto error_config;
4308 }
4309 }
4310 }
4311
Eric Laurentb23d5282013-05-14 15:27:20 -07004312 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004313 if (out->pcm_device_id < 0) {
4314 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
4315 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004316 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004317 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004318 }
4319
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004320 if (is_haptic_usecase) {
Meng Wang51d8c2a2020-04-27 15:23:21 +08004321 adev->haptic_pcm_device_id = platform_get_pcm_device_id(
4322 USECASE_AUDIO_PLAYBACK_HAPTICS, PCM_PLAYBACK);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004323 if (adev->haptic_pcm_device_id < 0) {
4324 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
4325 __func__, adev->haptic_pcm_device_id, out->usecase);
4326 ret = -EINVAL;
4327 goto error_config;
4328 }
4329 }
4330
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004331 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004332
4333 if (!uc_info) {
4334 ret = -ENOMEM;
4335 goto error_config;
4336 }
4337
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004338 uc_info->id = out->usecase;
4339 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004340 uc_info->stream.out = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004341 list_init(&uc_info->device_list);
4342 assign_devices(&uc_info->device_list, &out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004343 uc_info->in_snd_device = SND_DEVICE_NONE;
4344 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07004345
4346 /* This must be called before adding this usecase to the list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004347 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07004348 audio_extn_usb_check_and_set_svc_int(uc_info, true);
4349 /* USB backend is not reopened immediately.
4350 This is eventually done as part of select_devices */
4351 }
4352
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004353 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004354
Wei Wangf7ca6c92017-11-21 14:51:20 -08004355 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304356 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4357 adev->perf_lock_opts,
4358 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304359
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004360 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05304361 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304362 if (audio_extn_passthru_is_enabled() &&
4363 audio_extn_passthru_is_passthrough_stream(out)) {
4364 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304365 }
4366 }
4367
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004368 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02004369 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304370 if (!a2dp_combo) {
4371 check_a2dp_restore_l(adev, out, false);
4372 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004373 struct listnode dev;
4374 list_init(&dev);
4375 assign_devices(&dev, &out->device_list);
4376 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4377 reassign_device_list(&out->device_list,
4378 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aalique Grahame22e49102018-12-18 14:23:57 -08004379 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004380 reassign_device_list(&out->device_list,
4381 AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304382 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004383 assign_devices(&out->device_list, &dev);
Zhenlin Lian4f947842022-05-14 15:50:52 +05304384 clear_devices(&dev);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304385 }
4386 } else {
Revathi Uddarajub26e3932020-06-10 14:51:02 +05304387 select_devices(adev, out->usecase);
4388 if (is_a2dp_out_device_type(&out->device_list) &&
4389 !adev->a2dp_started) {
4390 if (is_speaker_active || is_speaker_safe_active) {
4391 struct listnode dev;
4392 list_init(&dev);
4393 assign_devices(&dev, &out->device_list);
4394 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4395 reassign_device_list(&out->device_list,
4396 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
4397 else
4398 reassign_device_list(&out->device_list,
4399 AUDIO_DEVICE_OUT_SPEAKER, "");
4400 select_devices(adev, out->usecase);
4401 assign_devices(&out->device_list, &dev);
Zhenlin Lian4f947842022-05-14 15:50:52 +05304402 clear_devices(&dev);
Revathi Uddarajub26e3932020-06-10 14:51:02 +05304403 } else {
4404 ret = -EINVAL;
4405 goto error_open;
4406 }
4407 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304408 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004409
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004410 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
4411 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07004412 voice_set_device_mute_flag(adev, true);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004413 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07004414
Derek Chenea197282019-01-07 17:35:01 -08004415 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
4416 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08004417
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004418 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
4419 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07004420
4421 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07004422 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07004423 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4424 ALOGE("%s: pcm stream not ready", __func__);
4425 goto error_open;
4426 }
4427 ret = pcm_start(out->pcm);
4428 if (ret < 0) {
4429 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
4430 goto error_open;
4431 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07004432 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07004433 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004434 unsigned int flags = PCM_OUT;
4435 unsigned int pcm_open_retry_count = 0;
4436 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
4437 flags |= PCM_MMAP | PCM_NOIRQ;
4438 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004439 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08004440 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004441 } else
4442 flags |= PCM_MONOTONIC;
4443
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004444 if ((adev->vr_audio_mode_enabled) &&
4445 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
4446 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4447 "PCM_Dev %d Topology", out->pcm_device_id);
4448 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4449 if (!ctl) {
4450 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
4451 __func__, mixer_ctl_name);
4452 } else {
4453 //if success use ULLPP
4454 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
4455 __func__, mixer_ctl_name, out->pcm_device_id);
4456 //There is a still a possibility that some sessions
4457 // that request for FAST|RAW when 3D audio is active
4458 //can go through ULLPP. Ideally we expects apps to
4459 //listen to audio focus and stop concurrent playback
4460 //Also, we will look for mode flag (voice_in_communication)
4461 //before enabling the realtime flag.
4462 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
4463 }
4464 }
4465
Vatsal Bucha3f39f222021-06-29 16:16:55 +05304466 platform_set_stream_channel_map(adev->platform, out->channel_mask,
4467 out->pcm_device_id, -1, &out->channel_map_param.channel_map[0]);
Surendar Karka91fa3682018-07-02 18:12:12 +05304468
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004469 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
4470 flags, pcm_open_retry_count,
4471 &(out->config));
4472 if (out->pcm == NULL) {
4473 ret = -EIO;
4474 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004475 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004476
4477 if (is_haptic_usecase) {
4478 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
4479 adev->haptic_pcm_device_id,
4480 flags, pcm_open_retry_count,
4481 &(adev->haptics_config));
4482 // failure to open haptics pcm shouldnt stop audio,
4483 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07004484
4485 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
4486 ALOGD("%s: enable haptic audio synchronization", __func__);
4487 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
4488 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004489 }
4490
Zhou Song2b8f28f2017-09-11 10:51:38 +08004491 // apply volume for voip playback after path is set up
4492 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
4493 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05304494 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
4495 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304496 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
4497 out->apply_volume = false;
Derek Chenf13dd492018-11-13 14:53:51 -08004498 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
4499 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Krishna Kishor Jha10ad39f2022-02-21 17:02:47 +05304500#ifdef SOFT_VOLUME
4501 out_set_soft_volume_params(&out->stream);
4502#endif
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304503 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004504 } else {
Zhou Song79929fe2020-01-20 17:57:43 +08004505 /*
4506 * set custom channel map if:
4507 * 1. neither mono nor stereo clips i.e. channels > 2 OR
4508 * 2. custom channel map has been set by client
4509 * else default channel map of FC/FR/FL can always be set to DSP
4510 */
4511 if (popcount(out->channel_mask) > 2 || out->channel_map_param.channel_map[0])
4512 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Weiyin Jiang810a80d2021-01-18 16:04:31 +08004513 out->pcm_device_id, -1, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08004514 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
4515 adev->dsp_bit_width_enforce_mode,
4516 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004517 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07004518 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004519 out->compr = compress_open(adev->snd_card,
4520 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004521 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004522 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05304523 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05304524 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
4525 adev->card_status = CARD_STATUS_OFFLINE;
4526 out->card_status = CARD_STATUS_OFFLINE;
4527 ret = -EIO;
4528 goto error_open;
4529 }
4530
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004531 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004532 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004533 compress_close(out->compr);
4534 out->compr = NULL;
4535 ret = -EIO;
4536 goto error_open;
4537 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304538 /* compress_open sends params of the track, so reset the flag here */
4539 out->is_compr_metadata_avail = false;
4540
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004541 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004542 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07004543
Fred Oh3f43e742015-03-04 18:42:34 -08004544 /* Since small bufs uses blocking writes, a write will be blocked
4545 for the default max poll time (20s) in the event of an SSR.
4546 Reduce the poll time to observe and deal with SSR faster.
4547 */
Ashish Jain5106d362016-05-11 19:23:33 +05304548 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08004549 compress_set_max_poll_wait(out->compr, 1000);
4550 }
4551
Manish Dewangan69426c82017-01-30 17:35:36 +05304552 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05304553 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05304554
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004555 audio_extn_dts_create_state_notifier_node(out->usecase);
4556 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4557 popcount(out->channel_mask),
4558 out->playback_started);
4559
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004560#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304561 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004562 audio_extn_dolby_send_ddp_endp_params(adev);
4563#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05304564 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
4565 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004566 if (adev->visualizer_start_output != NULL)
4567 adev->visualizer_start_output(out->handle, out->pcm_device_id);
4568 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05304569 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004570 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004571 }
Derek Chenf13dd492018-11-13 14:53:51 -08004572
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004573 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf13dd492018-11-13 14:53:51 -08004574 /* Update cached volume from media to offload/direct stream */
4575 struct listnode *node = NULL;
4576 list_for_each(node, &adev->active_outputs_list) {
4577 streams_output_ctxt_t *out_ctxt = node_to_item(node,
4578 streams_output_ctxt_t,
4579 list);
4580 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
4581 out->volume_l = out_ctxt->output->volume_l;
4582 out->volume_r = out_ctxt->output->volume_r;
4583 }
4584 }
4585 out_set_compr_volume(&out->stream,
4586 out->volume_l, out->volume_r);
4587 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004588 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004589
4590 if (ret == 0) {
Vaibhav Raut5f3bf222023-02-06 17:45:22 +05304591 if (out->flags & (AUDIO_OUTPUT_FLAG_FAST | AUDIO_OUTPUT_FLAG_RAW))
Narsinga Rao Chellaa6e1f702021-10-22 13:57:32 +05304592 register_out_stream(out);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004593 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07004594 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4595 ALOGE("%s: pcm stream not ready", __func__);
4596 goto error_open;
4597 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004598 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004599 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004600 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004601 if (ret < 0)
4602 goto error_open;
4603 }
4604 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004605 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304606 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Jaideep Sharma0fa53812020-09-17 09:00:11 +05304607 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004608
vivek mehtad15d2bf2019-05-17 13:35:10 -07004609 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
4610 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4611 audio_low_latency_hint_start();
4612 }
4613
Manish Dewangan21a850a2017-08-14 12:03:55 +05304614 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07004615 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07004616 if (ret < 0)
4617 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
4618 }
4619
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004620 // consider a scenario where on pause lower layers are tear down.
4621 // so on resume, swap mixer control need to be sent only when
4622 // backend is active, hence rather than sending from enable device
4623 // sending it from start of streamtream
4624
4625 platform_set_swap_channels(adev, true);
4626
Haynes Mathew George380745d2017-10-04 15:27:45 -07004627 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304628 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004629 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004630error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004631 if (adev->haptic_pcm) {
4632 pcm_close(adev->haptic_pcm);
4633 adev->haptic_pcm = NULL;
4634 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004635 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304636 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004637 stop_output_stream(out);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004638error_fatal:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05304639 /*
4640 * sleep 50ms to allow sufficient time for kernel
4641 * drivers to recover incases like SSR.
4642 */
4643 usleep(50000);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004644error_config:
Haynes Mathew George380745d2017-10-04 15:27:45 -07004645 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304646 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004647 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004648}
4649
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004650static int check_input_parameters(uint32_t sample_rate,
4651 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08004652 int channel_count,
4653 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004654{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004655 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004656
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304657 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
4658 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
4659 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07004660 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02004661 !audio_extn_compr_cap_format_supported(format) &&
4662 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004663 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004664
Aalique Grahame22e49102018-12-18 14:23:57 -08004665 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
4666 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
4667 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
4668 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
4669 return -EINVAL;
4670 }
4671
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004672 switch (channel_count) {
4673 case 1:
4674 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304675 case 3:
4676 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004677 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07004678 case 8:
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05304679 case 10:
4680 case 12:
4681 case 14:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004682 break;
4683 default:
4684 ret = -EINVAL;
4685 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004686
4687 switch (sample_rate) {
4688 case 8000:
4689 case 11025:
4690 case 12000:
4691 case 16000:
4692 case 22050:
4693 case 24000:
4694 case 32000:
4695 case 44100:
4696 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004697 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304698 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004699 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304700 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004701 break;
4702 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004703 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004704 }
4705
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004706 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004707}
4708
Naresh Tanniru04f71882018-06-26 17:46:22 +05304709
4710/** Add a value in a list if not already present.
4711 * @return true if value was successfully inserted or already present,
4712 * false if the list is full and does not contain the value.
4713 */
4714static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
4715 for (size_t i = 0; i < list_length; i++) {
4716 if (list[i] == value) return true; // value is already present
4717 if (list[i] == 0) { // no values in this slot
4718 list[i] = value;
4719 return true; // value inserted
4720 }
4721 }
4722 return false; // could not insert value
4723}
4724
4725/** Add channel_mask in supported_channel_masks if not already present.
4726 * @return true if channel_mask was successfully inserted or already present,
4727 * false if supported_channel_masks is full and does not contain channel_mask.
4728 */
4729static void register_channel_mask(audio_channel_mask_t channel_mask,
4730 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
4731 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
4732 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
4733}
4734
4735/** Add format in supported_formats if not already present.
4736 * @return true if format was successfully inserted or already present,
4737 * false if supported_formats is full and does not contain format.
4738 */
4739static void register_format(audio_format_t format,
4740 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
4741 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
4742 "%s: stream can not declare supporting its format %x", __func__, format);
4743}
4744/** Add sample_rate in supported_sample_rates if not already present.
4745 * @return true if sample_rate was successfully inserted or already present,
4746 * false if supported_sample_rates is full and does not contain sample_rate.
4747 */
4748static void register_sample_rate(uint32_t sample_rate,
4749 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
4750 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
4751 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
4752}
4753
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004754static inline uint32_t lcm(uint32_t num1, uint32_t num2)
4755{
4756 uint32_t high = num1, low = num2, temp = 0;
4757
4758 if (!num1 || !num2)
4759 return 0;
4760
4761 if (num1 < num2) {
4762 high = num2;
4763 low = num1;
4764 }
4765
4766 while (low != 0) {
4767 temp = low;
4768 low = high % low;
4769 high = temp;
4770 }
4771 return (num1 * num2)/high;
4772}
4773
4774static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
4775{
4776 uint32_t remainder = 0;
4777
4778 if (!multiplier)
4779 return num;
4780
4781 remainder = num % multiplier;
4782 if (remainder)
4783 num += (multiplier - remainder);
4784
4785 return num;
4786}
4787
Aalique Grahame22e49102018-12-18 14:23:57 -08004788static size_t get_stream_buffer_size(size_t duration_ms,
4789 uint32_t sample_rate,
4790 audio_format_t format,
4791 int channel_count,
4792 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004793{
4794 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004795 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004796
Aalique Grahame22e49102018-12-18 14:23:57 -08004797 size = (sample_rate * duration_ms) / 1000;
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +05304798 if (is_low_latency){
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +05304799#ifndef PLATFORM_AUTO
4800 size = configured_low_latency_capture_period_size;
4801#else
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +05304802 switch(sample_rate) {
4803 case 48000:
4804 size = 240;
4805 break;
4806 case 32000:
4807 size = 160;
4808 break;
4809 case 24000:
4810 size = 120;
4811 break;
4812 case 16000:
4813 size = 80;
4814 break;
4815 case 8000:
4816 size = 40;
4817 break;
4818 default:
4819 size = 240;
4820 }
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +05304821#endif
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +05304822 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304823
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004824 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08004825 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004826
Ralf Herzbd08d632018-09-28 15:50:49 +02004827 /* make sure the size is multiple of 32 bytes and additionally multiple of
4828 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004829 * At 48 kHz mono 16-bit PCM:
4830 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
4831 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004832 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004833 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004834 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07004835
4836 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004837}
4838
Aalique Grahame22e49102018-12-18 14:23:57 -08004839static size_t get_input_buffer_size(uint32_t sample_rate,
4840 audio_format_t format,
4841 int channel_count,
4842 bool is_low_latency)
4843{
Avinash Chandrad7296d42021-08-04 15:07:47 +05304844 bool is_usb_hifi = IS_USB_HIFI;
Aalique Grahame22e49102018-12-18 14:23:57 -08004845 /* Don't know if USB HIFI in this context so use true to be conservative */
4846 if (check_input_parameters(sample_rate, format, channel_count,
Avinash Chandrad7296d42021-08-04 15:07:47 +05304847 is_usb_hifi) != 0)
Aalique Grahame22e49102018-12-18 14:23:57 -08004848 return 0;
4849
4850 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4851 sample_rate,
4852 format,
4853 channel_count,
4854 is_low_latency);
4855}
4856
Derek Chenf6318be2017-06-12 17:16:24 -04004857size_t get_output_period_size(uint32_t sample_rate,
4858 audio_format_t format,
4859 int channel_count,
4860 int duration /*in millisecs*/)
Ashish Jain058165c2016-09-28 23:18:48 +05304861{
4862 size_t size = 0;
4863 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
4864
4865 if ((duration == 0) || (sample_rate == 0) ||
4866 (bytes_per_sample == 0) || (channel_count == 0)) {
4867 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
4868 bytes_per_sample, channel_count);
4869 return -EINVAL;
4870 }
4871
4872 size = (sample_rate *
4873 duration *
4874 bytes_per_sample *
4875 channel_count) / 1000;
4876 /*
4877 * To have same PCM samples for all channels, the buffer size requires to
4878 * be multiple of (number of channels * bytes per sample)
4879 * For writes to succeed, the buffer must be written at address which is multiple of 32
4880 */
4881 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
4882
4883 return (size/(channel_count * bytes_per_sample));
4884}
4885
Zhou Song48453a02018-01-10 17:50:59 +08004886static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05304887{
4888 uint64_t actual_frames_rendered = 0;
Weiyin Jiang4813da12020-05-28 00:37:28 +08004889 uint64_t written_frames = 0;
4890 uint64_t kernel_frames = 0;
4891 uint64_t dsp_frames = 0;
4892 uint64_t signed_frames = 0;
4893 size_t kernel_buffer_size = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304894
4895 /* This adjustment accounts for buffering after app processor.
4896 * It is based on estimated DSP latency per use case, rather than exact.
4897 */
George Gao9ba8a142020-07-23 14:30:03 -07004898 dsp_frames = platform_render_latency(out) *
Weiyin Jiang4813da12020-05-28 00:37:28 +08004899 out->sample_rate / 1000000LL;
Ashish Jain5106d362016-05-11 19:23:33 +05304900
Zhou Song48453a02018-01-10 17:50:59 +08004901 pthread_mutex_lock(&out->position_query_lock);
Weiyin Jiang4813da12020-05-28 00:37:28 +08004902 written_frames = out->written /
4903 (audio_bytes_per_sample(out->hal_ip_format) * popcount(out->channel_mask));
4904
Ashish Jain5106d362016-05-11 19:23:33 +05304905 /* not querying actual state of buffering in kernel as it would involve an ioctl call
4906 * which then needs protection, this causes delay in TS query for pcm_offload usecase
4907 * hence only estimate.
4908 */
Weiyin Jiang4813da12020-05-28 00:37:28 +08004909 kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
4910 kernel_frames = kernel_buffer_size /
4911 (audio_bytes_per_sample(out->hal_op_format) * popcount(out->channel_mask));
Ashish Jain5106d362016-05-11 19:23:33 +05304912
Weiyin Jiang4813da12020-05-28 00:37:28 +08004913 if (written_frames >= (kernel_frames + dsp_frames))
4914 signed_frames = written_frames - kernel_frames - dsp_frames;
Ashish Jain5106d362016-05-11 19:23:33 +05304915
Zhou Song48453a02018-01-10 17:50:59 +08004916 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05304917 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08004918 if (timestamp != NULL )
4919 *timestamp = out->writeAt;
4920 } else if (timestamp != NULL) {
4921 clock_gettime(CLOCK_MONOTONIC, timestamp);
4922 }
4923 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304924
Weiyin Jiang4813da12020-05-28 00:37:28 +08004925 ALOGVV("%s signed frames %lld written frames %lld kernel frames %lld dsp frames %lld",
4926 __func__, signed_frames, written_frames, kernel_frames, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05304927
4928 return actual_frames_rendered;
4929}
4930
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004931static uint32_t out_get_sample_rate(const struct audio_stream *stream)
4932{
4933 struct stream_out *out = (struct stream_out *)stream;
4934
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004935 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004936}
4937
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004938static int out_set_sample_rate(struct audio_stream *stream __unused,
4939 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004940{
4941 return -ENOSYS;
4942}
4943
4944static size_t out_get_buffer_size(const struct audio_stream *stream)
4945{
4946 struct stream_out *out = (struct stream_out *)stream;
4947
Varun Balaraje49253e2017-07-06 19:48:56 +05304948 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05304949 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05304950 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304951 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4952 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
4953 else
4954 return out->compr_config.fragment_size;
4955 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004956 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304957 else if (is_offload_usecase(out->usecase) &&
4958 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304959 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004960
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004961 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004962 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004963}
4964
4965static uint32_t out_get_channels(const struct audio_stream *stream)
4966{
4967 struct stream_out *out = (struct stream_out *)stream;
4968
4969 return out->channel_mask;
4970}
4971
4972static audio_format_t out_get_format(const struct audio_stream *stream)
4973{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004974 struct stream_out *out = (struct stream_out *)stream;
4975
4976 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004977}
4978
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004979static int out_set_format(struct audio_stream *stream __unused,
4980 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004981{
4982 return -ENOSYS;
4983}
4984
4985static int out_standby(struct audio_stream *stream)
4986{
4987 struct stream_out *out = (struct stream_out *)stream;
4988 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07004989 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004990
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304991 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4992 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004993
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004994 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004995 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004996 if (adev->adm_deregister_stream)
4997 adev->adm_deregister_stream(adev->adm_data, out->handle);
4998
Weiyin Jiang280ea742020-09-08 20:28:22 +08004999 if (is_offload_usecase(out->usecase)) {
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07005000 stop_compressed_output_l(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08005001 }
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07005002
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08005003 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005004 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08005005 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
5006 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305007 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08005008 pthread_mutex_unlock(&adev->lock);
5009 pthread_mutex_unlock(&out->lock);
5010 ALOGD("VOIP output entered standby");
5011 return 0;
5012 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005013 if (out->pcm) {
5014 pcm_close(out->pcm);
5015 out->pcm = NULL;
5016 }
Meng Wanga09da002020-04-20 12:56:04 +08005017 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
5018 if (adev->haptic_pcm) {
5019 pcm_close(adev->haptic_pcm);
5020 adev->haptic_pcm = NULL;
5021 }
5022
5023 if (adev->haptic_buffer != NULL) {
5024 free(adev->haptic_buffer);
5025 adev->haptic_buffer = NULL;
5026 adev->haptic_buffer_size = 0;
5027 }
5028 adev->haptic_pcm_device_id = 0;
5029 }
5030
Haynes Mathew George16081042017-05-31 17:16:49 -07005031 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5032 do_stop = out->playback_started;
5033 out->playback_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07005034
5035 if (out->mmap_shared_memory_fd >= 0) {
5036 ALOGV("%s: closing mmap_shared_memory_fd = %d",
5037 __func__, out->mmap_shared_memory_fd);
5038 close(out->mmap_shared_memory_fd);
5039 out->mmap_shared_memory_fd = -1;
5040 }
Haynes Mathew George16081042017-05-31 17:16:49 -07005041 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005042 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005043 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305044 out->send_next_track_params = false;
5045 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005046 out->gapless_mdata.encoder_delay = 0;
5047 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005048 if (out->compr != NULL) {
5049 compress_close(out->compr);
5050 out->compr = NULL;
5051 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08005052 }
Haynes Mathew George16081042017-05-31 17:16:49 -07005053 if (do_stop) {
5054 stop_output_stream(out);
5055 }
Lakshman Chaluvaraju06677b42019-06-24 10:04:52 +05305056 // if fm is active route on selected device in UI
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005057 audio_extn_fm_route_on_selected_device(adev, &out->device_list);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005058 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005059 }
5060 pthread_mutex_unlock(&out->lock);
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07005061 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005062 return 0;
5063}
5064
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305065static int out_on_error(struct audio_stream *stream)
5066{
5067 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07005068 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305069
5070 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08005071 // always send CMD_ERROR for offload streams, this
5072 // is needed e.g. when SSR happens within compress_open
5073 // since the stream is active, offload_callback_thread is also active.
5074 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
5075 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07005076 }
5077 pthread_mutex_unlock(&out->lock);
5078
5079 status = out_standby(&out->stream.common);
5080
5081 lock_output_stream(out);
5082 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08005083 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305084 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05305085
5086 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
5087 ALOGD("Setting previous card status if offline");
5088 out->prev_card_status_offline = true;
5089 }
5090
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305091 pthread_mutex_unlock(&out->lock);
5092
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07005093 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305094}
5095
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305096/*
Weiyin Jiang280ea742020-09-08 20:28:22 +08005097 * standby implementation without locks, assumes that the callee already
5098 * has taken adev and out lock.
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305099 */
5100int out_standby_l(struct audio_stream *stream)
5101{
5102 struct stream_out *out = (struct stream_out *)stream;
5103 struct audio_device *adev = out->dev;
5104
5105 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
5106 stream, out->usecase, use_case_table[out->usecase]);
5107
5108 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07005109 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305110 if (adev->adm_deregister_stream)
5111 adev->adm_deregister_stream(adev->adm_data, out->handle);
5112
Weiyin Jiang280ea742020-09-08 20:28:22 +08005113 if (is_offload_usecase(out->usecase)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305114 stop_compressed_output_l(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08005115 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305116
5117 out->standby = true;
5118 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
5119 voice_extn_compress_voip_close_output_stream(stream);
5120 out->started = 0;
5121 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07005122 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305123 return 0;
5124 } else if (!is_offload_usecase(out->usecase)) {
5125 if (out->pcm) {
5126 pcm_close(out->pcm);
5127 out->pcm = NULL;
5128 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005129 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
5130 if (adev->haptic_pcm) {
5131 pcm_close(adev->haptic_pcm);
5132 adev->haptic_pcm = NULL;
5133 }
5134
5135 if (adev->haptic_buffer != NULL) {
5136 free(adev->haptic_buffer);
5137 adev->haptic_buffer = NULL;
5138 adev->haptic_buffer_size = 0;
5139 }
5140 adev->haptic_pcm_device_id = 0;
5141 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305142 } else {
5143 ALOGD("copl(%p):standby", out);
5144 out->send_next_track_params = false;
5145 out->is_compr_metadata_avail = false;
5146 out->gapless_mdata.encoder_delay = 0;
5147 out->gapless_mdata.encoder_padding = 0;
5148 if (out->compr != NULL) {
5149 compress_close(out->compr);
5150 out->compr = NULL;
5151 }
5152 }
5153 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005154 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305155 }
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07005156 ALOGV("%s: exit", __func__);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305157 return 0;
5158}
5159
Aalique Grahame22e49102018-12-18 14:23:57 -08005160static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005161{
Aalique Grahame22e49102018-12-18 14:23:57 -08005162 struct stream_out *out = (struct stream_out *)stream;
5163
5164 // We try to get the lock for consistency,
5165 // but it isn't necessary for these variables.
5166 // If we're not in standby, we may be blocked on a write.
5167 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
5168 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
5169 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
Dechen Chai22768452021-07-30 09:29:16 +05305170#ifndef LINUX_ENABLED
Andy Hunga1f48fa2019-07-01 18:14:53 -07005171 char buffer[256]; // for statistics formatting
5172 if (!is_offload_usecase(out->usecase)) {
5173 simple_stats_to_string(&out->fifo_underruns, buffer, sizeof(buffer));
5174 dprintf(fd, " Fifo frame underruns: %s\n", buffer);
5175 }
5176
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005177 if (out->start_latency_ms.n > 0) {
5178 simple_stats_to_string(&out->start_latency_ms, buffer, sizeof(buffer));
5179 dprintf(fd, " Start latency ms: %s\n", buffer);
5180 }
Dechen Chai22768452021-07-30 09:29:16 +05305181#endif
Aalique Grahame22e49102018-12-18 14:23:57 -08005182 if (locked) {
5183 pthread_mutex_unlock(&out->lock);
5184 }
5185
Dechen Chai22768452021-07-30 09:29:16 +05305186#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -08005187 // dump error info
5188 (void)error_log_dump(
5189 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Dechen Chai22768452021-07-30 09:29:16 +05305190#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005191 return 0;
5192}
5193
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005194static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
5195{
5196 int ret = 0;
5197 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08005198
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005199 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08005200 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005201 return -EINVAL;
5202 }
5203
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05305204 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08005205
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005206 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
5207 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05305208 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005209 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005210 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
5211 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05305212 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005213 }
5214
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005215 ALOGV("%s new encoder delay %u and padding %u", __func__,
5216 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
5217
5218 return 0;
5219}
5220
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005221static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
5222{
5223 return out == adev->primary_output || out == adev->voice_tx_output;
5224}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005225
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305226// note: this call is safe only if the stream_cb is
5227// removed first in close_output_stream (as is done now).
5228static void out_snd_mon_cb(void * stream, struct str_parms * parms)
5229{
5230 if (!stream || !parms)
5231 return;
5232
5233 struct stream_out *out = (struct stream_out *)stream;
5234 struct audio_device *adev = out->dev;
5235
5236 card_status_t status;
5237 int card;
5238 if (parse_snd_card_status(parms, &card, &status) < 0)
5239 return;
5240
5241 pthread_mutex_lock(&adev->lock);
5242 bool valid_cb = (card == adev->snd_card);
5243 pthread_mutex_unlock(&adev->lock);
5244
5245 if (!valid_cb)
5246 return;
5247
5248 lock_output_stream(out);
5249 if (out->card_status != status)
5250 out->card_status = status;
5251 pthread_mutex_unlock(&out->lock);
5252
5253 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
5254 use_case_table[out->usecase],
5255 status == CARD_STATUS_OFFLINE ? "offline" : "online");
5256
Aditya Bavanari59ebed42019-02-05 17:44:57 +05305257 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305258 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05305259 if (voice_is_call_state_active(adev) &&
5260 out == adev->primary_output) {
5261 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
5262 pthread_mutex_lock(&adev->lock);
5263 voice_stop_call(adev);
5264 adev->mode = AUDIO_MODE_NORMAL;
5265 pthread_mutex_unlock(&adev->lock);
5266 }
5267 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305268 return;
5269}
5270
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005271int route_output_stream(struct stream_out *out,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005272 struct listnode *devices)
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005273{
5274 struct audio_device *adev = out->dev;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005275 int ret = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005276 struct listnode new_devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005277 bool bypass_a2dp = false;
5278 bool reconfig = false;
5279 unsigned long service_interval = 0;
5280
5281 ALOGD("%s: enter: usecase(%d: %s) devices %x",
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005282 __func__, out->usecase, use_case_table[out->usecase], get_device_types(devices));
5283
5284 list_init(&new_devices);
5285 assign_devices(&new_devices, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005286
5287 lock_output_stream(out);
5288 pthread_mutex_lock(&adev->lock);
5289
5290 /*
5291 * When HDMI cable is unplugged the music playback is paused and
5292 * the policy manager sends routing=0. But the audioflinger continues
5293 * to write data until standby time (3sec). As the HDMI core is
5294 * turned off, the write gets blocked.
5295 * Avoid this by routing audio to speaker until standby.
5296 */
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08005297 if (is_single_device_type_equal(&out->device_list,
5298 AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005299 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005300 !audio_extn_passthru_is_passthrough_stream(out) &&
5301 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005302 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005303 }
5304 /*
5305 * When A2DP is disconnected the
5306 * music playback is paused and the policy manager sends routing=0
5307 * But the audioflinger continues to write data until standby time
5308 * (3sec). As BT is turned off, the write gets blocked.
5309 * Avoid this by routing audio to speaker until standby.
5310 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005311 if (is_a2dp_out_device_type(&out->device_list) &&
5312 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005313 !audio_extn_a2dp_source_is_ready() &&
5314 !adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005315 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005316 }
5317 /*
Weiyin Jiangabedea32020-12-09 12:49:19 +08005318 * When USB headset is disconnected the music playback paused
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005319 * and the policy manager send routing=0. But if the USB is connected
5320 * back before the standby time, AFE is not closed and opened
5321 * when USB is connected back. So routing to speker will guarantee
5322 * AFE reconfiguration and AFE will be opend once USB is connected again
5323 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005324 if (is_usb_out_device_type(&out->device_list) &&
5325 list_empty(&new_devices) &&
5326 !audio_extn_usb_connected(NULL)) {
Sujin Panicker84d953a2020-11-16 17:39:54 +05305327 if (adev->mode == AUDIO_MODE_IN_CALL || adev->mode == AUDIO_MODE_IN_COMMUNICATION)
5328 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_EARPIECE, "");
5329 else
5330 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005331 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005332 /* To avoid a2dp to sco overlapping / BT device improper state
5333 * check with BT lib about a2dp streaming support before routing
5334 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005335 if (is_a2dp_out_device_type(&new_devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005336 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005337 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER) ||
5338 compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005339 //combo usecase just by pass a2dp
5340 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
5341 bypass_a2dp = true;
5342 } else {
5343 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
5344 /* update device to a2dp and don't route as BT returned error
5345 * However it is still possible a2dp routing called because
5346 * of current active device disconnection (like wired headset)
5347 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005348 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005349 pthread_mutex_unlock(&adev->lock);
5350 pthread_mutex_unlock(&out->lock);
5351 goto error;
5352 }
5353 }
5354 }
5355
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005356 // Workaround: If routing to an non existing usb device, fail gracefully
5357 // The routing request will otherwise block during 10 second
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005358 if (is_usb_out_device_type(&new_devices)) {
5359 struct str_parms *parms =
5360 str_parms_create_str(get_usb_device_address(&new_devices));
5361 if (!parms)
5362 goto error;
Weiyin Jiangabedea32020-12-09 12:49:19 +08005363 if (!audio_extn_usb_connected(NULL)) {
5364 ALOGW("%s: ignoring rerouting to non existing USB card", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005365 pthread_mutex_unlock(&adev->lock);
5366 pthread_mutex_unlock(&out->lock);
5367 str_parms_destroy(parms);
5368 ret = -ENOSYS;
5369 goto error;
5370 }
5371 str_parms_destroy(parms);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005372 }
5373
Weiyin Jiang80c8f9a2020-01-10 20:42:08 +08005374 // Workaround: If routing to an non existing hdmi device, fail gracefully
5375 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
5376 (platform_get_edid_info_v2(adev->platform,
5377 out->extconn.cs.controller,
5378 out->extconn.cs.stream) != 0)) {
5379 ALOGW("out_set_parameters() ignoring rerouting to non existing HDMI/DP");
5380 pthread_mutex_unlock(&adev->lock);
5381 pthread_mutex_unlock(&out->lock);
5382 ret = -ENOSYS;
5383 goto error;
5384 }
5385
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005386 /*
5387 * select_devices() call below switches all the usecases on the same
5388 * backend to the new device. Refer to check_usecases_codec_backend() in
5389 * the select_devices(). But how do we undo this?
5390 *
5391 * For example, music playback is active on headset (deep-buffer usecase)
5392 * and if we go to ringtones and select a ringtone, low-latency usecase
5393 * will be started on headset+speaker. As we can't enable headset+speaker
5394 * and headset devices at the same time, select_devices() switches the music
5395 * playback to headset+speaker while starting low-lateny usecase for ringtone.
5396 * So when the ringtone playback is completed, how do we undo the same?
5397 *
5398 * We are relying on the out_set_parameters() call on deep-buffer output,
5399 * once the ringtone playback is ended.
5400 * NOTE: We should not check if the current devices are same as new devices.
5401 * Because select_devices() must be called to switch back the music
5402 * playback to headset.
5403 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005404 if (!list_empty(&new_devices)) {
5405 bool same_dev = compare_devices(&out->device_list, &new_devices);
5406 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005407
5408 if (output_drives_call(adev, out)) {
5409 if (!voice_is_call_state_active(adev)) {
5410 if (adev->mode == AUDIO_MODE_IN_CALL) {
5411 adev->current_call_output = out;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005412 ret = voice_start_call(adev);
5413 }
5414 } else {
Kunlei Zhang253ad102020-10-14 16:21:28 +08005415 platform_is_volume_boost_supported_device(adev->platform, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005416 adev->current_call_output = out;
5417 voice_update_devices_for_all_voice_usecases(adev);
5418 }
5419 }
5420
Mingshu Pang971ff702020-09-09 15:28:22 +08005421 if (is_usb_out_device_type(&out->device_list)) {
5422 service_interval = audio_extn_usb_find_service_interval(false, true /*playback*/);
5423 audio_extn_usb_set_service_interval(true /*playback*/,
5424 service_interval,
5425 &reconfig);
5426 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
5427 }
5428
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005429 if (!out->standby) {
5430 if (!same_dev) {
5431 ALOGV("update routing change");
5432 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
5433 adev->perf_lock_opts,
5434 adev->perf_lock_opts_size);
5435 if (adev->adm_on_routing_change)
5436 adev->adm_on_routing_change(adev->adm_data,
5437 out->handle);
5438 }
5439 if (!bypass_a2dp) {
5440 select_devices(adev, out->usecase);
5441 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005442 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
5443 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005444 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005445 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005446 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005447 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005448 }
5449
5450 if (!same_dev) {
5451 // on device switch force swap, lower functions will make sure
5452 // to check if swap is allowed or not.
5453 platform_set_swap_channels(adev, true);
5454 audio_extn_perf_lock_release(&adev->perf_lock_handle);
5455 }
Zhou Songbaddf9f2020-11-20 13:57:39 +08005456 pthread_mutex_lock(&out->latch_lock);
5457 if (!is_a2dp_out_device_type(&out->device_list) || audio_extn_a2dp_source_is_ready()) {
5458 if (out->a2dp_muted) {
5459 out->a2dp_muted = false;
5460 if (is_offload_usecase(out->usecase))
5461 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5462 else if (out->usecase != USECASE_AUDIO_PLAYBACK_VOIP)
5463 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Weiyin Jiang280ea742020-09-08 20:28:22 +08005464 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005465 }
Zhou Songbaddf9f2020-11-20 13:57:39 +08005466 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP && !out->a2dp_muted)
5467 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
5468 pthread_mutex_unlock(&out->latch_lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005469 }
5470 }
5471
5472 pthread_mutex_unlock(&adev->lock);
5473 pthread_mutex_unlock(&out->lock);
5474
5475 /*handles device and call state changes*/
5476 audio_extn_extspk_update(adev->extspk);
5477
Revathi Uddaraju4255a632021-12-02 05:11:13 -08005478 clear_devices(&new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005479error:
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005480 ALOGV("%s: exit: code(%d)", __func__, ret);
5481 return ret;
5482}
5483
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005484static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
5485{
5486 struct stream_out *out = (struct stream_out *)stream;
5487 struct audio_device *adev = out->dev;
5488 struct str_parms *parms;
5489 char value[32];
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005490 int ret = 0, err;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005491 int ext_controller = -1;
5492 int ext_stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005493
sangwoobc677242013-08-08 16:53:43 +09005494 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005495 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005496 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305497 if (!parms)
5498 goto error;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005499
5500 err = platform_get_controller_stream_from_params(parms, &ext_controller,
5501 &ext_stream);
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08005502 if (err == 0) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005503 out->extconn.cs.controller = ext_controller;
5504 out->extconn.cs.stream = ext_stream;
5505 ALOGD("%s: usecase(%s) new controller/stream (%d/%d)", __func__,
5506 use_case_table[out->usecase], out->extconn.cs.controller,
5507 out->extconn.cs.stream);
5508 }
5509
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005510 if (out == adev->primary_output) {
5511 pthread_mutex_lock(&adev->lock);
5512 audio_extn_set_parameters(adev, parms);
5513 pthread_mutex_unlock(&adev->lock);
5514 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005515 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005516 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005517 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005518
5519 audio_extn_dts_create_state_notifier_node(out->usecase);
5520 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5521 popcount(out->channel_mask),
5522 out->playback_started);
5523
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08005524 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005525 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005526
Surendar Karkaf51b5842018-04-26 11:28:38 +05305527 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
5528 sizeof(value));
5529 if (err >= 0) {
5530 if (!strncmp("true", value, sizeof("true")) || atoi(value))
5531 audio_extn_send_dual_mono_mixing_coefficients(out);
5532 }
5533
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305534 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5535 if (err >= 0) {
5536 strlcpy(out->profile, value, sizeof(out->profile));
5537 ALOGV("updating stream profile with value '%s'", out->profile);
5538 lock_output_stream(out);
5539 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
5540 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005541 &out->device_list, out->flags,
5542 out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305543 out->sample_rate, out->bit_width,
5544 out->channel_mask, out->profile,
5545 &out->app_type_cfg);
5546 pthread_mutex_unlock(&out->lock);
5547 }
5548
Alexy Joseph98988832017-01-13 14:56:59 -08005549 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005550 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
5551 // and vendor.audio.hal.output.suspend.supported is set to true
5552 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08005553 //check suspend parameter only for low latency and if the property
5554 //is enabled
5555 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
5556 ALOGI("%s: got suspend_playback %s", __func__, value);
5557 lock_output_stream(out);
5558 if (!strncmp(value, "false", 5)) {
5559 //suspend_playback=false is supposed to set QOS value back to 75%
5560 //the mixer control sent with value Enable will achieve that
5561 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5562 } else if (!strncmp (value, "true", 4)) {
5563 //suspend_playback=true is supposed to remove QOS value
5564 //resetting the mixer control will set the default value
5565 //for the mixer control which is Disable and this removes the QOS vote
5566 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5567 } else {
5568 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
5569 " got %s", __func__, value);
5570 ret = -1;
5571 }
5572
5573 if (ret != 0) {
5574 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
5575 __func__, out->pm_qos_mixer_path, ret);
5576 }
5577
5578 pthread_mutex_unlock(&out->lock);
5579 }
5580 }
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005581
Alexy Joseph98988832017-01-13 14:56:59 -08005582 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005583 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305584error:
Eric Laurent994a6932013-07-17 11:51:42 -07005585 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005586 return ret;
5587}
5588
Paul McLeana50b7332018-12-17 08:24:21 -07005589static int in_set_microphone_direction(const struct audio_stream_in *stream,
5590 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07005591 struct stream_in *in = (struct stream_in *)stream;
5592
5593 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
5594
5595 in->direction = dir;
5596
5597 if (in->standby)
5598 return 0;
5599
5600 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07005601}
5602
5603static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07005604 struct stream_in *in = (struct stream_in *)stream;
5605
5606 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
5607
5608 if (zoom > 1.0 || zoom < -1.0)
5609 return -EINVAL;
5610
5611 in->zoom = zoom;
5612
5613 if (in->standby)
5614 return 0;
5615
5616 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07005617}
5618
5619
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005620static bool stream_get_parameter_channels(struct str_parms *query,
5621 struct str_parms *reply,
5622 audio_channel_mask_t *supported_channel_masks) {
5623 int ret = -1;
5624 char value[512];
5625 bool first = true;
5626 size_t i, j;
5627
5628 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
5629 ret = 0;
5630 value[0] = '\0';
5631 i = 0;
5632 while (supported_channel_masks[i] != 0) {
5633 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5634 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
5635 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305636 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005637
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305638 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005639 first = false;
5640 break;
5641 }
5642 }
5643 i++;
5644 }
5645 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5646 }
5647 return ret == 0;
5648}
5649
5650static bool stream_get_parameter_formats(struct str_parms *query,
5651 struct str_parms *reply,
5652 audio_format_t *supported_formats) {
5653 int ret = -1;
5654 char value[256];
5655 size_t i, j;
5656 bool first = true;
5657
5658 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
5659 ret = 0;
5660 value[0] = '\0';
5661 i = 0;
5662 while (supported_formats[i] != 0) {
5663 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5664 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
5665 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305666 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005667 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305668 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005669 first = false;
5670 break;
5671 }
5672 }
5673 i++;
5674 }
5675 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
5676 }
5677 return ret == 0;
5678}
5679
5680static bool stream_get_parameter_rates(struct str_parms *query,
5681 struct str_parms *reply,
5682 uint32_t *supported_sample_rates) {
5683
5684 int i;
5685 char value[256];
5686 int ret = -1;
5687 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
5688 ret = 0;
5689 value[0] = '\0';
5690 i=0;
5691 int cursor = 0;
5692 while (supported_sample_rates[i]) {
5693 int avail = sizeof(value) - cursor;
5694 ret = snprintf(value + cursor, avail, "%s%d",
5695 cursor > 0 ? "|" : "",
5696 supported_sample_rates[i]);
5697 if (ret < 0 || ret >= avail) {
5698 // if cursor is at the last element of the array
5699 // overwrite with \0 is duplicate work as
5700 // snprintf already put a \0 in place.
5701 // else
5702 // we had space to write the '|' at value[cursor]
5703 // (which will be overwritten) or no space to fill
5704 // the first element (=> cursor == 0)
5705 value[cursor] = '\0';
5706 break;
5707 }
5708 cursor += ret;
5709 ++i;
5710 }
5711 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
5712 value);
5713 }
5714 return ret >= 0;
5715}
5716
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005717static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
5718{
5719 struct stream_out *out = (struct stream_out *)stream;
5720 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005721 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005722 char value[256];
5723 struct str_parms *reply = str_parms_create();
5724 size_t i, j;
5725 int ret;
5726 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005727
5728 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005729 if (reply) {
5730 str_parms_destroy(reply);
5731 }
5732 if (query) {
5733 str_parms_destroy(query);
5734 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005735 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
5736 return NULL;
5737 }
5738
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005739 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005740 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
5741 if (ret >= 0) {
5742 value[0] = '\0';
5743 i = 0;
5744 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005745 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5746 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005747 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005748 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005749 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005750 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005751 first = false;
5752 break;
5753 }
5754 }
5755 i++;
5756 }
5757 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5758 str = str_parms_to_str(reply);
5759 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005760 voice_extn_out_get_parameters(out, query, reply);
5761 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005762 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005763
Alexy Joseph62142aa2015-11-16 15:10:34 -08005764
5765 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
5766 if (ret >= 0) {
5767 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05305768 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
5769 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08005770 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305771 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005772 } else {
5773 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05305774 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005775 }
5776 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005777 if (str)
5778 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08005779 str = str_parms_to_str(reply);
5780 }
5781
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005782 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
5783 if (ret >= 0) {
5784 value[0] = '\0';
5785 i = 0;
5786 first = true;
5787 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005788 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5789 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005790 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005791 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005792 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005793 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005794 first = false;
5795 break;
5796 }
5797 }
5798 i++;
5799 }
5800 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005801 if (str)
5802 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005803 str = str_parms_to_str(reply);
5804 }
Mingming Yin3a941d42016-02-17 18:08:05 -08005805
5806 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
5807 if (ret >= 0) {
5808 value[0] = '\0';
5809 i = 0;
5810 first = true;
5811 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005812 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
5813 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005814 if (!first) {
5815 strlcat(value, "|", sizeof(value));
5816 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005817 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08005818 first = false;
5819 break;
5820 }
5821 }
5822 i++;
5823 }
5824 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
5825 if (str)
5826 free(str);
5827 str = str_parms_to_str(reply);
5828 }
5829
Alexy Joseph98988832017-01-13 14:56:59 -08005830 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
5831 //only low latency track supports suspend_resume
5832 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005833 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08005834 if (str)
5835 free(str);
5836 str = str_parms_to_str(reply);
5837 }
5838
5839
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005840 str_parms_destroy(query);
5841 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07005842 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005843 return str;
5844}
5845
5846static uint32_t out_get_latency(const struct audio_stream_out *stream)
5847{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005848 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005849 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08005850 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005851
Alexy Josephaa54c872014-12-03 02:46:47 -08005852 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05305853 lock_output_stream(out);
5854 latency = audio_extn_utils_compress_get_dsp_latency(out);
5855 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005856 } else if ((out->realtime) ||
5857 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005858 // since the buffer won't be filled up faster than realtime,
5859 // return a smaller number
5860 if (out->config.rate)
5861 period_ms = (out->af_period_multiplier * out->config.period_size *
5862 1000) / (out->config.rate);
5863 else
5864 period_ms = 0;
George Gao9ba8a142020-07-23 14:30:03 -07005865 latency = period_ms + platform_render_latency(out) / 1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005866 } else {
5867 latency = (out->config.period_count * out->config.period_size * 1000) /
Mingshu Pangf69a88d2021-04-30 16:14:39 +08005868 (out->config.rate);
pavanisra2d95d82022-02-09 18:55:58 +05305869 if (out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5870 out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY)
Mingshu Pangf69a88d2021-04-30 16:14:39 +08005871 latency += platform_render_latency(out)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005872 }
5873
Zhou Songd2537a02020-06-11 22:04:46 +08005874 if (!out->standby && is_a2dp_out_device_type(&out->device_list))
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08005875 latency += audio_extn_a2dp_get_encoder_latency();
5876
Anish Kumar50ebcbf2014-12-09 04:01:39 +05305877 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08005878 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005879}
5880
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305881static float AmpToDb(float amplification)
5882{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305883 float db = DSD_VOLUME_MIN_DB;
5884 if (amplification > 0) {
5885 db = 20 * log10(amplification);
5886 if(db < DSD_VOLUME_MIN_DB)
5887 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305888 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305889 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305890}
5891
Krishna Kishor Jha10ad39f2022-02-21 17:02:47 +05305892#ifdef SOFT_VOLUME
5893static int out_set_soft_volume_params(struct audio_stream_out *stream)
5894{
5895 struct stream_out *out = (struct stream_out *)stream;
5896 int ret = 0;
5897 char mixer_ctl_name[128];
5898 struct audio_device *adev = out->dev;
5899 struct mixer_ctl *ctl = NULL;
5900 struct soft_step_volume_params *volume_params = NULL;
5901
5902 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5903 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Soft Vol Params", pcm_device_id);
5904 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5905 if (!ctl) {
5906 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5907 return -EINVAL;
5908 }
5909
5910 volume_params =(struct soft_step_volume_params * ) malloc(sizeof(struct soft_step_volume_params));
5911 if (volume_params == NULL){
5912 ALOGE("%s : malloc is failed for volume params", __func__);
5913 return -EINVAL;
5914 } else {
5915 ret = platform_get_soft_step_volume_params(volume_params,out->usecase);
5916 if (ret < 0) {
5917 ALOGE("%s : platform_get_soft_step_volume_params is fialed", __func__);
Karan Naidu28b335a2022-05-18 23:00:08 +05305918 ret = -EINVAL;
5919 goto ERR_EXIT;
Krishna Kishor Jha10ad39f2022-02-21 17:02:47 +05305920 }
5921
5922 }
5923 ret = mixer_ctl_set_array(ctl, volume_params, sizeof(struct soft_step_volume_params)/sizeof(int));
5924 if (ret < 0) {
5925 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
Karan Naidu28b335a2022-05-18 23:00:08 +05305926 ret = -EINVAL;
5927 goto ERR_EXIT;
5928 }
5929
5930 if (volume_params) {
5931 free(volume_params);
Krishna Kishor Jha10ad39f2022-02-21 17:02:47 +05305932 }
5933 return 0;
Karan Naidu28b335a2022-05-18 23:00:08 +05305934
5935ERR_EXIT:
5936 if (volume_params) {
5937 free(volume_params);
5938 }
5939 return ret;
Krishna Kishor Jha10ad39f2022-02-21 17:02:47 +05305940}
5941#endif
5942
Arun Mirpuri5d170872019-03-26 13:21:31 -07005943static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
5944 float right)
5945{
5946 struct stream_out *out = (struct stream_out *)stream;
5947 long volume = 0;
5948 char mixer_ctl_name[128] = "";
5949 struct audio_device *adev = out->dev;
5950 struct mixer_ctl *ctl = NULL;
5951 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5952 PCM_PLAYBACK);
5953
5954 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5955 "Playback %d Volume", pcm_device_id);
5956 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5957 if (!ctl) {
5958 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5959 __func__, mixer_ctl_name);
5960 return -EINVAL;
5961 }
5962 if (left != right)
5963 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
5964 __func__, left, right);
5965 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
5966 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
5967 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
5968 __func__, mixer_ctl_name, volume);
5969 return -EINVAL;
5970 }
5971 return 0;
5972}
5973
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305974static int out_set_compr_volume(struct audio_stream_out *stream, float left,
5975 float right)
5976{
5977 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305978 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305979 char mixer_ctl_name[128];
5980 struct audio_device *adev = out->dev;
5981 struct mixer_ctl *ctl;
5982 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5983 PCM_PLAYBACK);
5984
5985 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5986 "Compress Playback %d Volume", pcm_device_id);
5987 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5988 if (!ctl) {
5989 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5990 __func__, mixer_ctl_name);
5991 return -EINVAL;
5992 }
5993 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
5994 __func__, mixer_ctl_name, left, right);
5995 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
5996 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
5997 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5998
5999 return 0;
6000}
6001
Zhou Song2b8f28f2017-09-11 10:51:38 +08006002static int out_set_voip_volume(struct audio_stream_out *stream, float left,
6003 float right)
6004{
6005 struct stream_out *out = (struct stream_out *)stream;
6006 char mixer_ctl_name[] = "App Type Gain";
6007 struct audio_device *adev = out->dev;
6008 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05306009 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08006010
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07006011 if (!is_valid_volume(left, right)) {
6012 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
6013 __func__, left, right);
6014 return -EINVAL;
6015 }
6016
Zhou Song2b8f28f2017-09-11 10:51:38 +08006017 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
6018 if (!ctl) {
6019 ALOGE("%s: Could not get ctl for mixer cmd - %s",
6020 __func__, mixer_ctl_name);
6021 return -EINVAL;
6022 }
6023
6024 set_values[0] = 0; //0: Rx Session 1:Tx Session
6025 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05306026 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
6027 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08006028
6029 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
6030 return 0;
6031}
6032
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05306033static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
6034 float right)
6035{
6036 struct stream_out *out = (struct stream_out *)stream;
6037 /* Volume control for pcm playback */
6038 if (left != right) {
6039 return -EINVAL;
6040 } else {
6041 char mixer_ctl_name[128];
6042 struct audio_device *adev = out->dev;
6043 struct mixer_ctl *ctl;
6044 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
6045 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
6046 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
6047 if (!ctl) {
6048 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
6049 return -EINVAL;
6050 }
6051
6052 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
6053 int ret = mixer_ctl_set_value(ctl, 0, volume);
6054 if (ret < 0) {
6055 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
6056 return -EINVAL;
6057 }
6058
6059 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
6060
6061 return 0;
6062 }
6063}
6064
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006065static int out_set_volume(struct audio_stream_out *stream, float left,
6066 float right)
6067{
Eric Laurenta9024de2013-04-04 09:19:12 -07006068 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006069 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306070 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006071
Arun Mirpuri5d170872019-03-26 13:21:31 -07006072 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07006073 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
6074 /* only take left channel into account: the API is for stereo anyway */
6075 out->muted = (left == 0.0f);
6076 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006077 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306078 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006079 /*
6080 * Set mute or umute on HDMI passthrough stream.
6081 * Only take left channel into account.
6082 * Mute is 0 and unmute 1
6083 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306084 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306085 } else if (out->format == AUDIO_FORMAT_DSD){
6086 char mixer_ctl_name[128] = "DSD Volume";
6087 struct audio_device *adev = out->dev;
6088 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
6089
6090 if (!ctl) {
6091 ALOGE("%s: Could not get ctl for mixer cmd - %s",
6092 __func__, mixer_ctl_name);
6093 return -EINVAL;
6094 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05306095 volume[0] = (long)(AmpToDb(left));
6096 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306097 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
6098 return 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006099 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS) &&
Derek Chendf05eea2019-08-01 13:57:49 -07006100 (out->car_audio_stream == CAR_AUDIO_STREAM_MEDIA)) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07006101 ALOGD("%s: Overriding offload set volume for media bus stream", __func__);
6102 struct listnode *node = NULL;
6103 list_for_each(node, &adev->active_outputs_list) {
6104 streams_output_ctxt_t *out_ctxt = node_to_item(node,
6105 streams_output_ctxt_t,
6106 list);
6107 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
6108 out->volume_l = out_ctxt->output->volume_l;
6109 out->volume_r = out_ctxt->output->volume_r;
6110 }
6111 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08006112 pthread_mutex_lock(&out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +08006113 if (!out->a2dp_muted) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07006114 ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
6115 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08006116 pthread_mutex_unlock(&out->latch_lock);
Philippe Gravel1c9ac352019-05-28 16:08:37 -07006117 return ret;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006118 } else {
Weiyin Jiang280ea742020-09-08 20:28:22 +08006119 pthread_mutex_lock(&out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +08006120 ALOGV("%s: compress mute %d", __func__, out->a2dp_muted);
6121 if (!out->a2dp_muted)
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306122 ret = out_set_compr_volume(stream, left, right);
6123 out->volume_l = left;
6124 out->volume_r = right;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006125 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306126 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006127 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07006128 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08006129 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
6130 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Songbaddf9f2020-11-20 13:57:39 +08006131 pthread_mutex_lock(&out->latch_lock);
Aalique Grahame22e49102018-12-18 14:23:57 -08006132 if (!out->standby) {
6133 audio_extn_utils_send_app_type_gain(out->dev,
6134 out->app_type_cfg.app_type,
6135 &out->app_type_cfg.gain[0]);
Zhou Songbaddf9f2020-11-20 13:57:39 +08006136 if (!out->a2dp_muted)
6137 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08006138 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08006139 out->volume_l = left;
6140 out->volume_r = right;
Zhou Songbaddf9f2020-11-20 13:57:39 +08006141 pthread_mutex_unlock(&out->latch_lock);
Zhou Song2b8f28f2017-09-11 10:51:38 +08006142 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006143 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
6144 ALOGV("%s: MMAP set volume called", __func__);
6145 if (!out->standby)
6146 ret = out_set_mmap_volume(stream, left, right);
6147 out->volume_l = left;
6148 out->volume_r = right;
6149 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05306150 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05306151 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
6152 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Zhou Songbaddf9f2020-11-20 13:57:39 +08006153 pthread_mutex_lock(&out->latch_lock);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05306154 /* Volume control for pcm playback */
Zhou Songbaddf9f2020-11-20 13:57:39 +08006155 if (!out->standby && !out->a2dp_muted)
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05306156 ret = out_set_pcm_volume(stream, left, right);
6157 else
6158 out->apply_volume = true;
6159
6160 out->volume_l = left;
6161 out->volume_r = right;
Zhou Songbaddf9f2020-11-20 13:57:39 +08006162 pthread_mutex_unlock(&out->latch_lock);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05306163 return ret;
Derek Chenf13dd492018-11-13 14:53:51 -08006164 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
6165 ALOGV("%s: bus device set volume called", __func__);
Zhou Songbaddf9f2020-11-20 13:57:39 +08006166 pthread_mutex_lock(&out->latch_lock);
6167 if (!out->standby && !out->a2dp_muted)
Derek Chenf13dd492018-11-13 14:53:51 -08006168 ret = out_set_pcm_volume(stream, left, right);
6169 out->volume_l = left;
6170 out->volume_r = right;
Zhou Songbaddf9f2020-11-20 13:57:39 +08006171 pthread_mutex_unlock(&out->latch_lock);
Derek Chenf13dd492018-11-13 14:53:51 -08006172 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07006173 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006174
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006175 return -ENOSYS;
6176}
6177
Zhou Songc9672822017-08-16 16:01:39 +08006178static void update_frames_written(struct stream_out *out, size_t bytes)
6179{
6180 size_t bpf = 0;
6181
6182 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
6183 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
6184 bpf = 1;
6185 else if (!is_offload_usecase(out->usecase))
6186 bpf = audio_bytes_per_sample(out->format) *
6187 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08006188
6189 pthread_mutex_lock(&out->position_query_lock);
6190 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08006191 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08006192 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
6193 }
6194 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08006195}
6196
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006197int split_and_write_audio_haptic_data(struct stream_out *out,
6198 const void *buffer, size_t bytes_to_write)
6199{
6200 struct audio_device *adev = out->dev;
6201
6202 int ret = 0;
6203 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
6204 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
6205 size_t frame_size = channel_count * bytes_per_sample;
6206 size_t frame_count = bytes_to_write / frame_size;
6207
6208 bool force_haptic_path =
6209 property_get_bool("vendor.audio.test_haptic", false);
6210
6211 // extract Haptics data from Audio buffer
6212 bool alloc_haptic_buffer = false;
6213 int haptic_channel_count = adev->haptics_config.channels;
6214 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
6215 size_t audio_frame_size = frame_size - haptic_frame_size;
6216 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
6217
6218 if (adev->haptic_buffer == NULL) {
6219 alloc_haptic_buffer = true;
6220 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
6221 free(adev->haptic_buffer);
6222 adev->haptic_buffer_size = 0;
6223 alloc_haptic_buffer = true;
6224 }
6225
6226 if (alloc_haptic_buffer) {
6227 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08006228 if(adev->haptic_buffer == NULL) {
6229 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
6230 return -ENOMEM;
6231 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006232 adev->haptic_buffer_size = total_haptic_buffer_size;
6233 }
6234
6235 size_t src_index = 0, aud_index = 0, hap_index = 0;
6236 uint8_t *audio_buffer = (uint8_t *)buffer;
6237 uint8_t *haptic_buffer = adev->haptic_buffer;
6238
6239 // This is required for testing only. This works for stereo data only.
6240 // One channel is fed to audio stream and other to haptic stream for testing.
6241 if (force_haptic_path)
6242 audio_frame_size = haptic_frame_size = bytes_per_sample;
6243
6244 for (size_t i = 0; i < frame_count; i++) {
6245 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
6246 audio_frame_size);
6247 aud_index += audio_frame_size;
6248 src_index += audio_frame_size;
6249
6250 if (adev->haptic_pcm)
6251 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
6252 haptic_frame_size);
6253 hap_index += haptic_frame_size;
6254 src_index += haptic_frame_size;
6255
6256 // This is required for testing only.
6257 // Discard haptic channel data.
6258 if (force_haptic_path)
6259 src_index += haptic_frame_size;
6260 }
6261
6262 // write to audio pipeline
6263 ret = pcm_write(out->pcm, (void *)audio_buffer,
6264 frame_count * audio_frame_size);
6265
6266 // write to haptics pipeline
6267 if (adev->haptic_pcm)
6268 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
6269 frame_count * haptic_frame_size);
6270
6271 return ret;
6272}
6273
Aalique Grahame22e49102018-12-18 14:23:57 -08006274#ifdef NO_AUDIO_OUT
6275static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
6276 const void *buffer __unused, size_t bytes)
6277{
6278 struct stream_out *out = (struct stream_out *)stream;
6279
6280 /* No Output device supported other than BT for playback.
6281 * Sleep for the amount of buffer duration
6282 */
6283 lock_output_stream(out);
6284 usleep(bytes * 1000000 / audio_stream_out_frame_size(
6285 (const struct audio_stream_out *)&out->stream) /
6286 out_get_sample_rate(&out->stream.common));
6287 pthread_mutex_unlock(&out->lock);
6288 return bytes;
6289}
6290#endif
6291
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006292static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
6293 size_t bytes)
6294{
6295 struct stream_out *out = (struct stream_out *)stream;
6296 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07006297 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05306298 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006299 const size_t frame_size = audio_stream_out_frame_size(stream);
6300 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05306301 struct audio_usecase *usecase = NULL;
Meng Wang4c32fb42020-01-16 17:57:11 +08006302 uint32_t compr_passthr = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006303
Haynes Mathew George380745d2017-10-04 15:27:45 -07006304 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006305 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306306
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05006307 if (CARD_STATUS_OFFLINE == out->card_status ||
6308 POWER_POLICY_STATUS_OFFLINE == adev->out_power_policy) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08006309
Dhananjay Kumarac341582017-02-23 23:42:25 +05306310 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306311 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05306312 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
6313 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006314 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05306315 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05306316 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05306317 ALOGD(" %s: sound card is not active/SSR state", __func__);
6318 ret= -EIO;
6319 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306320 }
6321 }
6322
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306323 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05306324 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05306325 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306326 goto exit;
6327 }
6328
Haynes Mathew George16081042017-05-31 17:16:49 -07006329 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
6330 ret = -EINVAL;
6331 goto exit;
6332 }
6333
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006334 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306335 !out->is_iec61937_info_available) {
6336
6337 if (!audio_extn_passthru_is_passthrough_stream(out)) {
6338 out->is_iec61937_info_available = true;
6339 } else if (audio_extn_passthru_is_enabled()) {
6340 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05306341 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05306342
6343 if((out->format == AUDIO_FORMAT_DTS) ||
6344 (out->format == AUDIO_FORMAT_DTS_HD)) {
6345 ret = audio_extn_passthru_update_dts_stream_configuration(out,
6346 buffer, bytes);
6347 if (ret) {
6348 if (ret != -ENOSYS) {
6349 out->is_iec61937_info_available = false;
6350 ALOGD("iec61937 transmission info not yet updated retry");
6351 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306352 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05306353 /* if stream has started and after that there is
6354 * stream config change (iec transmission config)
6355 * then trigger select_device to update backend configuration.
6356 */
6357 out->stream_config_changed = true;
6358 pthread_mutex_lock(&adev->lock);
6359 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306360 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08006361 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306362 ret = -EINVAL;
6363 goto exit;
6364 }
Manish Dewangan671a4202017-08-18 17:30:46 +05306365 pthread_mutex_unlock(&adev->lock);
6366 out->stream_config_changed = false;
6367 out->is_iec61937_info_available = true;
6368 }
6369 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05306370
Meng Wang4c32fb42020-01-16 17:57:11 +08006371#ifdef AUDIO_GKI_ENABLED
6372 /* out->compr_config.codec->reserved[0] is for compr_passthr */
6373 compr_passthr = out->compr_config.codec->reserved[0];
6374#else
6375 compr_passthr = out->compr_config.codec->compr_passthr;
6376#endif
6377
Garmond Leung317cbf12017-09-13 16:20:50 -07006378 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Meng Wang4c32fb42020-01-16 17:57:11 +08006379 (compr_passthr == PASSTHROUGH) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05306380 (out->is_iec61937_info_available == true)) {
6381 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
6382 ret = -EINVAL;
6383 goto exit;
6384 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05306385 }
6386 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306387
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006388 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02006389 (audio_extn_a2dp_source_is_suspended())) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006390 if (!(compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER) ||
6391 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Zhou Songd01e7a22020-09-23 22:49:01 +08006392 if (!is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306393 ret = -EIO;
6394 goto exit;
6395 }
6396 }
6397 }
6398
Weiyin Jiangabedea32020-12-09 12:49:19 +08006399 if (is_usb_out_device_type(&out->device_list) &&
6400 !audio_extn_usb_connected(NULL)) {
6401 ret = -EIO;
6402 goto exit;
6403 }
6404
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006405 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07006406 out->standby = false;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006407 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
6408
Eric Laurent150dbfe2013-02-27 14:31:02 -08006409 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006410 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
6411 ret = voice_extn_compress_voip_start_output_stream(out);
6412 else
6413 ret = start_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006414 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006415 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07006416 out->standby = true;
Weiyin Jiangac2bae82020-07-29 17:23:53 +08006417 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006418 goto exit;
6419 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306420 out->started = 1;
Andy Hunga1f48fa2019-07-01 18:14:53 -07006421 out->last_fifo_valid = false; // we're coming out of standby, last_fifo isn't valid.
Weiyin Jiangac2bae82020-07-29 17:23:53 +08006422
6423 if ((last_known_cal_step != -1) && (adev->platform != NULL)) {
vivek mehtab72d08d2016-04-29 03:16:47 -07006424 ALOGD("%s: retry previous failed cal level set", __func__);
Weiyin Jiangac2bae82020-07-29 17:23:53 +08006425 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05306426 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07006427 }
Weiyin Jiangac2bae82020-07-29 17:23:53 +08006428 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306429
6430 if ((out->is_iec61937_info_available == true) &&
6431 (audio_extn_passthru_is_passthrough_stream(out))&&
6432 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
6433 ret = -EINVAL;
6434 goto exit;
6435 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05306436 if (out->set_dual_mono)
6437 audio_extn_send_dual_mono_mixing_coefficients(out);
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006438
Dechen Chai22768452021-07-30 09:29:16 +05306439#ifndef LINUX_ENABLED
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006440 // log startup time in ms.
6441 simple_stats_log(
6442 &out->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Dechen Chai22768452021-07-30 09:29:16 +05306443#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006444 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006445
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006446 if (adev->is_channel_status_set == false &&
6447 compare_device_type(&out->device_list,
6448 AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Alexy Josephb1379942016-01-29 15:49:38 -08006449 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05306450 adev->is_channel_status_set = true;
6451 }
6452
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05306453 if ((adev->use_old_pspd_mix_ctrl == true) &&
6454 (out->pspd_coeff_sent == false)) {
6455 /*
6456 * Need to resend pspd coefficients after stream started for
6457 * older kernel version as it does not save the coefficients
6458 * and also stream has to be started for coeff to apply.
6459 */
6460 usecase = get_usecase_from_list(adev, out->usecase);
6461 if (usecase != NULL) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05306462 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05306463 out->pspd_coeff_sent = true;
6464 }
6465 }
6466
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006467 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08006468 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006469 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006470 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006471 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
6472 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05306473 if (out->send_next_track_params && out->is_compr_metadata_avail) {
6474 ALOGD("copl(%p):send next track params in gapless", out);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08006475 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05306476 out->send_next_track_params = false;
6477 out->is_compr_metadata_avail = false;
6478 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006479 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05306480 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306481 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006482
Ashish Jain83a6cc22016-06-28 14:34:17 +05306483 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05306484 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05306485 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05306486 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006487 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05306488 return -EINVAL;
6489 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05306490 audio_format_t dst_format = out->hal_op_format;
6491 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306492
Dieter Luecking5d57def2018-09-07 14:23:37 +02006493 /* prevent division-by-zero */
6494 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
6495 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
6496 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
6497 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05306498 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006499 ATRACE_END();
6500 return -EINVAL;
6501 }
6502
Ashish Jainf1eaa582016-05-23 20:54:24 +05306503 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
6504 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
6505
Ashish Jain83a6cc22016-06-28 14:34:17 +05306506 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05306507 dst_format,
6508 buffer,
6509 src_format,
6510 frames);
6511
Ashish Jain83a6cc22016-06-28 14:34:17 +05306512 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05306513 bytes_to_write);
6514
6515 /*Convert written bytes in audio flinger format*/
6516 if (ret > 0)
6517 ret = ((ret * format_to_bitwidth_table[out->format]) /
6518 format_to_bitwidth_table[dst_format]);
6519 }
6520 } else
6521 ret = compress_write(out->compr, buffer, bytes);
6522
Zhou Songc9672822017-08-16 16:01:39 +08006523 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
6524 update_frames_written(out, bytes);
6525
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306526 if (ret < 0)
6527 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08006528 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05306529 /*msg to cb thread only if non blocking write is enabled*/
6530 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05306531 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006532 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05306533 } else if (-ENETRESET == ret) {
6534 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306535 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05306536 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05306537 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006538 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05306539 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006540 }
Ashish Jain5106d362016-05-11 19:23:33 +05306541
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05306542 /* Call compr start only when non-zero bytes of data is there to be rendered */
6543 if (!out->playback_started && ret > 0) {
6544 int status = compress_start(out->compr);
6545 if (status < 0) {
6546 ret = status;
6547 ALOGE("%s: compr start failed with err %d", __func__, errno);
6548 goto exit;
6549 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07006550 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006551 out->playback_started = 1;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006552 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006553 out->offload_state = OFFLOAD_STATE_PLAYING;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006554 pthread_mutex_unlock(&out->latch_lock);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006555
6556 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6557 popcount(out->channel_mask),
6558 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006559 }
6560 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006561 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006562 return ret;
6563 } else {
6564 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006565 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006566 if (out->muted)
6567 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006568 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
6569 __func__, frames, frame_size, bytes_to_write);
6570
Aalique Grahame22e49102018-12-18 14:23:57 -08006571 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07006572 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
6573 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
6574 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006575 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
6576 int16_t *src = (int16_t *)buffer;
6577 int16_t *dst = (int16_t *)buffer;
6578
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006579 LOG_ALWAYS_FATAL_IF(channel_count > 2 ||
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006580 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08006581 "out_write called for %s use case with wrong properties",
6582 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006583
6584 /*
6585 * FIXME: this can be removed once audio flinger mixer supports
6586 * mono output
6587 */
6588
6589 /*
6590 * Code below goes over each frame in the buffer and adds both
6591 * L and R samples and then divides by 2 to convert to mono
6592 */
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006593 if (channel_count == 2) {
6594 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
6595 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
6596 }
6597 bytes_to_write /= 2;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006598 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006599 }
Andy Hunga1f48fa2019-07-01 18:14:53 -07006600
6601 // Note: since out_get_presentation_position() is called alternating with out_write()
6602 // by AudioFlinger, we can check underruns using the prior timestamp read.
6603 // (Alternately we could check if the buffer is empty using pcm_get_htimestamp().
6604 if (out->last_fifo_valid) {
6605 // compute drain to see if there is an underrun.
6606 const int64_t current_ns = systemTime(SYSTEM_TIME_MONOTONIC); // sys call
Dhananjay Kumara4429632020-07-11 02:53:37 +05306607 int64_t time_diff_ns = current_ns - out->last_fifo_time_ns;
6608 int64_t frames_by_time =
6609 ((time_diff_ns > 0) && (time_diff_ns < (INT64_MAX / out->config.rate))) ?
6610 (time_diff_ns * out->config.rate / NANOS_PER_SECOND) : 0;
Andy Hunga1f48fa2019-07-01 18:14:53 -07006611 const int64_t underrun = frames_by_time - out->last_fifo_frames_remaining;
6612
6613 if (underrun > 0) {
Dechen Chai22768452021-07-30 09:29:16 +05306614#ifndef LINUX_ENABLED
Andy Hunga1f48fa2019-07-01 18:14:53 -07006615 simple_stats_log(&out->fifo_underruns, underrun);
Dechen Chai22768452021-07-30 09:29:16 +05306616#endif
Andy Hunga1f48fa2019-07-01 18:14:53 -07006617
6618 ALOGW("%s: underrun(%lld) "
6619 "frames_by_time(%lld) > out->last_fifo_frames_remaining(%lld)",
6620 __func__,
6621 (long long)out->fifo_underruns.n,
6622 (long long)frames_by_time,
6623 (long long)out->last_fifo_frames_remaining);
6624 }
6625 out->last_fifo_valid = false; // we're writing below, mark fifo info as stale.
6626 }
6627
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306628 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006629
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006630 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006631
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006632 if (out->config.rate)
6633 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
6634 out->config.rate;
6635
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006636 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006637 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
6638
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006639 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006640 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006641 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306642 out->convert_buffer != NULL) {
6643
6644 memcpy_by_audio_format(out->convert_buffer,
6645 out->hal_op_format,
6646 buffer,
6647 out->hal_ip_format,
6648 out->config.period_size * out->config.channels);
6649
6650 ret = pcm_write(out->pcm, out->convert_buffer,
6651 (out->config.period_size *
6652 out->config.channels *
6653 format_to_bitwidth_table[out->hal_op_format]));
6654 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05306655 /*
6656 * To avoid underrun in DSP when the application is not pumping
6657 * data at required rate, check for the no. of bytes and ignore
6658 * pcm_write if it is less than actual buffer size.
6659 * It is a work around to a change in compress VOIP driver.
6660 */
6661 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
6662 bytes < (out->config.period_size * out->config.channels *
6663 audio_bytes_per_sample(out->format))) {
6664 size_t voip_buf_size =
6665 out->config.period_size * out->config.channels *
6666 audio_bytes_per_sample(out->format);
6667 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
6668 __func__, bytes, voip_buf_size);
6669 usleep(((uint64_t)voip_buf_size - bytes) *
6670 1000000 / audio_stream_out_frame_size(stream) /
6671 out_get_sample_rate(&out->stream.common));
6672 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006673 } else {
6674 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
6675 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
6676 else
6677 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
6678 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306679 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006680
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006681 release_out_focus(out);
6682
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306683 if (ret < 0)
6684 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08006685 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05306686 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006687 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006688 }
6689
6690exit:
Zhou Songc9672822017-08-16 16:01:39 +08006691 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306692 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306693 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306694 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006695 pthread_mutex_unlock(&out->lock);
6696
6697 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006698 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08006699 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306700 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306701 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306702 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306703 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306704 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306705 out->standby = true;
6706 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306707 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006708 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
6709 /* prevent division-by-zero */
6710 uint32_t stream_size = audio_stream_out_frame_size(stream);
6711 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006712
Dieter Luecking5d57def2018-09-07 14:23:37 +02006713 if ((stream_size == 0) || (srate == 0)) {
6714 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
6715 ATRACE_END();
6716 return -EINVAL;
6717 }
6718 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
6719 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006720 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05306721 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006722 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006723 return ret;
6724 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006725 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07006726 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006727 return bytes;
6728}
6729
6730static int out_get_render_position(const struct audio_stream_out *stream,
6731 uint32_t *dsp_frames)
6732{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006733 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08006734
6735 if (dsp_frames == NULL)
6736 return -EINVAL;
6737
6738 *dsp_frames = 0;
6739 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08006740 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05306741
6742 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
6743 * this operation and adev_close_output_stream(where out gets reset).
6744 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05306745 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006746 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05306747 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006748 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05306749 return 0;
6750 }
6751
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006752 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05306753 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306754 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006755 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306756 if (ret < 0)
6757 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006758 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05306759 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006760 }
Naresh Tanniru80659832014-06-04 18:17:56 +05306761 if (-ENETRESET == ret) {
6762 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306763 out->card_status = CARD_STATUS_OFFLINE;
6764 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306765 } else if(ret < 0) {
6766 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306767 ret = -EINVAL;
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05006768 } else if (out->card_status == CARD_STATUS_OFFLINE ||
6769 adev->out_power_policy == POWER_POLICY_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05306770 /*
6771 * Handle corner case where compress session is closed during SSR
6772 * and timestamp is queried
6773 */
6774 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306775 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306776 } else if (out->prev_card_status_offline) {
6777 ALOGE("ERROR: previously sound card was offline,return error");
6778 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306779 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306780 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006781 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05306782 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306783 pthread_mutex_unlock(&out->lock);
6784 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08006785 } else if (audio_is_linear_pcm(out->format)) {
6786 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006787 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08006788 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006789 } else
6790 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006791}
6792
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006793static int out_add_audio_effect(const struct audio_stream *stream __unused,
6794 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006795{
6796 return 0;
6797}
6798
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006799static int out_remove_audio_effect(const struct audio_stream *stream __unused,
6800 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006801{
6802 return 0;
6803}
6804
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006805static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
6806 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006807{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05306808 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006809}
6810
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006811static int out_get_presentation_position(const struct audio_stream_out *stream,
6812 uint64_t *frames, struct timespec *timestamp)
6813{
6814 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05306815 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07006816 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006817
Ashish Jain5106d362016-05-11 19:23:33 +05306818 /* below piece of code is not guarded against any lock because audioFliner serializes
6819 * this operation and adev_close_output_stream( where out gets reset).
6820 */
6821 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05306822 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006823 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05306824 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
6825 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
6826 return 0;
6827 }
6828
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006829 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006830
Ashish Jain5106d362016-05-11 19:23:33 +05306831 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
6832 ret = compress_get_tstamp(out->compr, &dsp_frames,
6833 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08006834 // Adjustment accounts for A2dp encoder latency with offload usecases
6835 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006836 if (is_a2dp_out_device_type(&out->device_list)) {
yidongh0515e042017-07-06 15:00:34 +08006837 unsigned long offset =
6838 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
6839 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
6840 }
Ashish Jain5106d362016-05-11 19:23:33 +05306841 ALOGVV("%s rendered frames %ld sample_rate %d",
6842 __func__, dsp_frames, out->sample_rate);
6843 *frames = dsp_frames;
6844 if (ret < 0)
6845 ret = -errno;
6846 if (-ENETRESET == ret) {
6847 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306848 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05306849 ret = -EINVAL;
6850 } else
6851 ret = 0;
6852 /* this is the best we can do */
6853 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07006854 } else {
6855 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08006856 unsigned int avail;
6857 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
George Gao62ebc722019-07-29 16:29:44 -07006858 uint64_t signed_frames = 0;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006859 uint64_t frames_temp = 0;
George Gao62ebc722019-07-29 16:29:44 -07006860
Andy Hunga1f48fa2019-07-01 18:14:53 -07006861 if (out->kernel_buffer_size > avail) {
6862 frames_temp = out->last_fifo_frames_remaining = out->kernel_buffer_size - avail;
6863 } else {
6864 ALOGW("%s: avail:%u > kernel_buffer_size:%zu clamping!",
6865 __func__, avail, out->kernel_buffer_size);
6866 avail = out->kernel_buffer_size;
6867 frames_temp = out->last_fifo_frames_remaining = 0;
6868 }
6869 out->last_fifo_valid = true;
6870 out->last_fifo_time_ns = audio_utils_ns_from_timespec(timestamp);
6871
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006872 if (out->written >= frames_temp)
6873 signed_frames = out->written - frames_temp;
George Gao62ebc722019-07-29 16:29:44 -07006874
Andy Hunga1f48fa2019-07-01 18:14:53 -07006875 ALOGVV("%s: frames:%lld avail:%u kernel_buffer_size:%zu",
6876 __func__, (long long)signed_frames, avail, out->kernel_buffer_size);
6877
Weiyin Jiangd4633762018-03-16 12:05:03 +08006878 // This adjustment accounts for buffering after app processor.
6879 // It is based on estimated DSP latency per use case, rather than exact.
George Gao9ba8a142020-07-23 14:30:03 -07006880 frames_temp = platform_render_latency(out) *
Robert Lee58215542019-07-15 20:55:12 +08006881 out->sample_rate / 1000000LL;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006882 if (signed_frames >= frames_temp)
6883 signed_frames -= frames_temp;
Aniket Kumar Lataff613152017-07-18 18:19:21 -07006884
Weiyin Jiangd4633762018-03-16 12:05:03 +08006885 // Adjustment accounts for A2dp encoder latency with non offload usecases
6886 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006887 if (is_a2dp_out_device_type(&out->device_list)) {
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006888 frames_temp = audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000;
6889 if (signed_frames >= frames_temp)
6890 signed_frames -= frames_temp;
Weiyin Jiangd4633762018-03-16 12:05:03 +08006891 }
6892
6893 // It would be unusual for this value to be negative, but check just in case ...
George Gao62ebc722019-07-29 16:29:44 -07006894 *frames = signed_frames;
6895 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006896 }
Eric Laurenta7a33042019-07-10 16:20:22 -07006897 } else if (out->card_status == CARD_STATUS_OFFLINE ||
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05006898 adev->out_power_policy == POWER_POLICY_STATUS_OFFLINE ||
Eric Laurenta7a33042019-07-10 16:20:22 -07006899 // audioflinger still needs position updates when A2DP is suspended
Jasmine Cha5c2517f2019-09-09 11:07:28 +08006900 (is_a2dp_out_device_type(&out->device_list) && audio_extn_a2dp_source_is_suspended())) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306901 *frames = out->written;
6902 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306903 if (is_offload_usecase(out->usecase))
6904 ret = -EINVAL;
6905 else
6906 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006907 }
6908 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006909 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006910 return ret;
6911}
6912
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006913static int out_set_callback(struct audio_stream_out *stream,
6914 stream_callback_t callback, void *cookie)
6915{
6916 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006917 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006918
6919 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006920 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006921 out->client_callback = callback;
6922 out->client_cookie = cookie;
6923 if (out->adsp_hdlr_stream_handle) {
6924 ret = audio_extn_adsp_hdlr_stream_set_callback(
6925 out->adsp_hdlr_stream_handle,
6926 callback,
6927 cookie);
6928 if (ret)
6929 ALOGW("%s:adsp hdlr callback registration failed %d",
6930 __func__, ret);
6931 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006932 pthread_mutex_unlock(&out->lock);
6933 return 0;
6934}
6935
6936static int out_pause(struct audio_stream_out* stream)
6937{
6938 struct stream_out *out = (struct stream_out *)stream;
6939 int status = -ENOSYS;
6940 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006941 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006942 ALOGD("copl(%p):pause compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306943 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006944 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006945 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006946 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306947 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05306948 status = compress_pause(out->compr);
6949
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006950 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006951
Mingming Yin21854652016-04-13 11:54:02 -07006952 if (audio_extn_passthru_is_active()) {
6953 ALOGV("offload use case, pause passthru");
6954 audio_extn_passthru_on_pause(out);
6955 }
6956
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306957 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006958 audio_extn_dts_notify_playback_state(out->usecase, 0,
6959 out->sample_rate, popcount(out->channel_mask),
6960 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006961 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08006962 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006963 pthread_mutex_unlock(&out->lock);
6964 }
6965 return status;
6966}
6967
6968static int out_resume(struct audio_stream_out* stream)
6969{
6970 struct stream_out *out = (struct stream_out *)stream;
6971 int status = -ENOSYS;
6972 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006973 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006974 ALOGD("copl(%p):resume compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306975 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006976 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006977 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006978 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306979 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306980 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07006981 }
6982 if (!status) {
6983 out->offload_state = OFFLOAD_STATE_PLAYING;
6984 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306985 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006986 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6987 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006988 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08006989 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006990 pthread_mutex_unlock(&out->lock);
6991 }
6992 return status;
6993}
6994
6995static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
6996{
6997 struct stream_out *out = (struct stream_out *)stream;
6998 int status = -ENOSYS;
6999 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07007000 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007001 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007002 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
7003 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
7004 else
7005 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
7006 pthread_mutex_unlock(&out->lock);
7007 }
7008 return status;
7009}
7010
7011static int out_flush(struct audio_stream_out* stream)
7012{
7013 struct stream_out *out = (struct stream_out *)stream;
7014 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07007015 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07007016 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007017 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08007018 pthread_mutex_lock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07007019 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
Gautam Manam14c198b2020-12-24 14:08:04 +05307020 pthread_mutex_unlock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07007021 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07007022 } else {
7023 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
Gautam Manam14c198b2020-12-24 14:08:04 +05307024 pthread_mutex_unlock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07007025 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08007026 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007027 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07007028 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007029 return 0;
7030 }
7031 return -ENOSYS;
7032}
7033
Haynes Mathew George16081042017-05-31 17:16:49 -07007034static int out_stop(const struct audio_stream_out* stream)
7035{
7036 struct stream_out *out = (struct stream_out *)stream;
7037 struct audio_device *adev = out->dev;
7038 int ret = -ENOSYS;
7039
7040 ALOGV("%s", __func__);
7041 pthread_mutex_lock(&adev->lock);
7042 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
7043 out->playback_started && out->pcm != NULL) {
7044 pcm_stop(out->pcm);
7045 ret = stop_output_stream(out);
7046 out->playback_started = false;
7047 }
7048 pthread_mutex_unlock(&adev->lock);
7049 return ret;
7050}
7051
7052static int out_start(const struct audio_stream_out* stream)
7053{
7054 struct stream_out *out = (struct stream_out *)stream;
7055 struct audio_device *adev = out->dev;
7056 int ret = -ENOSYS;
7057
7058 ALOGV("%s", __func__);
7059 pthread_mutex_lock(&adev->lock);
7060 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
7061 !out->playback_started && out->pcm != NULL) {
7062 ret = start_output_stream(out);
7063 if (ret == 0) {
7064 out->playback_started = true;
7065 }
7066 }
7067 pthread_mutex_unlock(&adev->lock);
7068 return ret;
7069}
7070
7071/*
7072 * Modify config->period_count based on min_size_frames
7073 */
7074static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
7075{
7076 int periodCountRequested = (min_size_frames + config->period_size - 1)
7077 / config->period_size;
7078 int periodCount = MMAP_PERIOD_COUNT_MIN;
7079
7080 ALOGV("%s original config.period_size = %d config.period_count = %d",
7081 __func__, config->period_size, config->period_count);
7082
7083 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
7084 periodCount *= 2;
7085 }
7086 config->period_count = periodCount;
7087
7088 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
7089}
7090
Phil Burkfe17efd2019-03-25 10:23:35 -07007091// Read offset for the positional timestamp from a persistent vendor property.
7092// This is to workaround apparent inaccuracies in the timing information that
7093// is used by the AAudio timing model. The inaccuracies can cause glitches.
7094static int64_t get_mmap_out_time_offset() {
7095 const int32_t kDefaultOffsetMicros = 0;
7096 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08007097 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07007098 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
7099 return mmap_time_offset_micros * (int64_t)1000;
7100}
7101
Haynes Mathew George16081042017-05-31 17:16:49 -07007102static int out_create_mmap_buffer(const struct audio_stream_out *stream,
7103 int32_t min_size_frames,
7104 struct audio_mmap_buffer_info *info)
7105{
7106 struct stream_out *out = (struct stream_out *)stream;
7107 struct audio_device *adev = out->dev;
7108 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07007109 unsigned int offset1 = 0;
7110 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007111 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07007112 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007113 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07007114
Arun Mirpuri5d170872019-03-26 13:21:31 -07007115 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05307116 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07007117 pthread_mutex_lock(&adev->lock);
7118
Sharad Sanglec6f32552018-05-04 16:15:38 +05307119 if (CARD_STATUS_OFFLINE == out->card_status ||
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05007120 CARD_STATUS_OFFLINE == adev->card_status ||
7121 POWER_POLICY_STATUS_OFFLINE == adev->out_power_policy) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307122 ALOGW("out->card_status or adev->card_status offline, try again");
7123 ret = -EIO;
7124 goto exit;
7125 }
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307126 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07007127 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
7128 ret = -EINVAL;
7129 goto exit;
7130 }
7131 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
7132 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
7133 ret = -ENOSYS;
7134 goto exit;
7135 }
7136 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
7137 if (out->pcm_device_id < 0) {
7138 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
7139 __func__, out->pcm_device_id, out->usecase);
7140 ret = -EINVAL;
7141 goto exit;
7142 }
7143
7144 adjust_mmap_period_count(&out->config, min_size_frames);
7145
Arun Mirpuri5d170872019-03-26 13:21:31 -07007146 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07007147 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
7148 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
7149 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307150 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307151 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7152 out->card_status = CARD_STATUS_OFFLINE;
7153 adev->card_status = CARD_STATUS_OFFLINE;
7154 ret = -EIO;
7155 goto exit;
7156 }
7157
Haynes Mathew George16081042017-05-31 17:16:49 -07007158 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
7159 step = "open";
7160 ret = -ENODEV;
7161 goto exit;
7162 }
7163 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
7164 if (ret < 0) {
7165 step = "begin";
7166 goto exit;
7167 }
juyuchen626833d2019-06-04 16:48:02 +08007168
7169 info->flags = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007170 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07007171 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07007172 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07007173 ret = platform_get_mmap_data_fd(adev->platform,
7174 out->pcm_device_id, 0 /*playback*/,
7175 &info->shared_memory_fd,
7176 &mmap_size);
7177 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07007178 // Fall back to non exclusive mode
7179 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
7180 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07007181 out->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
7182 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, out->mmap_shared_memory_fd);
7183
Arun Mirpuri5d170872019-03-26 13:21:31 -07007184 if (mmap_size < buffer_size) {
7185 step = "mmap";
7186 goto exit;
7187 }
juyuchen626833d2019-06-04 16:48:02 +08007188 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07007189 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007190 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07007191 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07007192
7193 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
7194 if (ret < 0) {
7195 step = "commit";
7196 goto exit;
7197 }
7198
Phil Burkfe17efd2019-03-25 10:23:35 -07007199 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
7200
Haynes Mathew George16081042017-05-31 17:16:49 -07007201 out->standby = false;
7202 ret = 0;
7203
Arun Mirpuri5d170872019-03-26 13:21:31 -07007204 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07007205 __func__, info->shared_memory_address, info->buffer_size_frames);
7206
7207exit:
7208 if (ret != 0) {
7209 if (out->pcm == NULL) {
7210 ALOGE("%s: %s - %d", __func__, step, ret);
7211 } else {
7212 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
7213 pcm_close(out->pcm);
7214 out->pcm = NULL;
7215 }
7216 }
7217 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05307218 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07007219 return ret;
7220}
7221
7222static int out_get_mmap_position(const struct audio_stream_out *stream,
7223 struct audio_mmap_position *position)
7224{
7225 struct stream_out *out = (struct stream_out *)stream;
7226 ALOGVV("%s", __func__);
7227 if (position == NULL) {
7228 return -EINVAL;
7229 }
7230 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08007231 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07007232 return -ENOSYS;
7233 }
7234 if (out->pcm == NULL) {
7235 return -ENOSYS;
7236 }
7237
7238 struct timespec ts = { 0, 0 };
7239 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
7240 if (ret < 0) {
7241 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
7242 return ret;
7243 }
Phil Burkfe17efd2019-03-25 10:23:35 -07007244 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7245 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07007246 return 0;
7247}
7248
7249
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007250/** audio_stream_in implementation **/
7251static uint32_t in_get_sample_rate(const struct audio_stream *stream)
7252{
7253 struct stream_in *in = (struct stream_in *)stream;
7254
7255 return in->config.rate;
7256}
7257
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007258static int in_set_sample_rate(struct audio_stream *stream __unused,
7259 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007260{
7261 return -ENOSYS;
7262}
7263
7264static size_t in_get_buffer_size(const struct audio_stream *stream)
7265{
7266 struct stream_in *in = (struct stream_in *)stream;
7267
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007268 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
7269 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07007270 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
Raghu Bankapur37cbf382022-12-01 09:30:00 +05307271 return audio_extn_compr_cap_get_buffer_size(pcm_format_to_audio_format(in->config.format));
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307272 else if(audio_extn_cin_attached_usecase(in))
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307273 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007274
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007275 return in->config.period_size * in->af_period_multiplier *
7276 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007277}
7278
7279static uint32_t in_get_channels(const struct audio_stream *stream)
7280{
7281 struct stream_in *in = (struct stream_in *)stream;
7282
7283 return in->channel_mask;
7284}
7285
7286static audio_format_t in_get_format(const struct audio_stream *stream)
7287{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007288 struct stream_in *in = (struct stream_in *)stream;
7289
7290 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007291}
7292
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007293static int in_set_format(struct audio_stream *stream __unused,
7294 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007295{
7296 return -ENOSYS;
7297}
7298
7299static int in_standby(struct audio_stream *stream)
7300{
7301 struct stream_in *in = (struct stream_in *)stream;
7302 struct audio_device *adev = in->dev;
7303 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307304 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
7305 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07007306 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307307
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007308 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007309 if (!in->standby && in->is_st_session) {
7310 ALOGD("%s: sound trigger pcm stop lab", __func__);
7311 audio_extn_sound_trigger_stop_lab(in);
George Gao3018ede2019-10-23 13:23:00 -07007312 if (adev->num_va_sessions > 0)
7313 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007314 in->standby = 1;
7315 }
7316
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007317 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007318 if (adev->adm_deregister_stream)
7319 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
7320
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08007321 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007322 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08007323 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08007324 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08007325 voice_extn_compress_voip_close_input_stream(stream);
7326 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07007327 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
7328 do_stop = in->capture_started;
7329 in->capture_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07007330 if (in->mmap_shared_memory_fd >= 0) {
7331 ALOGV("%s: closing mmap_shared_memory_fd = %d",
7332 __func__, in->mmap_shared_memory_fd);
7333 close(in->mmap_shared_memory_fd);
7334 in->mmap_shared_memory_fd = -1;
7335 }
Zhou Songa8895042016-07-05 17:54:22 +08007336 } else {
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307337 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05307338 audio_extn_cin_close_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08007339 }
7340
Arun Mirpuri5d170872019-03-26 13:21:31 -07007341 if (in->pcm) {
7342 ATRACE_BEGIN("pcm_in_close");
7343 pcm_close(in->pcm);
7344 ATRACE_END();
7345 in->pcm = NULL;
7346 }
7347
Carter Hsu2e429db2019-05-14 18:50:52 +08007348 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08007349 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08007350
George Gao3018ede2019-10-23 13:23:00 -07007351 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
7352 if (adev->num_va_sessions > 0)
7353 adev->num_va_sessions--;
7354 }
Quinn Malef6050362019-01-30 15:55:40 -08007355
Eric Laurent150dbfe2013-02-27 14:31:02 -08007356 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007357 }
7358 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07007359 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007360 return status;
7361}
7362
Aalique Grahame22e49102018-12-18 14:23:57 -08007363static int in_dump(const struct audio_stream *stream,
7364 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007365{
Aalique Grahame22e49102018-12-18 14:23:57 -08007366 struct stream_in *in = (struct stream_in *)stream;
7367
7368 // We try to get the lock for consistency,
7369 // but it isn't necessary for these variables.
7370 // If we're not in standby, we may be blocked on a read.
7371 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
7372 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
7373 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
7374 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
Dechen Chai22768452021-07-30 09:29:16 +05307375#ifndef LINUX_ENABLED
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007376 char buffer[256]; // for statistics formatting
7377 if (in->start_latency_ms.n > 0) {
7378 simple_stats_to_string(&in->start_latency_ms, buffer, sizeof(buffer));
7379 dprintf(fd, " Start latency ms: %s\n", buffer);
7380 }
Dechen Chai22768452021-07-30 09:29:16 +05307381#endif
Aalique Grahame22e49102018-12-18 14:23:57 -08007382 if (locked) {
7383 pthread_mutex_unlock(&in->lock);
7384 }
Dechen Chai22768452021-07-30 09:29:16 +05307385#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -08007386 // dump error info
7387 (void)error_log_dump(
7388 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Dechen Chai22768452021-07-30 09:29:16 +05307389#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007390 return 0;
7391}
7392
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307393static void in_snd_mon_cb(void * stream, struct str_parms * parms)
7394{
7395 if (!stream || !parms)
7396 return;
7397
7398 struct stream_in *in = (struct stream_in *)stream;
7399 struct audio_device *adev = in->dev;
7400
7401 card_status_t status;
7402 int card;
7403 if (parse_snd_card_status(parms, &card, &status) < 0)
7404 return;
7405
7406 pthread_mutex_lock(&adev->lock);
7407 bool valid_cb = (card == adev->snd_card);
7408 pthread_mutex_unlock(&adev->lock);
7409
7410 if (!valid_cb)
7411 return;
7412
7413 lock_input_stream(in);
7414 if (in->card_status != status)
7415 in->card_status = status;
7416 pthread_mutex_unlock(&in->lock);
7417
7418 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
7419 use_case_table[in->usecase],
7420 status == CARD_STATUS_OFFLINE ? "offline" : "online");
7421
7422 // a better solution would be to report error back to AF and let
7423 // it put the stream to standby
7424 if (status == CARD_STATUS_OFFLINE)
7425 in_standby(&in->stream.common);
7426
7427 return;
7428}
7429
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007430int route_input_stream(struct stream_in *in,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007431 struct listnode *devices,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007432 audio_source_t source)
7433{
7434 struct audio_device *adev = in->dev;
7435 int ret = 0;
7436
7437 lock_input_stream(in);
7438 pthread_mutex_lock(&adev->lock);
7439
7440 /* no audio source uses val == 0 */
7441 if ((in->source != source) && (source != AUDIO_SOURCE_DEFAULT)) {
7442 in->source = source;
7443 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
7444 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
7445 (voice_extn_compress_voip_is_format_supported(in->format)) &&
7446 (in->config.rate == 8000 || in->config.rate == 16000 ||
7447 in->config.rate == 32000 || in->config.rate == 48000 ) &&
7448 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
7449 ret = voice_extn_compress_voip_open_input_stream(in);
7450 if (ret != 0) {
7451 ALOGE("%s: Compress voip input cannot be opened, error:%d",
7452 __func__, ret);
7453 }
7454 }
7455 }
7456
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007457 if (!compare_devices(&in->device_list, devices) && !list_empty(devices) &&
7458 is_audio_in_device_type(devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007459 // Workaround: If routing to an non existing usb device, fail gracefully
7460 // The routing request will otherwise block during 10 second
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007461 struct str_parms *usb_addr =
7462 str_parms_create_str(get_usb_device_address(devices));
7463 if (is_usb_in_device_type(devices) && usb_addr &&
Weiyin Jiangabedea32020-12-09 12:49:19 +08007464 !audio_extn_usb_connected(NULL)) {
7465 ALOGW("%s: ignoring rerouting to non existing USB", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007466 ret = -ENOSYS;
7467 } else {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007468 /* If recording is in progress, change the tx device to new device */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007469 assign_devices(&in->device_list, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007470 if (!in->standby && !in->is_st_session) {
7471 ALOGV("update input routing change");
7472 // inform adm before actual routing to prevent glitches.
7473 if (adev->adm_on_routing_change) {
7474 adev->adm_on_routing_change(adev->adm_data,
7475 in->capture_handle);
7476 ret = select_devices(adev, in->usecase);
7477 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7478 adev->adm_routing_changed = true;
7479 }
7480 }
7481 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007482 if (usb_addr)
7483 str_parms_destroy(usb_addr);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007484 }
7485 pthread_mutex_unlock(&adev->lock);
7486 pthread_mutex_unlock(&in->lock);
7487
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07007488 ALOGV("%s: exit: status(%d)", __func__, ret);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007489 return ret;
7490}
7491
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007492static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
7493{
7494 struct stream_in *in = (struct stream_in *)stream;
7495 struct audio_device *adev = in->dev;
7496 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007497 char value[32];
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307498 int err = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007499
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307500 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007501 parms = str_parms_create_str(kvpairs);
7502
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307503 if (!parms)
7504 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007505 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08007506 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007507
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307508 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
7509 if (err >= 0) {
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307510 strlcpy(in->profile, value, sizeof(in->profile));
7511 ALOGV("updating stream profile with value '%s'", in->profile);
7512 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
7513 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007514 &in->device_list, in->flags, in->format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307515 in->sample_rate, in->bit_width,
7516 in->profile, &in->app_type_cfg);
7517 }
7518
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007519 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08007520 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007521
7522 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307523error:
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307524 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007525}
7526
7527static char* in_get_parameters(const struct audio_stream *stream,
7528 const char *keys)
7529{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007530 struct stream_in *in = (struct stream_in *)stream;
7531 struct str_parms *query = str_parms_create_str(keys);
7532 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007533 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007534
7535 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08007536 if (reply) {
7537 str_parms_destroy(reply);
7538 }
7539 if (query) {
7540 str_parms_destroy(query);
7541 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007542 ALOGE("in_get_parameters: failed to create query or reply");
7543 return NULL;
7544 }
7545
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007546 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007547
7548 voice_extn_in_get_parameters(in, query, reply);
7549
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007550 stream_get_parameter_channels(query, reply,
7551 &in->supported_channel_masks[0]);
7552 stream_get_parameter_formats(query, reply,
7553 &in->supported_formats[0]);
7554 stream_get_parameter_rates(query, reply,
7555 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007556 str = str_parms_to_str(reply);
7557 str_parms_destroy(query);
7558 str_parms_destroy(reply);
7559
7560 ALOGV("%s: exit: returns - %s", __func__, str);
7561 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007562}
7563
Aalique Grahame22e49102018-12-18 14:23:57 -08007564static int in_set_gain(struct audio_stream_in *stream,
7565 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007566{
Aalique Grahame22e49102018-12-18 14:23:57 -08007567 struct stream_in *in = (struct stream_in *)stream;
7568 char mixer_ctl_name[128];
7569 struct mixer_ctl *ctl;
7570 int ctl_value;
7571
7572 ALOGV("%s: gain %f", __func__, gain);
7573
7574 if (stream == NULL)
7575 return -EINVAL;
7576
7577 /* in_set_gain() only used to silence MMAP capture for now */
7578 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
7579 return -ENOSYS;
7580
7581 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
7582
7583 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
7584 if (!ctl) {
7585 ALOGW("%s: Could not get ctl for mixer cmd - %s",
7586 __func__, mixer_ctl_name);
7587 return -ENOSYS;
7588 }
7589
7590 if (gain < RECORD_GAIN_MIN)
7591 gain = RECORD_GAIN_MIN;
7592 else if (gain > RECORD_GAIN_MAX)
7593 gain = RECORD_GAIN_MAX;
7594 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
7595
7596 mixer_ctl_set_value(ctl, 0, ctl_value);
7597
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007598 return 0;
7599}
7600
7601static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
7602 size_t bytes)
7603{
7604 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05307605
7606 if (in == NULL) {
7607 ALOGE("%s: stream_in ptr is NULL", __func__);
7608 return -EINVAL;
7609 }
7610
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007611 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05307612 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307613 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007614
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007615 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05307616
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007617 if (in->is_st_session) {
7618 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
7619 /* Read from sound trigger HAL */
7620 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08007621 if (in->standby) {
George Gao3018ede2019-10-23 13:23:00 -07007622 if (adev->num_va_sessions < UINT_MAX)
7623 adev->num_va_sessions++;
Quinn Malef6050362019-01-30 15:55:40 -08007624 in->standby = 0;
7625 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007626 pthread_mutex_unlock(&in->lock);
7627 return bytes;
7628 }
7629
Haynes Mathew George16081042017-05-31 17:16:49 -07007630 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
7631 ret = -ENOSYS;
7632 goto exit;
7633 }
7634
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007635 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
7636 !in->standby && adev->adm_routing_changed) {
7637 ret = -ENOSYS;
7638 goto exit;
7639 }
7640
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007641 if (in->standby) {
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007642 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
7643
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007644 pthread_mutex_lock(&adev->lock);
7645 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
7646 ret = voice_extn_compress_voip_start_input_stream(in);
7647 else
7648 ret = start_input_stream(in);
George Gao3018ede2019-10-23 13:23:00 -07007649 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
7650 if (adev->num_va_sessions < UINT_MAX)
7651 adev->num_va_sessions++;
7652 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007653 pthread_mutex_unlock(&adev->lock);
7654 if (ret != 0) {
7655 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007656 }
7657 in->standby = 0;
Dechen Chai22768452021-07-30 09:29:16 +05307658#ifndef LINUX_ENABLED
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007659 // log startup time in ms.
7660 simple_stats_log(
7661 &in->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Dechen Chai22768452021-07-30 09:29:16 +05307662#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007663 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007664
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05307665 /* Avoid read if capture_stopped is set */
7666 if (android_atomic_acquire_load(&(in->capture_stopped)) > 0) {
7667 ALOGD("%s: force stopped catpure session, ignoring read request", __func__);
7668 ret = -EINVAL;
7669 goto exit;
7670 }
7671
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007672 // what's the duration requested by the client?
7673 long ns = 0;
7674
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307675 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007676 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
7677 in->config.rate;
7678
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007679 ret = request_in_focus(in, ns);
7680 if (ret != 0)
7681 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007682 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007683
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307684 if (audio_extn_cin_attached_usecase(in)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307685 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
7686 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307687 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007688 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307689 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07007690 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007691 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007692 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07007693 } else if (audio_extn_ffv_get_stream() == in) {
7694 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307695 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007696 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307697 /* data from DSP comes in 24_8 format, convert it to 8_24 */
7698 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
7699 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
7700 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307701 ret = -EINVAL;
7702 goto exit;
7703 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307704 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307705 ret = -errno;
7706 }
7707 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307708 /* bytes read is always set to bytes for non compress usecases */
7709 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007710 }
7711
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007712 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007713
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007714 /*
Quinn Malef6050362019-01-30 15:55:40 -08007715 * Instead of writing zeroes here, we could trust the hardware to always
7716 * provide zeroes when muted. This is also muted with voice recognition
7717 * usecases so that other clients do not have access to voice recognition
7718 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007719 */
Quinn Malef6050362019-01-30 15:55:40 -08007720 if ((ret == 0 && voice_get_mic_mute(adev) &&
7721 !voice_is_in_call_rec_stream(in) &&
Zhou Song62ea0282020-03-22 19:53:01 +08007722 (in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY &&
Manoj Kumar N D54cab152023-01-27 16:41:55 +05307723 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY2 &&
7724 in->source != AUDIO_SOURCE_FM_TUNER &&
7725 !is_single_device_type_equal(&in->device_list, AUDIO_DEVICE_IN_FM_TUNER))) ||
Quinn Malef6050362019-01-30 15:55:40 -08007726 (adev->num_va_sessions &&
7727 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
7728 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
7729 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007730 memset(buffer, 0, bytes);
7731
7732exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307733 frame_size = audio_stream_in_frame_size(stream);
7734 if (frame_size > 0)
7735 in->frames_read += bytes_read/frame_size;
7736
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007737 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307738 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007739 pthread_mutex_unlock(&in->lock);
7740
7741 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307742 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307743 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307744 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307745 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307746 in->standby = true;
7747 }
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307748 if (!audio_extn_cin_attached_usecase(in)) {
Sharad Sangled17c9122017-03-20 15:58:52 +05307749 bytes_read = bytes;
7750 memset(buffer, 0, bytes);
7751 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007752 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007753 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7754 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007755 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05307756 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05307757 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007758 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307759 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007760}
7761
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007762static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007763{
7764 return 0;
7765}
7766
Aalique Grahame22e49102018-12-18 14:23:57 -08007767static int in_get_capture_position(const struct audio_stream_in *stream,
7768 int64_t *frames, int64_t *time)
7769{
7770 if (stream == NULL || frames == NULL || time == NULL) {
7771 return -EINVAL;
7772 }
7773 struct stream_in *in = (struct stream_in *)stream;
7774 int ret = -ENOSYS;
7775
7776 lock_input_stream(in);
7777 // note: ST sessions do not close the alsa pcm driver synchronously
7778 // on standby. Therefore, we may return an error even though the
7779 // pcm stream is still opened.
7780 if (in->standby) {
7781 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
7782 "%s stream in standby but pcm not NULL for non ST session", __func__);
7783 goto exit;
7784 }
7785 if (in->pcm) {
7786 struct timespec timestamp;
7787 unsigned int avail;
7788 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
7789 *frames = in->frames_read + avail;
Robert Lee58215542019-07-15 20:55:12 +08007790 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec
George Gao9ba8a142020-07-23 14:30:03 -07007791 - platform_capture_latency(in) * 1000LL;
Kakanaboina Ramanjaneyulu8cedb092021-03-15 15:55:29 +05307792 //Adjustment accounts for A2dp decoder latency for recording usecase
7793 // Note: decoder latency is returned in ms, while platform_capture_latency in ns.
7794 if (is_a2dp_in_device_type(&in->device_list))
7795 *time -= audio_extn_a2dp_get_decoder_latency() * 1000000LL;
Aalique Grahame22e49102018-12-18 14:23:57 -08007796 ret = 0;
7797 }
7798 }
7799exit:
7800 pthread_mutex_unlock(&in->lock);
7801 return ret;
7802}
7803
Carter Hsu2e429db2019-05-14 18:50:52 +08007804static int in_update_effect_list(bool add, effect_handle_t effect,
7805 struct listnode *head)
7806{
7807 struct listnode *node;
7808 struct in_effect_list *elist = NULL;
7809 struct in_effect_list *target = NULL;
7810 int ret = 0;
7811
7812 if (!head)
7813 return ret;
7814
7815 list_for_each(node, head) {
7816 elist = node_to_item(node, struct in_effect_list, list);
7817 if (elist->handle == effect) {
7818 target = elist;
7819 break;
7820 }
7821 }
7822
7823 if (add) {
7824 if (target) {
7825 ALOGD("effect %p already exist", effect);
7826 return ret;
7827 }
7828
7829 target = (struct in_effect_list *)
7830 calloc(1, sizeof(struct in_effect_list));
7831
7832 if (!target) {
7833 ALOGE("%s:fail to allocate memory", __func__);
7834 return -ENOMEM;
7835 }
7836
7837 target->handle = effect;
7838 list_add_tail(head, &target->list);
7839 } else {
7840 if (target) {
7841 list_remove(&target->list);
7842 free(target);
7843 }
7844 }
7845
7846 return ret;
7847}
7848
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007849static int add_remove_audio_effect(const struct audio_stream *stream,
7850 effect_handle_t effect,
7851 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007852{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007853 struct stream_in *in = (struct stream_in *)stream;
7854 int status = 0;
7855 effect_descriptor_t desc;
7856
7857 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007858 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
7859
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007860 if (status != 0)
7861 return status;
7862
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007863 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007864 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08007865 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08007866 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
7867 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007868 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08007869
7870 in_update_effect_list(enable, effect, &in->aec_list);
7871 enable = !list_empty(&in->aec_list);
7872 if (enable == in->enable_aec)
7873 goto exit;
7874
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007875 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007876 ALOGD("AEC enable %d", enable);
7877
Aalique Grahame22e49102018-12-18 14:23:57 -08007878 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7879 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
7880 in->dev->enable_voicerx = enable;
7881 struct audio_usecase *usecase;
7882 struct listnode *node;
7883 list_for_each(node, &in->dev->usecase_list) {
7884 usecase = node_to_item(node, struct audio_usecase, list);
7885 if (usecase->type == PCM_PLAYBACK)
7886 select_devices(in->dev, usecase->id);
7887 }
7888 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007889 if (!in->standby) {
7890 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
7891 select_devices(in->dev, in->usecase);
7892 }
7893
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007894 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007895 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
7896
7897 in_update_effect_list(enable, effect, &in->ns_list);
7898 enable = !list_empty(&in->ns_list);
7899 if (enable == in->enable_ns)
7900 goto exit;
7901
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007902 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007903 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007904 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08007905 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Ramu Gottipatifa5be522021-12-28 19:18:21 +05307906 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
kunleizd96526c2018-04-09 11:12:32 +08007907 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007908 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
7909 select_devices(in->dev, in->usecase);
7910 } else
7911 select_devices(in->dev, in->usecase);
7912 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007913 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007914exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007915 pthread_mutex_unlock(&in->dev->lock);
7916 pthread_mutex_unlock(&in->lock);
7917
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007918 return 0;
7919}
7920
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007921static int in_add_audio_effect(const struct audio_stream *stream,
7922 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007923{
Eric Laurent994a6932013-07-17 11:51:42 -07007924 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007925 return add_remove_audio_effect(stream, effect, true);
7926}
7927
7928static int in_remove_audio_effect(const struct audio_stream *stream,
7929 effect_handle_t effect)
7930{
Eric Laurent994a6932013-07-17 11:51:42 -07007931 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007932 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007933}
7934
Haynes Mathew George16081042017-05-31 17:16:49 -07007935static int in_stop(const struct audio_stream_in* stream)
7936{
7937 struct stream_in *in = (struct stream_in *)stream;
7938 struct audio_device *adev = in->dev;
7939
7940 int ret = -ENOSYS;
7941 ALOGV("%s", __func__);
7942 pthread_mutex_lock(&adev->lock);
7943 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7944 in->capture_started && in->pcm != NULL) {
7945 pcm_stop(in->pcm);
7946 ret = stop_input_stream(in);
7947 in->capture_started = false;
7948 }
7949 pthread_mutex_unlock(&adev->lock);
7950 return ret;
7951}
7952
7953static int in_start(const struct audio_stream_in* stream)
7954{
7955 struct stream_in *in = (struct stream_in *)stream;
7956 struct audio_device *adev = in->dev;
7957 int ret = -ENOSYS;
7958
7959 ALOGV("%s in %p", __func__, in);
7960 pthread_mutex_lock(&adev->lock);
7961 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7962 !in->capture_started && in->pcm != NULL) {
7963 if (!in->capture_started) {
7964 ret = start_input_stream(in);
7965 if (ret == 0) {
7966 in->capture_started = true;
7967 }
7968 }
7969 }
7970 pthread_mutex_unlock(&adev->lock);
7971 return ret;
7972}
7973
Phil Burke0a86d12019-02-16 22:28:11 -08007974// Read offset for the positional timestamp from a persistent vendor property.
7975// This is to workaround apparent inaccuracies in the timing information that
7976// is used by the AAudio timing model. The inaccuracies can cause glitches.
7977static int64_t in_get_mmap_time_offset() {
7978 const int32_t kDefaultOffsetMicros = 0;
7979 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08007980 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08007981 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
7982 return mmap_time_offset_micros * (int64_t)1000;
7983}
7984
Haynes Mathew George16081042017-05-31 17:16:49 -07007985static int in_create_mmap_buffer(const struct audio_stream_in *stream,
7986 int32_t min_size_frames,
7987 struct audio_mmap_buffer_info *info)
7988{
7989 struct stream_in *in = (struct stream_in *)stream;
7990 struct audio_device *adev = in->dev;
7991 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07007992 unsigned int offset1 = 0;
7993 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007994 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07007995 uint32_t mmap_size = 0;
7996 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007997
7998 pthread_mutex_lock(&adev->lock);
7999 ALOGV("%s in %p", __func__, in);
8000
Sharad Sanglec6f32552018-05-04 16:15:38 +05308001 if (CARD_STATUS_OFFLINE == in->card_status||
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05008002 CARD_STATUS_OFFLINE == adev->card_status ||
8003 POWER_POLICY_STATUS_OFFLINE == adev->in_power_policy) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05308004 ALOGW("in->card_status or adev->card_status offline, try again");
8005 ret = -EIO;
8006 goto exit;
8007 }
8008
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05308009 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07008010 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
8011 ret = -EINVAL;
8012 goto exit;
8013 }
8014 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
8015 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
8016 ALOGV("%s in %p", __func__, in);
8017 ret = -ENOSYS;
8018 goto exit;
8019 }
8020 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
8021 if (in->pcm_device_id < 0) {
8022 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
8023 __func__, in->pcm_device_id, in->usecase);
8024 ret = -EINVAL;
8025 goto exit;
8026 }
8027
8028 adjust_mmap_period_count(&in->config, min_size_frames);
8029
8030 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
8031 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
8032 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
8033 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05308034 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05308035 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
8036 in->card_status = CARD_STATUS_OFFLINE;
8037 adev->card_status = CARD_STATUS_OFFLINE;
8038 ret = -EIO;
8039 goto exit;
8040 }
8041
Haynes Mathew George16081042017-05-31 17:16:49 -07008042 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
8043 step = "open";
8044 ret = -ENODEV;
8045 goto exit;
8046 }
8047
8048 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
8049 if (ret < 0) {
8050 step = "begin";
8051 goto exit;
8052 }
Haynes Mathew George16081042017-05-31 17:16:49 -07008053
juyuchen626833d2019-06-04 16:48:02 +08008054 info->flags = 0;
Arun Mirpuri5d170872019-03-26 13:21:31 -07008055 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
8056 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
8057 info->burst_size_frames = in->config.period_size;
8058 ret = platform_get_mmap_data_fd(adev->platform,
8059 in->pcm_device_id, 1 /*capture*/,
8060 &info->shared_memory_fd,
8061 &mmap_size);
8062 if (ret < 0) {
8063 // Fall back to non exclusive mode
8064 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
8065 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07008066 in->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
8067 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, in->mmap_shared_memory_fd);
8068
Arun Mirpuri5d170872019-03-26 13:21:31 -07008069 if (mmap_size < buffer_size) {
8070 step = "mmap";
8071 goto exit;
8072 }
juyuchen626833d2019-06-04 16:48:02 +08008073 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Arun Mirpuri5d170872019-03-26 13:21:31 -07008074 }
8075
8076 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07008077
8078 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
8079 if (ret < 0) {
8080 step = "commit";
8081 goto exit;
8082 }
8083
Phil Burke0a86d12019-02-16 22:28:11 -08008084 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
8085
Haynes Mathew George16081042017-05-31 17:16:49 -07008086 in->standby = false;
8087 ret = 0;
8088
8089 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
8090 __func__, info->shared_memory_address, info->buffer_size_frames);
8091
8092exit:
8093 if (ret != 0) {
8094 if (in->pcm == NULL) {
8095 ALOGE("%s: %s - %d", __func__, step, ret);
8096 } else {
8097 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
8098 pcm_close(in->pcm);
8099 in->pcm = NULL;
8100 }
8101 }
8102 pthread_mutex_unlock(&adev->lock);
8103 return ret;
8104}
8105
8106static int in_get_mmap_position(const struct audio_stream_in *stream,
8107 struct audio_mmap_position *position)
8108{
8109 struct stream_in *in = (struct stream_in *)stream;
8110 ALOGVV("%s", __func__);
8111 if (position == NULL) {
8112 return -EINVAL;
8113 }
Gautam Manam34d1f542021-01-05 20:24:37 +05308114 lock_input_stream(in);
Haynes Mathew George16081042017-05-31 17:16:49 -07008115 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
Gautam Manam34d1f542021-01-05 20:24:37 +05308116 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07008117 return -ENOSYS;
8118 }
8119 if (in->pcm == NULL) {
Gautam Manam34d1f542021-01-05 20:24:37 +05308120 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07008121 return -ENOSYS;
8122 }
8123 struct timespec ts = { 0, 0 };
8124 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
8125 if (ret < 0) {
8126 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
Gautam Manam34d1f542021-01-05 20:24:37 +05308127 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07008128 return ret;
8129 }
Phil Burke0a86d12019-02-16 22:28:11 -08008130 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
8131 + in->mmap_time_offset_nanos;
Gautam Manam34d1f542021-01-05 20:24:37 +05308132 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07008133 return 0;
8134}
8135
Naresh Tannirudcb47c52018-06-25 16:23:32 +05308136static int in_get_active_microphones(const struct audio_stream_in *stream,
8137 struct audio_microphone_characteristic_t *mic_array,
8138 size_t *mic_count) {
8139 struct stream_in *in = (struct stream_in *)stream;
8140 struct audio_device *adev = in->dev;
8141 ALOGVV("%s", __func__);
8142
8143 lock_input_stream(in);
8144 pthread_mutex_lock(&adev->lock);
8145 int ret = platform_get_active_microphones(adev->platform,
8146 audio_channel_count_from_in_mask(in->channel_mask),
8147 in->usecase, mic_array, mic_count);
8148 pthread_mutex_unlock(&adev->lock);
8149 pthread_mutex_unlock(&in->lock);
8150
8151 return ret;
8152}
8153
8154static int adev_get_microphones(const struct audio_hw_device *dev,
8155 struct audio_microphone_characteristic_t *mic_array,
8156 size_t *mic_count) {
8157 struct audio_device *adev = (struct audio_device *)dev;
8158 ALOGVV("%s", __func__);
8159
8160 pthread_mutex_lock(&adev->lock);
8161 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
8162 pthread_mutex_unlock(&adev->lock);
8163
8164 return ret;
8165}
juyuchendb308c22019-01-21 11:57:17 -07008166
8167static void in_update_sink_metadata(struct audio_stream_in *stream,
8168 const struct sink_metadata *sink_metadata) {
8169
8170 if (stream == NULL
8171 || sink_metadata == NULL
8172 || sink_metadata->tracks == NULL) {
8173 return;
8174 }
8175
8176 int error = 0;
8177 struct stream_in *in = (struct stream_in *)stream;
8178 struct audio_device *adev = in->dev;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008179 struct listnode devices;
8180
8181 list_init(&devices);
juyuchendb308c22019-01-21 11:57:17 -07008182
8183 if (sink_metadata->track_count != 0)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008184 reassign_device_list(&devices, sink_metadata->tracks->dest_device, "");
juyuchendb308c22019-01-21 11:57:17 -07008185
8186 lock_input_stream(in);
8187 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008188 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, get_device_types(&devices));
juyuchendb308c22019-01-21 11:57:17 -07008189
Zhou Song503196b2021-07-23 17:31:05 +08008190 if ((in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY ||
8191 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2) &&
8192 !list_empty(&devices) &&
8193 adev->voice_tx_output != NULL) {
juyuchendb308c22019-01-21 11:57:17 -07008194 /* Use the rx device from afe-proxy record to route voice call because
8195 there is no routing if tx device is on primary hal and rx device
8196 is on other hal during voice call. */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008197 assign_devices(&adev->voice_tx_output->device_list, &devices);
juyuchendb308c22019-01-21 11:57:17 -07008198
8199 if (!voice_is_call_state_active(adev)) {
8200 if (adev->mode == AUDIO_MODE_IN_CALL) {
8201 adev->current_call_output = adev->voice_tx_output;
8202 error = voice_start_call(adev);
8203 if (error != 0)
8204 ALOGE("%s: start voice call failed %d", __func__, error);
8205 }
8206 } else {
8207 adev->current_call_output = adev->voice_tx_output;
8208 voice_update_devices_for_all_voice_usecases(adev);
8209 }
8210 }
8211
Zhenlin Lian4f947842022-05-14 15:50:52 +05308212 clear_devices(&devices);
juyuchendb308c22019-01-21 11:57:17 -07008213 pthread_mutex_unlock(&adev->lock);
8214 pthread_mutex_unlock(&in->lock);
8215}
8216
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308217int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07008218 audio_io_handle_t handle,
8219 audio_devices_t devices,
8220 audio_output_flags_t flags,
8221 struct audio_config *config,
8222 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04008223 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008224{
8225 struct audio_device *adev = (struct audio_device *)dev;
8226 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05308227 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008228 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008229 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05308230 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008231 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
8232 bool is_usb_dev = audio_is_usb_out_device(devices) &&
8233 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
8234 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008235 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07008236 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
8237 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008238 bool force_haptic_path =
8239 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07008240 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008241#ifdef AUDIO_GKI_ENABLED
8242 __s32 *generic_dec;
8243#endif
Weiyin Jiang906db3c2021-03-02 13:17:04 +08008244 pthread_mutexattr_t latch_attr;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008245
kunleizdff872d2018-08-20 14:40:33 +08008246 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08008247 is_usb_dev = false;
8248 devices = AUDIO_DEVICE_OUT_SPEAKER;
8249 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
8250 __func__, devices);
Mingshu Pangdbd20562019-11-25 18:04:39 +08008251 if (config->format == AUDIO_FORMAT_DEFAULT)
8252 config->format = AUDIO_FORMAT_PCM_16_BIT;
8253 if (config->sample_rate == 0)
8254 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8255 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8256 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
kunleizd6a9e0c2018-07-30 15:38:52 +08008257 }
8258
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008259 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05308260
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008261 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
8262
Mingming Yin3a941d42016-02-17 18:08:05 -08008263 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04008264 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
8265 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308266
8267
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008268 if (!out) {
8269 return -ENOMEM;
8270 }
8271
Haynes Mathew George204045b2015-02-25 20:32:03 -08008272 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07008273 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Weiyin Jiang906db3c2021-03-02 13:17:04 +08008274 pthread_mutexattr_init(&latch_attr);
8275 pthread_mutexattr_settype(&latch_attr, PTHREAD_MUTEX_RECURSIVE);
8276 pthread_mutex_init(&out->latch_lock, &latch_attr);
8277 pthread_mutexattr_destroy(&latch_attr);
Zhou Song48453a02018-01-10 17:50:59 +08008278 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08008279 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
8280
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008281 if (devices == AUDIO_DEVICE_NONE)
8282 devices = AUDIO_DEVICE_OUT_SPEAKER;
8283
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008284 out->flags = flags;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008285 list_init(&out->device_list);
8286 update_device_list(&out->device_list, devices, address, true /* add devices */);
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07008287 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07008288 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008289 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05308290 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05308291 if (out->channel_mask == AUDIO_CHANNEL_NONE)
8292 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
8293 else
8294 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07008295 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07008296 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08008297 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308298 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308299 out->started = 0;
Zhou Songbaddf9f2020-11-20 13:57:39 +08008300 out->a2dp_muted = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008301 out->hal_output_suspend_supported = 0;
8302 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05308303 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05308304 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05308305 out->pspd_coeff_sent = false;
Phil Burkd898ba62019-06-20 12:49:01 -07008306 out->mmap_shared_memory_fd = -1; // not open
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008307
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05308308 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05308309 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07008310 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
8311
Aalique Grahame22e49102018-12-18 14:23:57 -08008312 if (direct_dev &&
8313 (audio_is_linear_pcm(out->format) ||
8314 config->format == AUDIO_FORMAT_DEFAULT) &&
8315 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
8316 audio_format_t req_format = config->format;
8317 audio_channel_mask_t req_channel_mask = config->channel_mask;
8318 uint32_t req_sample_rate = config->sample_rate;
8319
8320 pthread_mutex_lock(&adev->lock);
8321 if (is_hdmi) {
8322 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
8323 ret = read_hdmi_sink_caps(out);
8324 if (config->sample_rate == 0)
8325 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8326 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8327 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
8328 if (config->format == AUDIO_FORMAT_DEFAULT)
8329 config->format = AUDIO_FORMAT_PCM_16_BIT;
8330 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008331 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
8332 &config->format,
8333 &out->supported_formats[0],
8334 MAX_SUPPORTED_FORMATS,
8335 &config->channel_mask,
8336 &out->supported_channel_masks[0],
8337 MAX_SUPPORTED_CHANNEL_MASKS,
8338 &config->sample_rate,
8339 &out->supported_sample_rates[0],
8340 MAX_SUPPORTED_SAMPLE_RATES);
8341 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008342 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008343
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008344 pthread_mutex_unlock(&adev->lock);
8345 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08008346 if (ret == -ENOSYS) {
8347 /* ignore and go with default */
8348 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08008349 }
8350 // For MMAP NO IRQ, allow conversions in ADSP
8351 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
8352 goto error_open;
8353 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008354 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08008355 goto error_open;
8356 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008357
8358 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
8359 config->sample_rate = req_sample_rate;
8360 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
8361 config->channel_mask = req_channel_mask;
8362 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
8363 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08008364 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008365
8366 out->sample_rate = config->sample_rate;
8367 out->channel_mask = config->channel_mask;
8368 out->format = config->format;
8369 if (is_hdmi) {
8370 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
8371 out->config = pcm_config_hdmi_multi;
8372 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8373 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8374 out->config = pcm_config_mmap_playback;
8375 out->stream.start = out_start;
8376 out->stream.stop = out_stop;
8377 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8378 out->stream.get_mmap_position = out_get_mmap_position;
8379 } else {
8380 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
8381 out->config = pcm_config_hifi;
8382 }
8383
8384 out->config.rate = out->sample_rate;
8385 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
8386 if (is_hdmi) {
8387 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
8388 audio_bytes_per_sample(out->format));
8389 }
8390 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08008391 }
8392
Derek Chenf6318be2017-06-12 17:16:24 -04008393 /* validate bus device address */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008394 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008395 /* extract car audio stream index */
8396 out->car_audio_stream =
8397 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
8398 if (out->car_audio_stream < 0) {
8399 ALOGE("%s: invalid car audio stream %x",
8400 __func__, out->car_audio_stream);
8401 ret = -EINVAL;
8402 goto error_open;
8403 }
Derek Chen5f67a942020-02-24 23:08:13 -08008404 ALOGV("%s: car_audio_stream %x", __func__, out->car_audio_stream);
Derek Chenf6318be2017-06-12 17:16:24 -04008405 }
8406
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008407 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07008408 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008409 if (!voice_extn_is_compress_voip_supported()) {
8410 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
8411 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07008412 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
Lakshman Chaluvarajue7fc9482020-05-30 14:29:29 +05308413 config->channel_mask : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008414 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
8415 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07008416 out->volume_l = INVALID_OUT_VOLUME;
8417 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07008418
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008419 out->config = default_pcm_config_voip_copp;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008420 out->config.rate = out->sample_rate;
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07008421 uint32_t channel_count =
8422 audio_channel_count_from_out_mask(out->channel_mask);
Ramjee Singh968858a2020-08-06 16:30:48 +05308423 out->config.channels = channel_count;
8424
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07008425 uint32_t buffer_size = get_stream_buffer_size(DEFAULT_VOIP_BUF_DURATION_MS,
8426 out->sample_rate, out->format,
8427 channel_count, false);
8428 uint32_t frame_size = audio_bytes_per_sample(out->format) * channel_count;
8429 if (frame_size != 0)
8430 out->config.period_size = buffer_size / frame_size;
8431 else
8432 ALOGW("%s: frame size is 0 for format %#x", __func__, out->format);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008433 }
8434 } else {
8435 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
8436 voice_extn_compress_voip_is_active(out->dev)) &&
8437 (voice_extn_compress_voip_is_config_supported(config))) {
8438 ret = voice_extn_compress_voip_open_output_stream(out);
8439 if (ret != 0) {
8440 ALOGE("%s: Compress voip output cannot be opened, error:%d",
8441 __func__, ret);
8442 goto error_open;
8443 }
Sujin Panicker19027262019-09-16 18:28:06 +05308444 } else {
8445 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8446 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008447 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008448 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008449 } else if (audio_is_linear_pcm(out->format) &&
8450 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
8451 out->channel_mask = config->channel_mask;
8452 out->sample_rate = config->sample_rate;
8453 out->format = config->format;
8454 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
8455 // does this change?
8456 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
8457 out->config.rate = config->sample_rate;
8458 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
8459 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
8460 audio_bytes_per_sample(config->format));
8461 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07008462 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308463 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308464 pthread_mutex_lock(&adev->lock);
8465 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
8466 pthread_mutex_unlock(&adev->lock);
8467
8468 // reject offload during card offline to allow
8469 // fallback to s/w paths
8470 if (offline) {
8471 ret = -ENODEV;
8472 goto error_open;
8473 }
vivek mehta0ea887a2015-08-26 14:01:20 -07008474
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008475 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
8476 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
8477 ALOGE("%s: Unsupported Offload information", __func__);
8478 ret = -EINVAL;
8479 goto error_open;
8480 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008481
Atul Khare3fa6e542017-08-09 00:56:17 +05308482 if (config->offload_info.format == 0)
8483 config->offload_info.format = config->format;
8484 if (config->offload_info.sample_rate == 0)
8485 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008486
Mingming Yin90310102013-11-13 16:57:00 -08008487 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308488 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07008489 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008490 ret = -EINVAL;
8491 goto error_open;
8492 }
8493
Ben Romberger0f8c87b2017-05-24 17:41:11 -07008494 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
8495 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
8496 (audio_extn_passthru_is_passthrough_stream(out)) &&
8497 !((config->sample_rate == 48000) ||
8498 (config->sample_rate == 96000) ||
8499 (config->sample_rate == 192000))) {
8500 ALOGE("%s: Unsupported sample rate %d for audio format %x",
8501 __func__, config->sample_rate, config->offload_info.format);
8502 ret = -EINVAL;
8503 goto error_open;
8504 }
8505
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008506 out->compr_config.codec = (struct snd_codec *)
8507 calloc(1, sizeof(struct snd_codec));
8508
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008509 if (!out->compr_config.codec) {
8510 ret = -ENOMEM;
8511 goto error_open;
8512 }
8513
Dhananjay Kumarac341582017-02-23 23:42:25 +05308514 out->stream.pause = out_pause;
8515 out->stream.resume = out_resume;
8516 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05308517 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05308518 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07008519 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05308520 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07008521 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05308522 } else {
8523 out->usecase = get_offload_usecase(adev, false /* is_compress */);
8524 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07008525 }
vivek mehta446c3962015-09-14 10:57:35 -07008526
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308527 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8528 ALOGD("%s: Setting latency mode to true", __func__);
Meng Wang4c32fb42020-01-16 17:57:11 +08008529#ifdef AUDIO_GKI_ENABLED
8530 /* out->compr_config.codec->reserved[1] is for flags */
8531 out->compr_config.codec->reserved[1] |= audio_extn_utils_get_perf_mode_flag();
8532#else
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308533 out->compr_config.codec->flags |= audio_extn_utils_get_perf_mode_flag();
Meng Wang4c32fb42020-01-16 17:57:11 +08008534#endif
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308535 }
8536
vivek mehta446c3962015-09-14 10:57:35 -07008537 if (out->usecase == USECASE_INVALID) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008538 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Mingming Yin3a941d42016-02-17 18:08:05 -08008539 config->format == 0 && config->sample_rate == 0 &&
8540 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07008541 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08008542 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
8543 } else {
8544 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
8545 ret = -EEXIST;
8546 goto error_open;
8547 }
vivek mehta446c3962015-09-14 10:57:35 -07008548 }
8549
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008550 if (config->offload_info.channel_mask)
8551 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008552 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008553 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008554 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008555 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05308556 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008557 ret = -EINVAL;
8558 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008559 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008560
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008561 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008562 out->sample_rate = config->offload_info.sample_rate;
8563
Mingming Yin3ee55c62014-08-04 14:23:35 -07008564 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008565
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308566 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05308567 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308568 audio_extn_dolby_send_ddp_endp_params(adev);
8569 audio_extn_dolby_set_dmid(adev);
8570 }
vivek mehta0ea887a2015-08-26 14:01:20 -07008571
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008572 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08008573 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008574 out->compr_config.codec->bit_rate =
8575 config->offload_info.bit_rate;
8576 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05308577 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008578 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05308579 /* Update bit width only for non passthrough usecases.
8580 * For passthrough usecases, the output will always be opened @16 bit
8581 */
8582 if (!audio_extn_passthru_is_passthrough_stream(out))
8583 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308584
8585 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
Meng Wang4c32fb42020-01-16 17:57:11 +08008586#ifdef AUDIO_GKI_ENABLED
8587 /* out->compr_config.codec->reserved[1] is for flags */
8588 out->compr_config.codec->reserved[1] |= COMPRESSED_TIMESTAMP_FLAG;
8589 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->reserved[1]);
8590#else
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308591 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
8592 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
Meng Wang4c32fb42020-01-16 17:57:11 +08008593#endif
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308594
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008595 /*TODO: Do we need to change it for passthrough */
8596 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008597
Manish Dewangana6fc5442015-08-24 20:30:31 +05308598 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
8599 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308600 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05308601 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308602 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
8603 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308604
8605 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
8606 AUDIO_FORMAT_PCM) {
8607
8608 /*Based on platform support, configure appropriate alsa format for corresponding
8609 *hal input format.
8610 */
8611 out->compr_config.codec->format = hal_format_to_alsa(
8612 config->offload_info.format);
8613
Ashish Jain83a6cc22016-06-28 14:34:17 +05308614 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05308615 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308616 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308617
Dhananjay Kumarac341582017-02-23 23:42:25 +05308618 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05308619 *hal input format and alsa format might differ based on platform support.
8620 */
8621 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05308622 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308623
8624 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
8625
Deeraj Soman93155a62019-09-30 19:00:37 +05308626 if (property_get_bool("vendor.audio.offload.buffer.duration.enabled", false)) {
8627 if ((config->offload_info.duration_us >= MIN_OFFLOAD_BUFFER_DURATION_MS * 1000) &&
8628 (config->offload_info.duration_us <= MAX_OFFLOAD_BUFFER_DURATION_MS * 1000))
8629 out->info.duration_us = (int64_t)config->offload_info.duration_us;
8630 }
Deeraj Soman65358ab2019-02-07 15:40:49 +05308631
Ashish Jainf1eaa582016-05-23 20:54:24 +05308632 /* Check if alsa session is configured with the same format as HAL input format,
8633 * if not then derive correct fragment size needed to accomodate the
8634 * conversion of HAL input format to alsa format.
8635 */
8636 audio_extn_utils_update_direct_pcm_fragment_size(out);
8637
8638 /*if hal input and output fragment size is different this indicates HAL input format is
8639 *not same as the alsa format
8640 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308641 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05308642 /*Allocate a buffer to convert input data to the alsa configured format.
8643 *size of convert buffer is equal to the size required to hold one fragment size
8644 *worth of pcm data, this is because flinger does not write more than fragment_size
8645 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308646 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
8647 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05308648 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
8649 ret = -ENOMEM;
8650 goto error_open;
8651 }
8652 }
8653 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
8654 out->compr_config.fragment_size =
8655 audio_extn_passthru_get_buffer_size(&config->offload_info);
8656 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8657 } else {
8658 out->compr_config.fragment_size =
8659 platform_get_compress_offload_buffer_size(&config->offload_info);
8660 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8661 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008662
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308663 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8664 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
8665 }
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008666 if (config->offload_info.format == AUDIO_FORMAT_FLAC) {
8667#ifdef AUDIO_GKI_ENABLED
8668 generic_dec =
8669 &(out->compr_config.codec->options.generic.reserved[1]);
8670 ((struct snd_generic_dec_flac *)generic_dec)->sample_size =
8671 AUDIO_OUTPUT_BIT_WIDTH;
8672#else
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05308673 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008674#endif
8675 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008676
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05308677 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
8678 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
8679 }
8680
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008681 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
8682 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008683
Manish Dewangan69426c82017-01-30 17:35:36 +05308684 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
8685 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
8686 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
8687 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8688 out->render_mode = RENDER_MODE_AUDIO_MASTER;
8689 } else {
8690 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
8691 }
Alexy Josephaa54c872014-12-03 02:46:47 -08008692
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05308693 memset(&out->channel_map_param, 0,
8694 sizeof(struct audio_out_channel_map_param));
8695
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008696 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05308697 out->send_next_track_params = false;
8698 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008699 out->offload_state = OFFLOAD_STATE_IDLE;
8700 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08008701 out->writeAt.tv_sec = 0;
8702 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008703
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008704 audio_extn_dts_create_state_notifier_node(out->usecase);
8705
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008706 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
8707 __func__, config->offload_info.version,
8708 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05308709
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308710 /* Check if DSD audio format is supported in codec
8711 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308712 */
8713
8714 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308715 (!platform_check_codec_dsd_support(adev->platform) ||
8716 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308717 ret = -EINVAL;
8718 goto error_open;
8719 }
8720
Ashish Jain5106d362016-05-11 19:23:33 +05308721 /* Disable gapless if any of the following is true
8722 * passthrough playback
8723 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05308724 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05308725 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308726 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308727 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07008728 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308729 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308730 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05308731 check_and_set_gapless_mode(adev, false);
8732 } else
8733 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07008734
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308735 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07008736 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
8737 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308738 if (config->format == AUDIO_FORMAT_DSD) {
8739 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
Meng Wang4c32fb42020-01-16 17:57:11 +08008740#ifdef AUDIO_GKI_ENABLED
8741 /* out->compr_config.codec->reserved[0] is for compr_passthr */
8742 out->compr_config.codec->reserved[0] = PASSTHROUGH_DSD;
8743#else
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308744 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
Meng Wang4c32fb42020-01-16 17:57:11 +08008745#endif
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308746 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07008747
8748 create_offload_callback_thread(out);
8749
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008750 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008751 switch (config->sample_rate) {
8752 case 0:
8753 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8754 break;
8755 case 8000:
8756 case 16000:
8757 case 48000:
8758 out->sample_rate = config->sample_rate;
8759 break;
8760 default:
8761 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
8762 config->sample_rate);
8763 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8764 ret = -EINVAL;
8765 goto error_open;
8766 }
8767 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8768 switch (config->channel_mask) {
8769 case AUDIO_CHANNEL_NONE:
8770 case AUDIO_CHANNEL_OUT_STEREO:
8771 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8772 break;
8773 default:
8774 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
8775 config->channel_mask);
8776 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8777 ret = -EINVAL;
8778 goto error_open;
8779 }
8780 switch (config->format) {
8781 case AUDIO_FORMAT_DEFAULT:
8782 case AUDIO_FORMAT_PCM_16_BIT:
8783 out->format = AUDIO_FORMAT_PCM_16_BIT;
8784 break;
8785 default:
8786 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
8787 config->format);
8788 config->format = AUDIO_FORMAT_PCM_16_BIT;
8789 ret = -EINVAL;
8790 goto error_open;
8791 }
8792
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05308793 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008794 if (ret != 0) {
8795 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008796 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008797 goto error_open;
8798 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008799 } else if (is_single_device_type_equal(&out->device_list,
8800 AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08008801 switch (config->sample_rate) {
8802 case 0:
8803 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
8804 break;
8805 case 8000:
8806 case 16000:
8807 case 48000:
8808 out->sample_rate = config->sample_rate;
8809 break;
8810 default:
8811 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
8812 config->sample_rate);
8813 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8814 ret = -EINVAL;
8815 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008816 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008817 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8818 switch (config->channel_mask) {
8819 case AUDIO_CHANNEL_NONE:
8820 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8821 break;
8822 case AUDIO_CHANNEL_OUT_STEREO:
8823 out->channel_mask = config->channel_mask;
8824 break;
8825 default:
8826 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
8827 config->channel_mask);
8828 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8829 ret = -EINVAL;
8830 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008831 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008832 switch (config->format) {
8833 case AUDIO_FORMAT_DEFAULT:
8834 out->format = AUDIO_FORMAT_PCM_16_BIT;
8835 break;
8836 case AUDIO_FORMAT_PCM_16_BIT:
8837 out->format = config->format;
8838 break;
8839 default:
8840 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
8841 config->format);
8842 config->format = AUDIO_FORMAT_PCM_16_BIT;
8843 ret = -EINVAL;
8844 break;
8845 }
8846 if (ret != 0)
8847 goto error_open;
8848
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008849 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
8850 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08008851 out->config.rate = out->sample_rate;
8852 out->config.channels =
8853 audio_channel_count_from_out_mask(out->channel_mask);
8854 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008855 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008856 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05308857 unsigned int channels = 0;
8858 /*Update config params to default if not set by the caller*/
8859 if (config->sample_rate == 0)
8860 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8861 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8862 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8863 if (config->format == AUDIO_FORMAT_DEFAULT)
8864 config->format = AUDIO_FORMAT_PCM_16_BIT;
8865
8866 channels = audio_channel_count_from_out_mask(out->channel_mask);
8867
Varun Balaraje49253e2017-07-06 19:48:56 +05308868 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
8869 out->usecase = get_interactive_usecase(adev);
8870 out->config = pcm_config_low_latency;
8871 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05308872 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008873 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
8874 out->flags);
8875 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07008876 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8877 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8878 out->config = pcm_config_mmap_playback;
8879 out->stream.start = out_start;
8880 out->stream.stop = out_stop;
8881 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8882 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308883 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8884 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008885 out->hal_output_suspend_supported =
8886 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
8887 out->dynamic_pm_qos_config_supported =
8888 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
8889 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08008890 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
8891 } else {
8892 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
8893 //the mixer path will be a string similar to "low-latency-playback resume"
8894 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
8895 strlcat(out->pm_qos_mixer_path,
8896 " resume", MAX_MIXER_PATH_LEN);
8897 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
8898 out->pm_qos_mixer_path);
8899 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308900 out->config = pcm_config_low_latency;
8901 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
8902 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
8903 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05308904 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
8905 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
8906 if (out->config.period_size <= 0) {
8907 ALOGE("Invalid configuration period size is not valid");
8908 ret = -EINVAL;
8909 goto error_open;
8910 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008911 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
8912 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
8913 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008914 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
8915 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
8916 out->config = pcm_config_haptics_audio;
8917 if (force_haptic_path)
8918 adev->haptics_config = pcm_config_haptics_audio;
8919 else
8920 adev->haptics_config = pcm_config_haptics;
8921
Meng Wangd08ce322020-04-02 08:59:20 +08008922 channels =
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008923 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
8924
8925 if (force_haptic_path) {
8926 out->config.channels = 1;
8927 adev->haptics_config.channels = 1;
8928 } else
8929 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 -08008930 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008931 ret = audio_extn_auto_hal_open_output_stream(out);
8932 if (ret) {
8933 ALOGE("%s: Failed to open output stream for bus device", __func__);
8934 ret = -EINVAL;
8935 goto error_open;
8936 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308937 } else {
8938 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008939 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8940 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308941 }
8942 out->hal_ip_format = format = out->format;
8943 out->config.format = hal_format_to_pcm(out->hal_ip_format);
8944 out->hal_op_format = pcm_format_to_hal(out->config.format);
8945 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
8946 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008947 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05308948 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308949 if (out->hal_ip_format != out->hal_op_format) {
8950 uint32_t buffer_size = out->config.period_size *
8951 format_to_bitwidth_table[out->hal_op_format] *
8952 out->config.channels;
8953 out->convert_buffer = calloc(1, buffer_size);
8954 if (out->convert_buffer == NULL){
8955 ALOGE("Allocation failed for convert buffer for size %d",
8956 out->compr_config.fragment_size);
8957 ret = -ENOMEM;
8958 goto error_open;
8959 }
8960 ALOGD("Convert buffer allocated of size %d", buffer_size);
8961 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008962 }
8963
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008964 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
8965 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308966
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008967 /* TODO remove this hardcoding and check why width is zero*/
8968 if (out->bit_width == 0)
8969 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308970 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008971 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008972 &out->device_list, out->flags,
8973 out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05308974 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05308975 &out->app_type_cfg);
Kogara Naveen Kumar65828fe2022-10-14 16:41:04 +05308976 if (((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
8977 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) && (!compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS))) {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08008978 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008979 if(adev->primary_output == NULL)
8980 adev->primary_output = out;
8981 else {
8982 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008983 ret = -EEXIST;
8984 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008985 }
8986 }
8987
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008988 /* Check if this usecase is already existing */
8989 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07008990 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
8991 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008992 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008993 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008994 ret = -EEXIST;
8995 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008996 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008997
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008998 pthread_mutex_unlock(&adev->lock);
8999
9000 out->stream.common.get_sample_rate = out_get_sample_rate;
9001 out->stream.common.set_sample_rate = out_set_sample_rate;
9002 out->stream.common.get_buffer_size = out_get_buffer_size;
9003 out->stream.common.get_channels = out_get_channels;
9004 out->stream.common.get_format = out_get_format;
9005 out->stream.common.set_format = out_set_format;
9006 out->stream.common.standby = out_standby;
9007 out->stream.common.dump = out_dump;
9008 out->stream.common.set_parameters = out_set_parameters;
9009 out->stream.common.get_parameters = out_get_parameters;
9010 out->stream.common.add_audio_effect = out_add_audio_effect;
9011 out->stream.common.remove_audio_effect = out_remove_audio_effect;
9012 out->stream.get_latency = out_get_latency;
9013 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08009014#ifdef NO_AUDIO_OUT
9015 out->stream.write = out_write_for_no_output;
9016#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009017 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08009018#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009019 out->stream.get_render_position = out_get_render_position;
9020 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07009021 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009022
Haynes Mathew George16081042017-05-31 17:16:49 -07009023 if (out->realtime)
9024 out->af_period_multiplier = af_period_multiplier;
9025 else
9026 out->af_period_multiplier = 1;
9027
Andy Hunga1f48fa2019-07-01 18:14:53 -07009028 out->kernel_buffer_size = out->config.period_size * out->config.period_count;
9029
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009030 out->standby = 1;
Zhou Songbaddf9f2020-11-20 13:57:39 +08009031 out->volume_l = PLAYBACK_GAIN_MAX;
9032 out->volume_r = PLAYBACK_GAIN_MAX;
Eric Laurenta9024de2013-04-04 09:19:12 -07009033 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07009034 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009035
9036 config->format = out->stream.common.get_format(&out->stream.common);
9037 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
9038 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05309039 register_format(out->format, out->supported_formats);
9040 register_channel_mask(out->channel_mask, out->supported_channel_masks);
9041 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009042
Dechen Chai22768452021-07-30 09:29:16 +05309043#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -08009044 out->error_log = error_log_create(
9045 ERROR_LOG_ENTRIES,
9046 1000000000 /* aggregate consecutive identical errors within one second in ns */);
Dechen Chai22768452021-07-30 09:29:16 +05309047#endif
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309048 /*
9049 By locking output stream before registering, we allow the callback
9050 to update stream's state only after stream's initial state is set to
9051 adev state.
9052 */
9053 lock_output_stream(out);
9054 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
9055 pthread_mutex_lock(&adev->lock);
9056 out->card_status = adev->card_status;
9057 pthread_mutex_unlock(&adev->lock);
9058 pthread_mutex_unlock(&out->lock);
9059
Aalique Grahame22e49102018-12-18 14:23:57 -08009060 stream_app_type_cfg_init(&out->app_type_cfg);
9061
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009062 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309063 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07009064 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08009065
9066 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
9067 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
9068 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08009069 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05309070 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08009071 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07009072 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05309073 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
9074 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08009075 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
9076 out->usecase, PCM_PLAYBACK);
9077 hdlr_stream_cfg.flags = out->flags;
9078 hdlr_stream_cfg.type = PCM_PLAYBACK;
9079 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
9080 &hdlr_stream_cfg);
9081 if (ret) {
9082 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
9083 out->adsp_hdlr_stream_handle = NULL;
9084 }
9085 }
Gangadhar Sb0210342019-02-22 17:39:41 +05309086 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
9087 is_direct_passthough, false);
9088 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
9089 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07009090 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07009091 if (ret < 0) {
9092 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
9093 out->ip_hdlr_handle = NULL;
9094 }
9095 }
Derek Chenf939fb72018-11-13 13:34:41 -08009096
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009097 ret = io_streams_map_insert(adev, &out->stream.common,
9098 out->handle, AUDIO_PATCH_HANDLE_NONE);
9099 if (ret != 0)
9100 goto error_open;
9101
Susan Wang6dd13092021-01-25 10:27:11 -05009102 out->out_ctxt.output = out;
Derek Chenf939fb72018-11-13 13:34:41 -08009103
9104 pthread_mutex_lock(&adev->lock);
Susan Wang6dd13092021-01-25 10:27:11 -05009105 list_add_tail(&adev->active_outputs_list, &out->out_ctxt.list);
Derek Chenf939fb72018-11-13 13:34:41 -08009106 pthread_mutex_unlock(&adev->lock);
9107
Eric Laurent994a6932013-07-17 11:51:42 -07009108 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009109 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07009110
9111error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05309112 if (out->convert_buffer)
9113 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07009114 free(out);
9115 *stream_out = NULL;
9116 ALOGD("%s: exit: ret %d", __func__, ret);
9117 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009118}
9119
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309120void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009121 struct audio_stream_out *stream)
9122{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07009123 struct stream_out *out = (struct stream_out *)stream;
9124 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009125 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07009126
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009127 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309128
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009129 io_streams_map_remove(adev, out->handle);
9130
Susan Wang6dd13092021-01-25 10:27:11 -05009131 // remove out_ctxt early to prevent the stream
9132 // being opened in a race condition
9133 pthread_mutex_lock(&adev->lock);
9134 list_remove(&out->out_ctxt.list);
9135 pthread_mutex_unlock(&adev->lock);
9136
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309137 // must deregister from sndmonitor first to prevent races
9138 // between the callback and close_stream
9139 audio_extn_snd_mon_unregister_listener(out);
9140
Ben Rombergerd771a7c2017-02-22 18:05:17 -08009141 /* close adsp hdrl session before standby */
9142 if (out->adsp_hdlr_stream_handle) {
9143 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
9144 if (ret)
9145 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
9146 out->adsp_hdlr_stream_handle = NULL;
9147 }
9148
Manish Dewangan21a850a2017-08-14 12:03:55 +05309149 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07009150 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
9151 out->ip_hdlr_handle = NULL;
9152 }
9153
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009154 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309155 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009156 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05309157 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309158 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009159 if(ret != 0)
9160 ALOGE("%s: Compress voip output cannot be closed, error:%d",
9161 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009162 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009163 out_standby(&stream->common);
9164
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07009165 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08009166 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07009167 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07009168 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07009169 if (out->compr_config.codec != NULL)
9170 free(out->compr_config.codec);
9171 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009172
Zhou Songbaddf9f2020-11-20 13:57:39 +08009173 out->a2dp_muted = false;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05309174
Varun Balaraje49253e2017-07-06 19:48:56 +05309175 if (is_interactive_usecase(out->usecase))
9176 free_interactive_usecase(adev, out->usecase);
9177
Ashish Jain83a6cc22016-06-28 14:34:17 +05309178 if (out->convert_buffer != NULL) {
9179 free(out->convert_buffer);
9180 out->convert_buffer = NULL;
9181 }
9182
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009183 if (adev->voice_tx_output == out)
9184 adev->voice_tx_output = NULL;
9185
Dechen Chai22768452021-07-30 09:29:16 +05309186#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -08009187 error_log_destroy(out->error_log);
9188 out->error_log = NULL;
Dechen Chai22768452021-07-30 09:29:16 +05309189#endif
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05309190 if (adev->primary_output == out)
9191 adev->primary_output = NULL;
9192
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07009193 pthread_cond_destroy(&out->cond);
9194 pthread_mutex_destroy(&out->lock);
Weiyin Jiang280ea742020-09-08 20:28:22 +08009195 pthread_mutex_destroy(&out->pre_lock);
9196 pthread_mutex_destroy(&out->latch_lock);
9197 pthread_mutex_destroy(&out->position_query_lock);
Derek Chenf939fb72018-11-13 13:34:41 -08009198
9199 pthread_mutex_lock(&adev->lock);
Zhenlin Lian4f947842022-05-14 15:50:52 +05309200 clear_devices(&out->device_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009201 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08009202 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07009203 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009204}
9205
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05009206void in_set_power_policy(uint8_t enable)
9207{
9208 struct listnode *node;
9209
9210 ALOGD("%s: Enter, state %d", __func__, enable);
9211
9212 pthread_mutex_lock(&adev->lock);
9213 adev->in_power_policy = enable ? POWER_POLICY_STATUS_ONLINE : POWER_POLICY_STATUS_OFFLINE;
9214 pthread_mutex_unlock(&adev->lock);
9215
9216 if (!enable) {
9217 list_for_each(node, &adev->active_inputs_list) {
9218 streams_input_ctxt_t *in_ctxt = node_to_item(node,
9219 streams_input_ctxt_t,
9220 list);
9221 struct stream_in *in = in_ctxt->input;
9222 in_standby(&in->stream.common);
9223 }
9224 }
9225
9226 ALOGD("%s: Exit", __func__);
9227}
9228
9229void out_set_power_policy(uint8_t enable)
9230{
9231 struct listnode *node;
9232
9233 ALOGD("%s: Enter, state %d", __func__, enable);
9234
9235 pthread_mutex_lock(&adev->lock);
E V Ravi317be872022-02-23 19:08:15 +05309236 adev->out_power_policy = enable ? POWER_POLICY_STATUS_ONLINE : POWER_POLICY_STATUS_OFFLINE;
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05009237 pthread_mutex_unlock(&adev->lock);
9238
9239 if (!enable) {
9240 list_for_each(node, &adev->active_outputs_list) {
9241 streams_output_ctxt_t *out_ctxt = node_to_item(node,
9242 streams_output_ctxt_t,
9243 list);
9244 struct stream_out *out = out_ctxt->output;
9245 out_on_error(&out->stream.common);
9246 }
9247 }
9248
9249 ALOGD("%s: Exit", __func__);
9250}
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009251static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
9252{
9253 struct audio_device *adev = (struct audio_device *)dev;
9254 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009255 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07009256 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009257 int ret;
9258 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08009259 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08009260 struct listnode *node;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07009261 int controller = -1, stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009262
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009263 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009264 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009265
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05309266 if (!parms)
9267 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05309268
Derek Chen6f293672019-04-01 01:40:24 -07009269 /* notify adev and input/output streams on the snd card status */
9270 adev_snd_mon_cb((void *)adev, parms);
9271
Weiyin Jiang24f55292020-12-22 14:35:46 +08009272 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
9273 if (ret >= 0) {
9274 list_for_each(node, &adev->active_outputs_list) {
9275 streams_output_ctxt_t *out_ctxt = node_to_item(node,
9276 streams_output_ctxt_t,
9277 list);
9278 out_snd_mon_cb((void *)out_ctxt->output, parms);
9279 }
Derek Chen6f293672019-04-01 01:40:24 -07009280
Weiyin Jiang24f55292020-12-22 14:35:46 +08009281 list_for_each(node, &adev->active_inputs_list) {
9282 streams_input_ctxt_t *in_ctxt = node_to_item(node,
9283 streams_input_ctxt_t,
9284 list);
9285 in_snd_mon_cb((void *)in_ctxt->input, parms);
9286 }
Derek Chen6f293672019-04-01 01:40:24 -07009287 }
9288
Zhou Songd6d71752019-05-21 18:08:51 +08009289 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05309290 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
9291 if (ret >= 0) {
9292 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08009293 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05309294 adev->bt_sco_on = true;
Shalini Manjunatha3a2e06e2021-02-01 12:23:49 +05309295 /*
9296 * When ever BT_SCO=ON arrives, make sure to route
9297 * all use cases to SCO device, otherwise due to delay in
9298 * BT_SCO=ON and lack of synchronization with create audio patch
9299 * request for SCO device, some times use case not routed properly to
9300 * SCO device
9301 */
9302 struct audio_usecase *usecase;
9303 struct listnode *node;
9304 list_for_each(node, &adev->usecase_list) {
9305 usecase = node_to_item(node, struct audio_usecase, list);
Anver sadhiquef0efca32021-09-03 15:25:44 +05309306 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
Anver sadhique93f3c912021-08-11 11:19:45 +05309307 (!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 +05309308 ALOGD("BT_SCO ON, switch all in use case to it");
9309 select_devices(adev, usecase->id);
9310 }
Mingshu Pangef517202021-04-22 10:35:00 +08009311 if (usecase->stream.out && (usecase->type == PCM_PLAYBACK ||
9312 usecase->type == VOICE_CALL) &&
Anver sadhique93f3c912021-08-11 11:19:45 +05309313 (!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 +05309314 ALOGD("BT_SCO ON, switch all out use case to it");
9315 select_devices(adev, usecase->id);
9316 }
9317 }
9318 }
9319 else {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05309320 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08009321 audio_extn_sco_reset_configuration();
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08009322 }
9323 }
9324
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009325 status = voice_set_parameters(adev, parms);
9326 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08009327 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009328
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009329 status = platform_set_parameters(adev->platform, parms);
9330 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08009331 goto done;
9332
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009333 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
9334 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07009335 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009336 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
9337 adev->bluetooth_nrec = true;
9338 else
9339 adev->bluetooth_nrec = false;
9340 }
9341
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009342 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
9343 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009344 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
9345 adev->screen_off = false;
9346 else
9347 adev->screen_off = true;
Quinn Male70f20f32019-06-26 16:50:26 -07009348 audio_extn_sound_trigger_update_screen_status(adev->screen_off);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009349 }
9350
Eric Laurent4b084132018-10-19 17:33:43 -07009351 ret = str_parms_get_int(parms, "rotation", &val);
9352 if (ret >= 0) {
9353 bool reverse_speakers = false;
9354 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
9355 switch (val) {
9356 // FIXME: note that the code below assumes that the speakers are in the correct placement
9357 // relative to the user when the device is rotated 90deg from its default rotation. This
9358 // assumption is device-specific, not platform-specific like this code.
9359 case 270:
9360 reverse_speakers = true;
9361 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
9362 break;
9363 case 0:
9364 case 180:
9365 camera_rotation = CAMERA_ROTATION_PORTRAIT;
9366 break;
9367 case 90:
9368 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
9369 break;
9370 default:
9371 ALOGE("%s: unexpected rotation of %d", __func__, val);
9372 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07009373 }
Eric Laurent4b084132018-10-19 17:33:43 -07009374 if (status == 0) {
9375 // check and set swap
9376 // - check if orientation changed and speaker active
9377 // - set rotation and cache the rotation value
9378 adev->camera_orientation =
9379 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
9380 if (!audio_extn_is_maxx_audio_enabled())
9381 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
9382 }
9383 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07009384
Mingming Yin514a8bc2014-07-29 15:22:21 -07009385 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
9386 if (ret >= 0) {
9387 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
9388 adev->bt_wb_speech_enabled = true;
9389 else
9390 adev->bt_wb_speech_enabled = false;
9391 }
9392
Zhou Song12c29502019-03-16 10:37:18 +08009393 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
9394 if (ret >= 0) {
9395 val = atoi(value);
9396 adev->swb_speech_mode = val;
9397 }
9398
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07009399 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
9400 if (ret >= 0) {
9401 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309402 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08009403 if (audio_is_output_device(val) &&
9404 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07009405 ALOGV("cache new ext disp type and edid");
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07009406 platform_get_controller_stream_from_params(parms, &controller, &stream);
9407 platform_set_ext_display_device_v2(adev->platform, controller, stream);
9408 ret = platform_get_ext_disp_type_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07009409 if (ret < 0) {
9410 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05309411 } else {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07009412 platform_cache_edid_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07009413 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309414 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07009415 /*
9416 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
9417 * Per AudioPolicyManager, USB device is higher priority than WFD.
9418 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
9419 * If WFD use case occupies AFE proxy, it may result unintended behavior while
9420 * starting voice call on USB
9421 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08009422 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309423 if (ret >= 0)
9424 audio_extn_usb_add_device(device, atoi(value));
9425
Zhou Song6f862822017-11-06 17:27:57 +08009426 if (!audio_extn_usb_is_tunnel_supported()) {
9427 ALOGV("detected USB connect .. disable proxy");
9428 adev->allow_afe_proxy_usage = false;
9429 }
Zhou Song503196b2021-07-23 17:31:05 +08009430 } else if (audio_is_hearing_aid_out_device(device) &&
9431 property_get_bool("persist.vendor.audio.ha_proxy.enabled", false)) {
9432 adev->ha_proxy_enable = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07009433 }
9434 }
9435
9436 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
9437 if (ret >= 0) {
9438 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309439 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07009440 /*
9441 * The HDMI / Displayport disconnect handling has been moved to
9442 * audio extension to ensure that its parameters are not
9443 * invalidated prior to updating sysfs of the disconnect event
9444 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
9445 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309446 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08009447 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309448 if (ret >= 0)
9449 audio_extn_usb_remove_device(device, atoi(value));
9450
Zhou Song6f862822017-11-06 17:27:57 +08009451 if (!audio_extn_usb_is_tunnel_supported()) {
9452 ALOGV("detected USB disconnect .. enable proxy");
9453 adev->allow_afe_proxy_usage = true;
9454 }
Zhou Song503196b2021-07-23 17:31:05 +08009455 } else if (audio_is_hearing_aid_out_device(device)) {
9456 adev->ha_proxy_enable = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07009457 }
9458 }
9459
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009460 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08009461
9462 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08009463 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309464 struct audio_usecase *usecase;
9465 struct listnode *node;
9466 list_for_each(node, &adev->usecase_list) {
9467 usecase = node_to_item(node, struct audio_usecase, list);
Weiyin Jiangff56ff32020-05-08 14:32:21 +08009468 if ((usecase->stream.out == NULL) || (usecase->type != PCM_PLAYBACK))
9469 continue;
9470
9471 if (is_a2dp_out_device_type(&usecase->device_list)) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309472 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05309473 audio_extn_a2dp_set_handoff_mode(true);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05309474 ALOGD("Switching to speaker and muting the stream before select_devices");
9475 check_a2dp_restore_l(adev, usecase->stream.out, false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309476 //force device switch to re configure encoder
9477 select_devices(adev, usecase->id);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05309478 ALOGD("Unmuting the stream after select_devices");
Zhou Songbaddf9f2020-11-20 13:57:39 +08009479 check_a2dp_restore_l(adev, usecase->stream.out, true);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05309480 audio_extn_a2dp_set_handoff_mode(false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309481 break;
Zhou Songd01e7a22020-09-23 22:49:01 +08009482 } else if (is_offload_usecase(usecase->stream.out->usecase)) {
Weiyin Jiang280ea742020-09-08 20:28:22 +08009483 pthread_mutex_lock(&usecase->stream.out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +08009484 if (usecase->stream.out->a2dp_muted) {
Weiyin Jiang280ea742020-09-08 20:28:22 +08009485 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
9486 reassign_device_list(&usecase->stream.out->device_list,
9487 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, "");
9488 check_a2dp_restore_l(adev, usecase->stream.out, true);
9489 break;
9490 }
9491 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309492 }
9493 }
9494 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009495
9496 //handle vr audio setparam
9497 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9498 value, sizeof(value));
9499 if (ret >= 0) {
9500 ALOGI("Setting vr mode to be %s", value);
9501 if (!strncmp(value, "true", 4)) {
9502 adev->vr_audio_mode_enabled = true;
9503 ALOGI("Setting vr mode to true");
9504 } else if (!strncmp(value, "false", 5)) {
9505 adev->vr_audio_mode_enabled = false;
9506 ALOGI("Setting vr mode to false");
9507 } else {
9508 ALOGI("wrong vr mode set");
9509 }
9510 }
9511
Eric Laurent4b084132018-10-19 17:33:43 -07009512 //FIXME: to be replaced by proper video capture properties API
9513 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
9514 if (ret >= 0) {
9515 int camera_facing = CAMERA_FACING_BACK;
9516 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
9517 camera_facing = CAMERA_FACING_FRONT;
9518 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
9519 camera_facing = CAMERA_FACING_BACK;
9520 else {
9521 ALOGW("%s: invalid camera facing value: %s", __func__, value);
9522 goto done;
9523 }
9524 adev->camera_orientation =
9525 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
9526 struct audio_usecase *usecase;
9527 struct listnode *node;
9528 list_for_each(node, &adev->usecase_list) {
9529 usecase = node_to_item(node, struct audio_usecase, list);
9530 struct stream_in *in = usecase->stream.in;
9531 if (usecase->type == PCM_CAPTURE && in != NULL &&
9532 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
9533 select_devices(adev, in->usecase);
9534 }
9535 }
9536 }
9537
Tahir Dawson7fabad42022-06-21 12:37:55 -04009538 audio_extn_auto_hal_set_parameters(adev, parms);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05309539 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08009540done:
9541 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009542 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05309543error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009544 ALOGV("%s: exit with code(%d)", __func__, status);
9545 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009546}
9547
9548static char* adev_get_parameters(const struct audio_hw_device *dev,
9549 const char *keys)
9550{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05309551 ALOGD("%s:%s", __func__, keys);
9552
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009553 struct audio_device *adev = (struct audio_device *)dev;
9554 struct str_parms *reply = str_parms_create();
9555 struct str_parms *query = str_parms_create_str(keys);
9556 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05309557 char value[256] = {0};
9558 int ret = 0;
9559
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009560 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08009561 if (reply) {
9562 str_parms_destroy(reply);
9563 }
9564 if (query) {
9565 str_parms_destroy(query);
9566 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009567 ALOGE("adev_get_parameters: failed to create query or reply");
9568 return NULL;
9569 }
9570
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009571 //handle vr audio getparam
9572
9573 ret = str_parms_get_str(query,
9574 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9575 value, sizeof(value));
9576
9577 if (ret >= 0) {
9578 bool vr_audio_enabled = false;
9579 pthread_mutex_lock(&adev->lock);
9580 vr_audio_enabled = adev->vr_audio_mode_enabled;
9581 pthread_mutex_unlock(&adev->lock);
9582
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07009583 ALOGV("getting vr mode to %d", vr_audio_enabled);
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009584
9585 if (vr_audio_enabled) {
9586 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9587 "true");
9588 goto exit;
9589 } else {
9590 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9591 "false");
9592 goto exit;
9593 }
9594 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009595
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009596 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009597 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08009598 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08009599 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009600 platform_get_parameters(adev->platform, query, reply);
justinwengd5395152019-11-04 12:23:09 +08009601 audio_extn_ma_get_parameters(adev, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05309602 pthread_mutex_unlock(&adev->lock);
9603
Naresh Tannirud7205b62014-06-20 02:54:48 +05309604exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009605 str = str_parms_to_str(reply);
9606 str_parms_destroy(query);
9607 str_parms_destroy(reply);
9608
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07009609 ALOGV("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009610 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009611}
9612
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009613static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009614{
9615 return 0;
9616}
9617
9618static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
9619{
Haynes Mathew George5191a852013-09-11 14:19:36 -07009620 int ret;
9621 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08009622
9623 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
9624
Haynes Mathew George5191a852013-09-11 14:19:36 -07009625 pthread_mutex_lock(&adev->lock);
9626 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07009627 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07009628 pthread_mutex_unlock(&adev->lock);
9629 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009630}
9631
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009632static int adev_set_master_volume(struct audio_hw_device *dev __unused,
9633 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009634{
9635 return -ENOSYS;
9636}
9637
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009638static int adev_get_master_volume(struct audio_hw_device *dev __unused,
9639 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009640{
9641 return -ENOSYS;
9642}
9643
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009644static int adev_set_master_mute(struct audio_hw_device *dev __unused,
9645 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009646{
9647 return -ENOSYS;
9648}
9649
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009650static int adev_get_master_mute(struct audio_hw_device *dev __unused,
9651 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009652{
9653 return -ENOSYS;
9654}
9655
9656static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
9657{
9658 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07009659 struct listnode *node;
9660 struct audio_usecase *usecase = NULL;
9661 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08009662
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009663 pthread_mutex_lock(&adev->lock);
9664 if (adev->mode != mode) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309665 ALOGD("%s: mode %d , prev_mode %d \n", __func__, mode , adev->mode);
9666 adev->prev_mode = adev->mode; /* prev_mode is kept to handle voip concurrency*/
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009667 adev->mode = mode;
Weiyin Jiang96b96f72020-09-22 16:48:19 +08009668 if (mode == AUDIO_MODE_CALL_SCREEN) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309669 adev->current_call_output = adev->primary_output;
9670 voice_start_call(adev);
9671 } else if (voice_is_in_call_or_call_screen(adev) &&
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08009672 (mode == AUDIO_MODE_NORMAL ||
9673 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07009674 list_for_each(node, &adev->usecase_list) {
9675 usecase = node_to_item(node, struct audio_usecase, list);
9676 if (usecase->type == VOICE_CALL)
9677 break;
9678 }
9679 if (usecase &&
9680 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
9681 ret = audio_extn_usb_check_and_set_svc_int(usecase,
9682 true);
9683 if (ret != 0) {
9684 /* default service interval was successfully updated,
9685 reopen USB backend with new service interval */
9686 check_usecases_codec_backend(adev,
9687 usecase,
9688 usecase->out_snd_device);
9689 }
9690 }
9691
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009692 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07009693 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009694 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08009695 // restore device for other active usecases after stop call
9696 list_for_each(node, &adev->usecase_list) {
9697 usecase = node_to_item(node, struct audio_usecase, list);
9698 select_devices(adev, usecase->id);
9699 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009700 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009701 }
9702 pthread_mutex_unlock(&adev->lock);
9703 return 0;
9704}
9705
9706static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
9707{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009708 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08009709 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009710
9711 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08009712 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009713 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009714
Derek Chend2530072014-11-24 12:39:14 -08009715 if (adev->ext_hw_plugin)
9716 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009717
9718 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009719 pthread_mutex_unlock(&adev->lock);
9720
9721 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009722}
9723
9724static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
9725{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009726 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009727 return 0;
9728}
9729
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009730static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009731 const struct audio_config *config)
9732{
Avinash Chandrad7296d42021-08-04 15:07:47 +05309733 bool is_usb_hifi = IS_USB_HIFI;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009734 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009735
Aalique Grahame22e49102018-12-18 14:23:57 -08009736 /* Don't know if USB HIFI in this context so use true to be conservative */
9737 if (check_input_parameters(config->sample_rate, config->format, channel_count,
Avinash Chandrad7296d42021-08-04 15:07:47 +05309738 is_usb_hifi) != 0)
Aalique Grahame22e49102018-12-18 14:23:57 -08009739 return 0;
9740
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009741 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
9742 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009743}
9744
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009745static bool adev_input_allow_hifi_record(struct audio_device *adev,
9746 audio_devices_t devices,
9747 audio_input_flags_t flags,
9748 audio_source_t source) {
9749 const bool allowed = true;
9750
9751 if (!audio_is_usb_in_device(devices))
9752 return !allowed;
9753
9754 switch (flags) {
9755 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009756 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07009757 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
9758 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009759 default:
9760 return !allowed;
9761 }
9762
9763 switch (source) {
9764 case AUDIO_SOURCE_DEFAULT:
9765 case AUDIO_SOURCE_MIC:
9766 case AUDIO_SOURCE_UNPROCESSED:
9767 break;
9768 default:
9769 return !allowed;
9770 }
9771
9772 switch (adev->mode) {
9773 case 0:
9774 break;
9775 default:
9776 return !allowed;
9777 }
9778
9779 return allowed;
9780}
9781
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009782static int adev_update_voice_comm_input_stream(struct stream_in *in,
9783 struct audio_config *config)
9784{
9785 bool valid_rate = (config->sample_rate == 8000 ||
9786 config->sample_rate == 16000 ||
9787 config->sample_rate == 32000 ||
9788 config->sample_rate == 48000);
9789 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
9790
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009791 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08009792 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009793 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9794 in->config = default_pcm_config_voip_copp;
9795 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
9796 DEFAULT_VOIP_BUF_DURATION_MS,
9797 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009798 } else {
9799 ALOGW("%s No valid input in voip, use defaults"
9800 "sample rate %u, channel mask 0x%X",
9801 __func__, config->sample_rate, in->channel_mask);
9802 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009803 in->config.rate = config->sample_rate;
9804 in->sample_rate = config->sample_rate;
9805 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009806 //XXX needed for voice_extn_compress_voip_open_input_stream
9807 in->config.rate = config->sample_rate;
9808 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
Shalini Manjunathaa763cc42019-08-23 15:13:46 +05309809 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009810 voice_extn_compress_voip_is_active(in->dev)) &&
9811 (voice_extn_compress_voip_is_format_supported(in->format)) &&
9812 valid_rate && valid_ch) {
9813 voice_extn_compress_voip_open_input_stream(in);
9814 // update rate entries to match config from AF
9815 in->config.rate = config->sample_rate;
9816 in->sample_rate = config->sample_rate;
9817 } else {
9818 ALOGW("%s compress voip not active, use defaults", __func__);
9819 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009820 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009821 return 0;
9822}
9823
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009824static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07009825 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009826 audio_devices_t devices,
9827 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009828 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309829 audio_input_flags_t flags,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009830 const char *address,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009831 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009832{
9833 struct audio_device *adev = (struct audio_device *)dev;
9834 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009835 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009836 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009837 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05309838 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009839 bool is_usb_dev = audio_is_usb_in_device(devices);
9840 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
9841 devices,
9842 flags,
9843 source);
Andy Hung94320602018-10-29 18:31:12 -07009844 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
9845 " sample_rate %u, channel_mask %#x, format %#x",
9846 __func__, flags, is_usb_dev, may_use_hifi_record,
9847 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309848
kunleizdff872d2018-08-20 14:40:33 +08009849 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08009850 is_usb_dev = false;
9851 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
9852 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
9853 __func__, devices);
9854 }
9855
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009856 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009857
9858 if (!(is_usb_dev && may_use_hifi_record)) {
9859 if (config->sample_rate == 0)
9860 config->sample_rate = 48000;
9861 if (config->channel_mask == AUDIO_CHANNEL_NONE)
9862 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9863 if (config->format == AUDIO_FORMAT_DEFAULT)
9864 config->format = AUDIO_FORMAT_PCM_16_BIT;
9865
9866 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
9867
Aalique Grahame22e49102018-12-18 14:23:57 -08009868 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9869 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009870 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05309871 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009872
9873 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009874
9875 if (!in) {
9876 ALOGE("failed to allocate input stream");
9877 return -ENOMEM;
9878 }
9879
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309880 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05309881 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
9882 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009883 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07009884 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009885
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009886 in->stream.common.get_sample_rate = in_get_sample_rate;
9887 in->stream.common.set_sample_rate = in_set_sample_rate;
9888 in->stream.common.get_buffer_size = in_get_buffer_size;
9889 in->stream.common.get_channels = in_get_channels;
9890 in->stream.common.get_format = in_get_format;
9891 in->stream.common.set_format = in_set_format;
9892 in->stream.common.standby = in_standby;
9893 in->stream.common.dump = in_dump;
9894 in->stream.common.set_parameters = in_set_parameters;
9895 in->stream.common.get_parameters = in_get_parameters;
9896 in->stream.common.add_audio_effect = in_add_audio_effect;
9897 in->stream.common.remove_audio_effect = in_remove_audio_effect;
9898 in->stream.set_gain = in_set_gain;
9899 in->stream.read = in_read;
9900 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08009901 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309902 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07009903 in->stream.set_microphone_direction = in_set_microphone_direction;
9904 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07009905 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009906
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009907 list_init(&in->device_list);
9908 update_device_list(&in->device_list, devices, address, true);
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009909 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009910 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009911 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009912 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009913 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07009914 in->bit_width = 16;
9915 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07009916 in->direction = MIC_DIRECTION_UNSPECIFIED;
9917 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08009918 list_init(&in->aec_list);
9919 list_init(&in->ns_list);
Phil Burkd898ba62019-06-20 12:49:01 -07009920 in->mmap_shared_memory_fd = -1; // not open
Haynes Mathew George46740472017-10-27 18:40:12 -07009921
Andy Hung94320602018-10-29 18:31:12 -07009922 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08009923 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
9924 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
9925 /* Force channel config requested to mono if incall
9926 record is being requested for only uplink/downlink */
9927 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
9928 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9929 ret = -EINVAL;
9930 goto err_open;
9931 }
9932 }
9933
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009934 if (is_usb_dev && may_use_hifi_record) {
9935 /* HiFi record selects an appropriate format, channel, rate combo
9936 depending on sink capabilities*/
9937 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
9938 &config->format,
9939 &in->supported_formats[0],
9940 MAX_SUPPORTED_FORMATS,
9941 &config->channel_mask,
9942 &in->supported_channel_masks[0],
9943 MAX_SUPPORTED_CHANNEL_MASKS,
9944 &config->sample_rate,
9945 &in->supported_sample_rates[0],
9946 MAX_SUPPORTED_SAMPLE_RATES);
9947 if (ret != 0) {
9948 ret = -EINVAL;
9949 goto err_open;
9950 }
9951 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009952 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309953 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05309954 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
9955 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
9956 in->config.format = PCM_FORMAT_S32_LE;
9957 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309958 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
9959 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
9960 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
9961 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
9962 bool ret_error = false;
9963 in->bit_width = 24;
9964 /* 24 bit is restricted to UNPROCESSED source only,also format supported
9965 from HAL is 24_packed and 8_24
9966 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
9967 24_packed return error indicating supported format is 24_packed
9968 *> In case of any other source requesting 24 bit or float return error
9969 indicating format supported is 16 bit only.
9970
9971 on error flinger will retry with supported format passed
9972 */
9973 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
9974 (source != AUDIO_SOURCE_CAMCORDER)) {
9975 config->format = AUDIO_FORMAT_PCM_16_BIT;
9976 if (config->sample_rate > 48000)
9977 config->sample_rate = 48000;
9978 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07009979 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
9980 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309981 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
9982 ret_error = true;
9983 }
9984
9985 if (ret_error) {
9986 ret = -EINVAL;
9987 goto err_open;
9988 }
9989 }
9990
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009991 in->channel_mask = config->channel_mask;
9992 in->format = config->format;
9993
9994 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309995
Huicheng Liu1404ba12020-09-11 01:03:25 -04009996 /* validate bus device address */
9997 if (compare_device_type(&in->device_list, AUDIO_DEVICE_IN_BUS)) {
9998 /* extract car audio stream index */
9999 in->car_audio_stream =
10000 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
10001 if (in->car_audio_stream < 0) {
10002 ALOGE("%s: invalid car audio stream %x",
10003 __func__, in->car_audio_stream);
10004 ret = -EINVAL;
10005 goto err_open;
10006 }
10007 ALOGV("%s: car_audio_stream 0x%x", __func__, in->car_audio_stream);
Huicheng Liuea4fd422021-01-12 18:34:50 -050010008 ret = audio_extn_auto_hal_open_input_stream(in);
10009 if (ret) {
10010 ALOGE("%s: Failed to open input stream for bus device", __func__);
10011 ret = -EINVAL;
10012 goto err_open;
10013 }
Huicheng Liu1404ba12020-09-11 01:03:25 -040010014 }
10015
Susan Wange3959562021-03-11 11:50:26 -050010016 /* reassign use case for echo reference stream on automotive platforms */
10017 if (in->source == AUDIO_SOURCE_ECHO_REFERENCE) {
10018 ret = audio_extn_auto_hal_open_echo_reference_stream(in);
10019 }
10020
Kogara Naveen Kumar379ff692022-01-31 11:56:51 +053010021 if ((in->source == AUDIO_SOURCE_FM_TUNER) || (devices == AUDIO_DEVICE_IN_FM_TUNER)) {
Samyak Jain0aa07ab2019-04-04 14:36:32 +053010022 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
10023 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
10024 else {
10025 ret = -EINVAL;
10026 goto err_open;
10027 }
10028 }
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +053010029#ifdef PLATFORM_AUTO
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +053010030 if ((config->sample_rate == 48000 ||
10031 config->sample_rate == 32000 ||
10032 config->sample_rate == 24000 ||
10033 config->sample_rate == 16000 ||
10034 config->sample_rate == 8000)&&
Deeraj Somanfa377bf2019-02-06 12:57:59 +053010035 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
10036 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +053010037 (flags & AUDIO_INPUT_FLAG_FAST) != 0)
10038#else
10039 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
10040 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
10041 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
10042 (flags & AUDIO_INPUT_FLAG_FAST) != 0)
10043#endif
10044{
Haynes Mathew George484e8d22017-07-31 18:55:17 -070010045 is_low_latency = true;
10046#if LOW_LATENCY_CAPTURE_USE_CASE
Revathi Uddarajud9f23d92020-07-27 10:55:06 +053010047 if ((flags & AUDIO_INPUT_FLAG_VOIP_TX) != 0)
10048 in->usecase = USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY;
10049 else
10050 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Haynes Mathew George484e8d22017-07-31 18:55:17 -070010051#endif
10052 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -080010053 if (!in->realtime) {
10054 in->config = pcm_config_audio_capture;
10055 frame_size = audio_stream_in_frame_size(&in->stream);
10056 buffer_size = get_input_buffer_size(config->sample_rate,
10057 config->format,
10058 channel_count,
10059 is_low_latency);
10060 in->config.period_size = buffer_size / frame_size;
10061 in->config.rate = config->sample_rate;
10062 in->af_period_multiplier = 1;
10063 } else {
10064 // period size is left untouched for rt mode playback
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +053010065#ifdef PLATFORM_AUTO
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +053010066 switch(config->sample_rate)
10067 {
10068 case 48000:
10069 in->config = pcm_config_audio_capture_rt_48KHz;
10070 break;
10071 case 32000:
10072 in->config = pcm_config_audio_capture_rt_32KHz;
10073 break;
10074 case 24000:
10075 in->config = pcm_config_audio_capture_rt_24KHz;
10076 break;
10077 case 16000:
10078 in->config = pcm_config_audio_capture_rt_16KHz;
10079 break;
10080 case 8000:
10081 in->config = pcm_config_audio_capture_rt_8KHz;
10082 break;
10083 default:
10084 in->config = pcm_config_audio_capture_rt_48KHz;
10085 }
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +053010086#else
10087 in->config = pcm_config_audio_capture_rt_48KHz;
10088#endif
Aalique Grahame22e49102018-12-18 14:23:57 -080010089 in->af_period_multiplier = af_period_multiplier;
10090 }
Kogara Naveen Kumarc5758232022-11-07 20:25:40 +053010091
10092 /* assign concurrent capture usecase if record has to caried out from
10093 * actual hardware input source */
10094 if (audio_extn_is_concurrent_capture_enabled() &&
10095 !audio_is_virtual_input_source(in->source)) {
10096 /* Acquire lock to avoid two concurrent use cases initialized to
10097 same pcm record use case */
10098 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY) {
10099 pthread_mutex_lock(&adev->lock);
10100 if (!(adev->pcm_low_latency_record_uc_state)) {
10101 ALOGD("%s: using USECASE_AUDIO_RECORD_LOW_LATENCY",__func__);
10102 adev->pcm_low_latency_record_uc_state = 1;
10103 pthread_mutex_unlock(&adev->lock);
10104 } else if (audio_extn_is_concurrent_low_latency_pcm_record_enabled()) {
10105 in->usecase = get_low_latency_record_usecase(adev);
10106 pthread_mutex_unlock(&adev->lock);
10107 } else {
10108 pthread_mutex_unlock(&adev->lock);
10109 /* Assign compress record use case for second record */
10110 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
10111 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
10112 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
10113 if (audio_extn_cin_applicable_stream(in)) {
10114 in->sample_rate = config->sample_rate;
10115 ret = audio_extn_cin_configure_input_stream(in, config);
10116 if (ret)
10117 goto err_open;
10118 }
10119 }
10120 }
10121 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -070010122 }
10123
Susan Wangb803cb52021-10-14 12:03:36 -040010124 /* Additional sample rates added below must also be present
10125 in audio_policy_configuration.xml for mmap_no_irq_in */
10126 bool valid_mmap_record_rate = (config->sample_rate == 8000 ||
10127 config->sample_rate == 16000 ||
Susan Wang89da9042021-10-14 12:03:36 -040010128 config->sample_rate == 24000 ||
Susan Wangb803cb52021-10-14 12:03:36 -040010129 config->sample_rate == 32000 ||
10130 config->sample_rate == 48000);
10131 if (valid_mmap_record_rate &&
10132 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -070010133 in->realtime = 0;
10134 in->usecase = USECASE_AUDIO_RECORD_MMAP;
10135 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -070010136 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -070010137 in->stream.start = in_start;
10138 in->stream.stop = in_stop;
10139 in->stream.create_mmap_buffer = in_create_mmap_buffer;
10140 in->stream.get_mmap_position = in_get_mmap_position;
Ramjee Singhbcb3b6c2021-11-17 13:19:16 +053010141 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -070010142 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
Haynes Mathew George46740472017-10-27 18:40:12 -070010143 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -070010144 in->usecase = USECASE_AUDIO_RECORD_HIFI;
10145 in->config = pcm_config_audio_capture;
10146 frame_size = audio_stream_in_frame_size(&in->stream);
10147 buffer_size = get_input_buffer_size(config->sample_rate,
10148 config->format,
10149 channel_count,
10150 false /*is_low_latency*/);
10151 in->config.period_size = buffer_size / frame_size;
10152 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -070010153 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -070010154 switch (config->format) {
10155 case AUDIO_FORMAT_PCM_32_BIT:
10156 in->bit_width = 32;
10157 break;
10158 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
10159 case AUDIO_FORMAT_PCM_8_24_BIT:
10160 in->bit_width = 24;
10161 break;
10162 default:
10163 in->bit_width = 16;
10164 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010165 } else if (is_single_device_type_equal(&in->device_list,
10166 AUDIO_DEVICE_IN_TELEPHONY_RX) ||
10167 is_single_device_type_equal(&in->device_list,
10168 AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070010169 if (config->sample_rate == 0)
10170 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
10171 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
10172 config->sample_rate != 8000) {
10173 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
10174 ret = -EINVAL;
10175 goto err_open;
10176 }
10177 if (config->format == AUDIO_FORMAT_DEFAULT)
10178 config->format = AUDIO_FORMAT_PCM_16_BIT;
10179 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
10180 config->format = AUDIO_FORMAT_PCM_16_BIT;
10181 ret = -EINVAL;
10182 goto err_open;
10183 }
10184
10185 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
Zhou Song62ea0282020-03-22 19:53:01 +080010186 if (adev->ha_proxy_enable &&
10187 is_single_device_type_equal(&in->device_list,
10188 AUDIO_DEVICE_IN_TELEPHONY_RX))
10189 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY2;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070010190 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070010191 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -080010192 in->af_period_multiplier = 1;
10193 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
Shalini Manjunathaac412b32020-01-03 15:00:14 +053010194 (!voice_extn_is_compress_voip_supported()) &&
Aalique Grahame22e49102018-12-18 14:23:57 -080010195 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
10196 (config->sample_rate == 8000 ||
10197 config->sample_rate == 16000 ||
10198 config->sample_rate == 32000 ||
10199 config->sample_rate == 48000) &&
10200 channel_count == 1) {
10201 in->usecase = USECASE_AUDIO_RECORD_VOIP;
10202 in->config = pcm_config_audio_capture;
10203 frame_size = audio_stream_in_frame_size(&in->stream);
10204 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
10205 config->sample_rate,
10206 config->format,
10207 channel_count, false /*is_low_latency*/);
10208 in->config.period_size = buffer_size / frame_size;
10209 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
10210 in->config.rate = config->sample_rate;
10211 in->af_period_multiplier = 1;
Mingshu Pangc2d65042021-01-14 16:19:10 +080010212 } else if (in->realtime) {
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +053010213#ifdef PLATFORM_AUTO
Kogara Naveen Kumara688a812022-04-27 16:45:59 +053010214 switch(config->sample_rate)
10215 {
10216 case 48000:
10217 in->config = pcm_config_audio_capture_rt_48KHz;
10218 break;
10219 case 32000:
10220 in->config = pcm_config_audio_capture_rt_32KHz;
10221 break;
10222 case 24000:
10223 in->config = pcm_config_audio_capture_rt_24KHz;
10224 break;
10225 case 16000:
10226 in->config = pcm_config_audio_capture_rt_16KHz;
10227 break;
10228 case 8000:
10229 in->config = pcm_config_audio_capture_rt_8KHz;
10230 break;
10231 default:
10232 in->config = pcm_config_audio_capture_rt_48KHz;
10233 }
Mingshu Pangc2d65042021-01-14 16:19:10 +080010234 in->config.format = pcm_format_from_audio_format(config->format);
10235 in->af_period_multiplier = af_period_multiplier;
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +053010236#else
10237 in->config = pcm_config_audio_capture_rt_48KHz;
10238#endif
10239} else {
Revathi Uddarajud2634032017-12-07 14:42:34 +053010240 int ret_val;
10241 pthread_mutex_lock(&adev->lock);
10242 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
10243 in, config, &channel_mask_updated);
10244 pthread_mutex_unlock(&adev->lock);
10245
10246 if (!ret_val) {
10247 if (channel_mask_updated == true) {
10248 ALOGD("%s: return error to retry with updated channel mask (%#x)",
10249 __func__, config->channel_mask);
10250 ret = -EINVAL;
10251 goto err_open;
10252 }
10253 ALOGD("%s: created multi-channel session succesfully",__func__);
10254 } else if (audio_extn_compr_cap_enabled() &&
10255 audio_extn_compr_cap_format_supported(config->format) &&
10256 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
10257 audio_extn_compr_cap_init(in);
10258 } else if (audio_extn_cin_applicable_stream(in)) {
Deeraj Soman14230922019-01-30 16:39:30 +053010259 ret = audio_extn_cin_configure_input_stream(in, config);
Revathi Uddarajud2634032017-12-07 14:42:34 +053010260 if (ret)
10261 goto err_open;
10262 } else {
10263 in->config = pcm_config_audio_capture;
10264 in->config.rate = config->sample_rate;
10265 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +053010266 in->format = config->format;
10267 frame_size = audio_stream_in_frame_size(&in->stream);
10268 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -070010269 config->format,
10270 channel_count,
10271 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +020010272 /* prevent division-by-zero */
10273 if (frame_size == 0) {
10274 ALOGE("%s: Error frame_size==0", __func__);
10275 ret = -EINVAL;
10276 goto err_open;
10277 }
10278
Revathi Uddarajud2634032017-12-07 14:42:34 +053010279 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -080010280 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -080010281
Revathi Uddarajud2634032017-12-07 14:42:34 +053010282 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
10283 /* optionally use VOIP usecase depending on config(s) */
10284 ret = adev_update_voice_comm_input_stream(in, config);
10285 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -080010286
Revathi Uddarajud2634032017-12-07 14:42:34 +053010287 if (ret) {
10288 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
10289 goto err_open;
10290 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -080010291 }
Jaideep Sharmad305a4a2020-02-27 14:29:04 +053010292
10293 /* assign concurrent capture usecase if record has to caried out from
10294 * actual hardware input source */
10295 if (audio_extn_is_concurrent_capture_enabled() &&
10296 !audio_is_virtual_input_source(in->source)) {
Samyak Jainc37062f2019-04-25 18:41:06 +053010297 /* Acquire lock to avoid two concurrent use cases initialized to
10298 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +080010299
Samyak Jainc37062f2019-04-25 18:41:06 +053010300 if (in->usecase == USECASE_AUDIO_RECORD) {
10301 pthread_mutex_lock(&adev->lock);
10302 if (!(adev->pcm_record_uc_state)) {
10303 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
10304 adev->pcm_record_uc_state = 1;
10305 pthread_mutex_unlock(&adev->lock);
Krishna Kishor Jha0f4d8482022-02-18 10:56:05 +053010306 } else if (audio_extn_is_concurrent_pcm_record_enabled()) {
10307 in->usecase = get_record_usecase(adev);
10308 pthread_mutex_unlock(&adev->lock);
Samyak Jainc37062f2019-04-25 18:41:06 +053010309 } else {
10310 pthread_mutex_unlock(&adev->lock);
10311 /* Assign compress record use case for second record */
10312 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
10313 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
10314 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
10315 if (audio_extn_cin_applicable_stream(in)) {
10316 in->sample_rate = config->sample_rate;
Deeraj Soman14230922019-01-30 16:39:30 +053010317 ret = audio_extn_cin_configure_input_stream(in, config);
Samyak Jainc37062f2019-04-25 18:41:06 +053010318 if (ret)
10319 goto err_open;
10320 }
10321 }
10322 }
kunleiz28c73e72019-03-27 17:24:04 +080010323 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -070010324 }
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +053010325
Ramjee Singh82fd0c12019-08-21 16:31:33 +053010326 if (audio_extn_ssr_get_stream() != in)
10327 in->config.channels = channel_count;
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -070010328
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -070010329 in->sample_rate = in->config.rate;
10330
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010331 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
10332 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010333 &in->device_list, flags, in->format,
Haynes Mathew George4ffef292017-11-21 15:08:02 -080010334 in->sample_rate, in->bit_width,
10335 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +053010336 register_format(in->format, in->supported_formats);
10337 register_channel_mask(in->channel_mask, in->supported_channel_masks);
10338 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010339
Dechen Chai22768452021-07-30 09:29:16 +053010340#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -080010341 in->error_log = error_log_create(
10342 ERROR_LOG_ENTRIES,
10343 1000000000 /* aggregate consecutive identical errors within one second */);
Dechen Chai22768452021-07-30 09:29:16 +053010344#endif
Aalique Grahame22e49102018-12-18 14:23:57 -080010345
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010346 /* This stream could be for sound trigger lab,
10347 get sound trigger pcm if present */
10348 audio_extn_sound_trigger_check_and_get_session(in);
10349
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010350 lock_input_stream(in);
10351 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
10352 pthread_mutex_lock(&adev->lock);
10353 in->card_status = adev->card_status;
10354 pthread_mutex_unlock(&adev->lock);
10355 pthread_mutex_unlock(&in->lock);
10356
Aalique Grahame22e49102018-12-18 14:23:57 -080010357 stream_app_type_cfg_init(&in->app_type_cfg);
10358
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010359 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -080010360
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010361 ret = io_streams_map_insert(adev, &in->stream.common,
10362 handle, AUDIO_PATCH_HANDLE_NONE);
10363 if (ret != 0)
10364 goto err_open;
10365
Susan Wang6dd13092021-01-25 10:27:11 -050010366 in->in_ctxt.input = in;
Derek Chenf939fb72018-11-13 13:34:41 -080010367
10368 pthread_mutex_lock(&adev->lock);
Susan Wang6dd13092021-01-25 10:27:11 -050010369 list_add_tail(&adev->active_inputs_list, &in->in_ctxt.list);
Derek Chenf939fb72018-11-13 13:34:41 -080010370 pthread_mutex_unlock(&adev->lock);
10371
Eric Laurent994a6932013-07-17 11:51:42 -070010372 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -080010373 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010374
10375err_open:
Krishna Kishor Jha0f4d8482022-02-18 10:56:05 +053010376 if (audio_extn_is_concurrent_pcm_record_enabled() && is_pcm_record_usecase(in->usecase)) {
10377 free_record_usecase(adev, in->usecase);
10378 } else if (in->usecase == USECASE_AUDIO_RECORD) {
Samyak Jainc37062f2019-04-25 18:41:06 +053010379 pthread_mutex_lock(&adev->lock);
10380 adev->pcm_record_uc_state = 0;
10381 pthread_mutex_unlock(&adev->lock);
10382 }
Kogara Naveen Kumarc5758232022-11-07 20:25:40 +053010383 if (audio_extn_is_concurrent_low_latency_pcm_record_enabled() && is_pcm_low_latency_record_usecase(in->usecase)) {
10384 free_low_latency_record_usecase(adev, in->usecase);
10385 } else if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY) {
10386 pthread_mutex_lock(&adev->lock);
10387 adev->pcm_low_latency_record_uc_state = 0;
10388 pthread_mutex_unlock(&adev->lock);
10389 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010390 free(in);
10391 *stream_in = NULL;
10392 return ret;
10393}
10394
10395static void adev_close_input_stream(struct audio_hw_device *dev,
10396 struct audio_stream_in *stream)
10397{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080010398 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -070010399 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -070010400 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +053010401
Sidipotu Ashokf43018c2014-05-02 16:21:50 +053010402 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080010403
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010404 if (in == NULL) {
10405 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
10406 return;
10407 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010408 io_streams_map_remove(adev, in->capture_handle);
10409
Susan Wang6dd13092021-01-25 10:27:11 -050010410 // remove out_ctxt early to prevent the stream
10411 // being opened in a race condition
10412 pthread_mutex_lock(&adev->lock);
10413 list_remove(&in->in_ctxt.list);
10414 pthread_mutex_unlock(&adev->lock);
10415
kunleiz70e57612018-12-28 17:50:23 +080010416 /* must deregister from sndmonitor first to prevent races
10417 * between the callback and close_stream
10418 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010419 audio_extn_snd_mon_unregister_listener(stream);
10420
kunleiz70e57612018-12-28 17:50:23 +080010421 /* Disable echo reference if there are no active input, hfp call
10422 * and sound trigger while closing input stream
10423 */
Eric Laurent637e2d42018-11-15 12:24:31 -080010424 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +080010425 !audio_extn_hfp_is_active(adev) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010426 !audio_extn_sound_trigger_check_ec_ref_enable()) {
10427 struct listnode out_devices;
10428 list_init(&out_devices);
10429 platform_set_echo_reference(adev, false, &out_devices);
Zhenlin Lian4f947842022-05-14 15:50:52 +053010430 clear_devices(&out_devices);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010431 } else
kunleiz70e57612018-12-28 17:50:23 +080010432 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +053010433
Dechen Chai22768452021-07-30 09:29:16 +053010434#ifndef LINUX_ENABLED
Weiyin Jiang2995f662019-04-17 14:25:12 +080010435 error_log_destroy(in->error_log);
10436 in->error_log = NULL;
Dechen Chai22768452021-07-30 09:29:16 +053010437#endif
Pallavid7c7a272018-01-16 11:22:55 +053010438
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080010439 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +053010440 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080010441 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +053010442 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080010443 if (ret != 0)
10444 ALOGE("%s: Compress voip input cannot be closed, error:%d",
10445 __func__, ret);
10446 } else
10447 in_standby(&stream->common);
10448
Weiyin Jiang280ea742020-09-08 20:28:22 +080010449 pthread_mutex_destroy(&in->lock);
10450 pthread_mutex_destroy(&in->pre_lock);
10451
Revathi Uddarajud2634032017-12-07 14:42:34 +053010452 pthread_mutex_lock(&adev->lock);
Krishna Kishor Jha0f4d8482022-02-18 10:56:05 +053010453 if (audio_extn_is_concurrent_pcm_record_enabled() && is_pcm_record_usecase(in->usecase)) {
10454 free_record_usecase(adev, in->usecase);
10455 } else if (in->usecase == USECASE_AUDIO_RECORD) {
Samyak Jain15fda662018-12-18 16:40:52 +053010456 adev->pcm_record_uc_state = 0;
10457 }
10458
Kogara Naveen Kumarc5758232022-11-07 20:25:40 +053010459 if (audio_extn_is_concurrent_low_latency_pcm_record_enabled() && is_pcm_low_latency_record_usecase(in->usecase)) {
10460 free_low_latency_record_usecase(adev, in->usecase);
10461 } else if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY) {
10462 adev->pcm_low_latency_record_uc_state = 0;
10463 }
10464
Kunlei Zhang5d5d8d92020-02-26 15:00:59 +080010465 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
10466 adev->enable_voicerx = false;
10467 }
10468
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -070010469 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -070010470 audio_extn_ssr_deinit();
10471 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010472
Garmond Leunge2433c32017-09-28 21:51:22 -070010473 if (audio_extn_ffv_get_stream() == in) {
10474 audio_extn_ffv_stream_deinit();
10475 }
10476
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010477 if (audio_extn_compr_cap_enabled() &&
Subhadra Jagadeesan63a1e832023-01-13 11:26:38 +053010478 audio_extn_compr_cap_format_supported(pcm_format_to_audio_format((in->config).format)))
Mingming Yine62d7842013-10-25 16:26:03 -070010479 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +053010480
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +053010481 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +053010482 audio_extn_cin_free_input_stream_resources(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010483
Mingming Yinfd7607b2016-01-22 12:48:44 -080010484 if (in->is_st_session) {
10485 ALOGV("%s: sound trigger pcm stop lab", __func__);
10486 audio_extn_sound_trigger_stop_lab(in);
10487 }
Zhenlin Lian4f947842022-05-14 15:50:52 +053010488 clear_devices(&in->device_list);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010489 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +053010490 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010491 return;
10492}
10493
Aalique Grahame22e49102018-12-18 14:23:57 -080010494/* verifies input and output devices and their capabilities.
10495 *
10496 * This verification is required when enabling extended bit-depth or
10497 * sampling rates, as not all qcom products support it.
10498 *
10499 * Suitable for calling only on initialization such as adev_open().
10500 * It fills the audio_device use_case_table[] array.
10501 *
10502 * Has a side-effect that it needs to configure audio routing / devices
10503 * in order to power up the devices and read the device parameters.
10504 * It does not acquire any hw device lock. Should restore the devices
10505 * back to "normal state" upon completion.
10506 */
10507static int adev_verify_devices(struct audio_device *adev)
10508{
10509 /* enumeration is a bit difficult because one really wants to pull
10510 * the use_case, device id, etc from the hidden pcm_device_table[].
10511 * In this case there are the following use cases and device ids.
10512 *
10513 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
10514 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
10515 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
10516 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
10517 * [USECASE_AUDIO_RECORD] = {0, 0},
10518 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
10519 * [USECASE_VOICE_CALL] = {2, 2},
10520 *
10521 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
10522 * USECASE_VOICE_CALL omitted, but possible for either input or output.
10523 */
10524
10525 /* should be the usecases enabled in adev_open_input_stream() */
10526 static const int test_in_usecases[] = {
10527 USECASE_AUDIO_RECORD,
10528 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
10529 };
10530 /* should be the usecases enabled in adev_open_output_stream()*/
10531 static const int test_out_usecases[] = {
10532 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
10533 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
10534 };
10535 static const usecase_type_t usecase_type_by_dir[] = {
10536 PCM_PLAYBACK,
10537 PCM_CAPTURE,
10538 };
10539 static const unsigned flags_by_dir[] = {
10540 PCM_OUT,
10541 PCM_IN,
10542 };
10543
10544 size_t i;
10545 unsigned dir;
10546 const unsigned card_id = adev->snd_card;
10547
10548 for (dir = 0; dir < 2; ++dir) {
10549 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
10550 const unsigned flags_dir = flags_by_dir[dir];
10551 const size_t testsize =
10552 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
10553 const int *testcases =
10554 dir ? test_in_usecases : test_out_usecases;
10555 const audio_devices_t audio_device =
10556 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
10557
10558 for (i = 0; i < testsize; ++i) {
10559 const audio_usecase_t audio_usecase = testcases[i];
10560 int device_id;
10561 struct pcm_params **pparams;
10562 struct stream_out out;
10563 struct stream_in in;
10564 struct audio_usecase uc_info;
10565 int retval;
10566
10567 pparams = &adev->use_case_table[audio_usecase];
10568 pcm_params_free(*pparams); /* can accept null input */
10569 *pparams = NULL;
10570
10571 /* find the device ID for the use case (signed, for error) */
10572 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
10573 if (device_id < 0)
10574 continue;
10575
10576 /* prepare structures for device probing */
10577 memset(&uc_info, 0, sizeof(uc_info));
10578 uc_info.id = audio_usecase;
10579 uc_info.type = usecase_type;
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010580 list_init(&uc_info.device_list);
Aalique Grahame22e49102018-12-18 14:23:57 -080010581 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -080010582 memset(&in, 0, sizeof(in));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010583 list_init(&in.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010584 update_device_list(&in.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -080010585 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
10586 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -080010587 }
10588 memset(&out, 0, sizeof(out));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010589 list_init(&out.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010590 update_device_list(&out.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -080010591 uc_info.stream.out = &out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010592 update_device_list(&uc_info.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -080010593 uc_info.in_snd_device = SND_DEVICE_NONE;
10594 uc_info.out_snd_device = SND_DEVICE_NONE;
10595 list_add_tail(&adev->usecase_list, &uc_info.list);
10596
10597 /* select device - similar to start_(in/out)put_stream() */
10598 retval = select_devices(adev, audio_usecase);
10599 if (retval >= 0) {
10600 *pparams = pcm_params_get(card_id, device_id, flags_dir);
10601#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -070010602 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -080010603 if (*pparams) {
10604 ALOGV("%s: (%s) card %d device %d", __func__,
10605 dir ? "input" : "output", card_id, device_id);
10606 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
10607 } else {
10608 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
10609 }
10610#endif
10611 }
10612
10613 /* deselect device - similar to stop_(in/out)put_stream() */
10614 /* 1. Get and set stream specific mixer controls */
10615 retval = disable_audio_route(adev, &uc_info);
10616 /* 2. Disable the rx device */
10617 retval = disable_snd_device(adev,
10618 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
10619 list_remove(&uc_info.list);
10620 }
10621 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010622 return 0;
10623}
10624
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010625int update_patch(unsigned int num_sources,
10626 const struct audio_port_config *sources,
10627 unsigned int num_sinks,
10628 const struct audio_port_config *sinks,
10629 audio_patch_handle_t handle,
10630 struct audio_patch_info *p_info,
10631 patch_type_t patch_type, bool new_patch)
10632{
Aniket Kumar Latad13758f2020-08-06 15:11:36 -070010633 ALOGV("%s: enter", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010634
10635 if (p_info == NULL) {
10636 ALOGE("%s: Invalid patch pointer", __func__);
10637 return -EINVAL;
10638 }
10639
10640 if (new_patch) {
10641 p_info->patch = (struct audio_patch *) calloc(1, sizeof(struct audio_patch));
10642 if (p_info->patch == NULL) {
10643 ALOGE("%s: Could not allocate patch", __func__);
10644 return -ENOMEM;
10645 }
10646 }
10647
10648 p_info->patch->id = handle;
10649 p_info->patch->num_sources = num_sources;
10650 p_info->patch->num_sinks = num_sinks;
10651
10652 for (int i = 0; i < num_sources; i++)
10653 p_info->patch->sources[i] = sources[i];
10654 for (int i = 0; i < num_sinks; i++)
10655 p_info->patch->sinks[i] = sinks[i];
10656
10657 p_info->patch_type = patch_type;
10658 return 0;
10659}
10660
10661audio_patch_handle_t generate_patch_handle()
10662{
10663 static audio_patch_handle_t patch_handle = AUDIO_PATCH_HANDLE_NONE;
10664 if (++patch_handle < 0)
10665 patch_handle = AUDIO_PATCH_HANDLE_NONE + 1;
10666 return patch_handle;
10667}
10668
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010669int adev_create_audio_patch(struct audio_hw_device *dev,
10670 unsigned int num_sources,
10671 const struct audio_port_config *sources,
10672 unsigned int num_sinks,
10673 const struct audio_port_config *sinks,
10674 audio_patch_handle_t *handle)
10675{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010676 int ret = 0;
10677 struct audio_device *adev = (struct audio_device *)dev;
10678 struct audio_patch_info *p_info = NULL;
10679 patch_type_t patch_type = PATCH_NONE;
10680 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10681 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
10682 struct audio_stream_info *s_info = NULL;
10683 struct audio_stream *stream = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010684 struct listnode devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010685 audio_devices_t device_type = AUDIO_DEVICE_NONE;
10686 bool new_patch = false;
10687 char addr[AUDIO_DEVICE_MAX_ADDRESS_LEN];
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010688
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010689 ALOGD("%s: enter: num sources %d, num_sinks %d, handle %d", __func__,
10690 num_sources, num_sinks, *handle);
10691
10692 if (num_sources == 0 || num_sources > AUDIO_PATCH_PORTS_MAX ||
10693 num_sinks == 0 || num_sinks > AUDIO_PATCH_PORTS_MAX) {
10694 ALOGE("%s: Invalid patch arguments", __func__);
10695 ret = -EINVAL;
10696 goto done;
10697 }
10698
10699 if (num_sources > 1) {
10700 ALOGE("%s: Multiple sources are not supported", __func__);
10701 ret = -EINVAL;
10702 goto done;
10703 }
10704
10705 if (sources == NULL || sinks == NULL) {
10706 ALOGE("%s: Invalid sources or sinks port config", __func__);
10707 ret = -EINVAL;
10708 goto done;
10709 }
10710
10711 ALOGV("%s: source role %d, source type %d", __func__,
10712 sources[0].type, sources[0].role);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010713 list_init(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010714
10715 // Populate source/sink information and fetch stream info
10716 switch (sources[0].type) {
10717 case AUDIO_PORT_TYPE_DEVICE: // Patch for audio capture or loopback
10718 device_type = sources[0].ext.device.type;
10719 strlcpy(&addr[0], &sources[0].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010720 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010721 if (sinks[0].type == AUDIO_PORT_TYPE_MIX) {
10722 patch_type = PATCH_CAPTURE;
10723 io_handle = sinks[0].ext.mix.handle;
10724 input_source = sinks[0].ext.mix.usecase.source;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010725 ALOGD("%s: Capture patch from device %x to mix %d",
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010726 __func__, device_type, io_handle);
10727 } else {
10728 // Device to device patch is not implemented.
10729 // This space will need changes if audio HAL
10730 // handles device to device patches in the future.
10731 patch_type = PATCH_DEVICE_LOOPBACK;
10732 }
10733 break;
10734 case AUDIO_PORT_TYPE_MIX: // Patch for audio playback
10735 io_handle = sources[0].ext.mix.handle;
10736 for (int i = 0; i < num_sinks; i++) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010737 device_type = sinks[i].ext.device.type;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010738 strlcpy(&addr[0], &sinks[i].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010739 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010740 }
10741 patch_type = PATCH_PLAYBACK;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010742 ALOGD("%s: Playback patch from mix handle %d to device %x",
10743 __func__, io_handle, get_device_types(&devices));
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010744 break;
10745 case AUDIO_PORT_TYPE_SESSION:
10746 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010747 ALOGE("%s: Unsupported source type %d", __func__, sources[0].type);
10748 ret = -EINVAL;
10749 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010750 }
10751
10752 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010753
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010754 // Generate patch info and update patch
10755 if (*handle == AUDIO_PATCH_HANDLE_NONE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010756 *handle = generate_patch_handle();
10757 p_info = (struct audio_patch_info *)
10758 calloc(1, sizeof(struct audio_patch_info));
10759 if (p_info == NULL) {
10760 ALOGE("%s: Failed to allocate memory", __func__);
10761 pthread_mutex_unlock(&adev->lock);
10762 ret = -ENOMEM;
10763 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010764 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010765 new_patch = true;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010766 } else {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010767 p_info = fetch_patch_info_l(adev, *handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010768 if (p_info == NULL) {
10769 ALOGE("%s: Unable to fetch patch for received patch handle %d",
10770 __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010771 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010772 ret = -EINVAL;
10773 goto done;
10774 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010775 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010776 update_patch(num_sources, sources, num_sinks, sinks,
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010777 *handle, p_info, patch_type, new_patch);
10778
10779 // Fetch stream info of associated mix for playback or capture patches
10780 if (p_info->patch_type == PATCH_PLAYBACK ||
10781 p_info->patch_type == PATCH_CAPTURE) {
10782 s_info = hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10783 if (s_info == NULL) {
10784 ALOGE("%s: Failed to obtain stream info", __func__);
10785 if (new_patch)
10786 free(p_info);
10787 pthread_mutex_unlock(&adev->lock);
10788 ret = -EINVAL;
10789 goto done;
10790 }
10791 ALOGV("%s: Fetched stream info with io_handle %d", __func__, io_handle);
10792 s_info->patch_handle = *handle;
10793 stream = s_info->stream;
10794 }
10795 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010796
10797 // Update routing for stream
10798 if (stream != NULL) {
Revathi Uddaraju4255a632021-12-02 05:11:13 -080010799 if (p_info->patch_type == PATCH_PLAYBACK) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010800 ret = route_output_stream((struct stream_out *) stream, &devices);
Revathi Uddaraju4255a632021-12-02 05:11:13 -080010801 } else if (p_info->patch_type == PATCH_CAPTURE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010802 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Revathi Uddaraju4255a632021-12-02 05:11:13 -080010803 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010804 if (ret < 0) {
10805 pthread_mutex_lock(&adev->lock);
10806 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10807 if (new_patch)
10808 free(p_info);
10809 pthread_mutex_unlock(&adev->lock);
10810 ALOGE("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10811 goto done;
10812 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010813 }
10814
10815 // Add new patch to patch map
10816 if (!ret && new_patch) {
10817 pthread_mutex_lock(&adev->lock);
10818 hashmapPut(adev->patch_map, (void *) (intptr_t) *handle, (void *) p_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010819 ALOGD("%s: Added a new patch with handle %d", __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010820 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010821 }
10822
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010823done:
Zhenlin Lian4f947842022-05-14 15:50:52 +053010824 clear_devices(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010825 audio_extn_hw_loopback_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010826 num_sources,
10827 sources,
10828 num_sinks,
10829 sinks,
10830 handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010831 audio_extn_auto_hal_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010832 num_sources,
10833 sources,
10834 num_sinks,
10835 sinks,
10836 handle);
10837 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010838}
10839
10840int adev_release_audio_patch(struct audio_hw_device *dev,
10841 audio_patch_handle_t handle)
10842{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010843 struct audio_device *adev = (struct audio_device *) dev;
10844 int ret = 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010845 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010846 struct audio_stream *stream = NULL;
Derek Chenf939fb72018-11-13 13:34:41 -080010847
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010848 if (handle == AUDIO_PATCH_HANDLE_NONE) {
10849 ALOGE("%s: Invalid patch handle %d", __func__, handle);
10850 ret = -EINVAL;
10851 goto done;
10852 }
10853
10854 ALOGD("%s: Remove patch with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010855 pthread_mutex_lock(&adev->lock);
10856 struct audio_patch_info *p_info = fetch_patch_info_l(adev, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010857 if (p_info == NULL) {
10858 ALOGE("%s: Patch info not found with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010859 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010860 ret = -EINVAL;
10861 goto done;
10862 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010863 struct audio_patch *patch = p_info->patch;
10864 if (patch == NULL) {
10865 ALOGE("%s: Patch not found for handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010866 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010867 ret = -EINVAL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010868 goto done;
10869 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010870 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10871 switch (patch->sources[0].type) {
10872 case AUDIO_PORT_TYPE_MIX:
10873 io_handle = patch->sources[0].ext.mix.handle;
10874 break;
10875 case AUDIO_PORT_TYPE_DEVICE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010876 if (p_info->patch_type == PATCH_CAPTURE)
10877 io_handle = patch->sinks[0].ext.mix.handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010878 break;
10879 case AUDIO_PORT_TYPE_SESSION:
10880 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010881 pthread_mutex_unlock(&adev->lock);
10882 ret = -EINVAL;
10883 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010884 }
10885
10886 // Remove patch and reset patch handle in stream info
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010887 patch_type_t patch_type = p_info->patch_type;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010888 patch_map_remove_l(adev, handle);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010889 if (patch_type == PATCH_PLAYBACK ||
10890 patch_type == PATCH_CAPTURE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010891 struct audio_stream_info *s_info =
10892 hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10893 if (s_info == NULL) {
10894 ALOGE("%s: stream for io_handle %d is not available", __func__, io_handle);
10895 pthread_mutex_unlock(&adev->lock);
10896 goto done;
10897 }
10898 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10899 stream = s_info->stream;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010900 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010901 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010902
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010903 if (stream != NULL) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010904 struct listnode devices;
10905 list_init(&devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010906 if (patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010907 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010908 else if (patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010909 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Zhenlin Lian4f947842022-05-14 15:50:52 +053010910 clear_devices(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010911 }
10912
10913 if (ret < 0)
10914 ALOGW("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10915
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010916done:
10917 audio_extn_hw_loopback_release_audio_patch(dev, handle);
10918 audio_extn_auto_hal_release_audio_patch(dev, handle);
10919
10920 ALOGV("%s: Successfully released patch %d", __func__, handle);
Derek Chenf939fb72018-11-13 13:34:41 -080010921 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010922}
10923
10924int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
10925{
Derek Chenf13dd492018-11-13 14:53:51 -080010926 int ret = 0;
10927
10928 ret = audio_extn_hw_loopback_get_audio_port(dev, config);
10929 ret |= audio_extn_auto_hal_get_audio_port(dev, config);
10930 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010931}
10932
10933int adev_set_audio_port_config(struct audio_hw_device *dev,
10934 const struct audio_port_config *config)
10935{
Derek Chenf13dd492018-11-13 14:53:51 -080010936 int ret = 0;
10937
10938 ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
10939 ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
10940 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010941}
10942
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -070010943static int adev_dump(const audio_hw_device_t *device __unused,
10944 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010945{
10946 return 0;
10947}
10948
10949static int adev_close(hw_device_t *device)
10950{
Aalique Grahame22e49102018-12-18 14:23:57 -080010951 size_t i;
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010952 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -070010953
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010954 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -070010955 return 0;
10956
10957 pthread_mutex_lock(&adev_init_lock);
10958
10959 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +053010960 if (audio_extn_spkr_prot_is_enabled())
10961 audio_extn_spkr_prot_deinit();
Jaideep Sharmaa2b49672019-09-10 20:37:03 +053010962 audio_extn_battery_properties_listener_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010963 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010964 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -080010965 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010966 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -080010967 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010968 audio_extn_utils_release_streams_cfg_lists(
10969 &adev->streams_output_cfg_list,
10970 &adev->streams_input_cfg_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010971 if (audio_extn_qap_is_enabled())
10972 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010973 if (audio_extn_qaf_is_enabled())
10974 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -070010975 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +080010976 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -070010977 free(adev->snd_dev_ref_cnt);
10978 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010979 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
10980 pcm_params_free(adev->use_case_table[i]);
10981 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010982 if (adev->adm_deinit)
10983 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010984 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010985 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010986 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010987 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010988 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010989 if (adev->device_cfg_params) {
10990 free(adev->device_cfg_params);
10991 adev->device_cfg_params = NULL;
10992 }
Derek Chend2530072014-11-24 12:39:14 -080010993 if(adev->ext_hw_plugin)
10994 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -080010995 audio_extn_auto_hal_deinit();
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010996 free_map(adev->patch_map);
10997 free_map(adev->io_streams_map);
Kiran Kandi910e1862013-10-29 13:29:42 -070010998 free(device);
10999 adev = NULL;
11000 }
11001 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +053011002 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011003 return 0;
11004}
11005
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070011006/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
11007 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
11008 * just that it _might_ work.
11009 */
11010static int period_size_is_plausible_for_low_latency(int period_size)
11011{
11012 switch (period_size) {
11013 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -070011014 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070011015 case 240:
11016 case 320:
11017 case 480:
11018 return 1;
11019 default:
11020 return 0;
11021 }
11022}
11023
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053011024static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
11025{
11026 bool is_snd_card_status = false;
11027 bool is_ext_device_status = false;
11028 char value[32];
11029 int card = -1;
11030 card_status_t status;
11031
11032 if (cookie != adev || !parms)
11033 return;
11034
11035 if (!parse_snd_card_status(parms, &card, &status)) {
11036 is_snd_card_status = true;
11037 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
11038 is_ext_device_status = true;
11039 } else {
11040 // not a valid event
11041 return;
11042 }
11043
11044 pthread_mutex_lock(&adev->lock);
11045 if (card == adev->snd_card || is_ext_device_status) {
11046 if (is_snd_card_status && adev->card_status != status) {
Jaideep Sharmacb402512020-09-24 17:51:07 +053011047 ALOGD("%s card_status %d", __func__, status);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053011048 adev->card_status = status;
11049 platform_snd_card_update(adev->platform, status);
11050 audio_extn_fm_set_parameters(adev, parms);
Derek Chend6f371d2019-03-01 13:45:58 -080011051 audio_extn_auto_hal_set_parameters(adev, parms);
Zhou Song4f43e352019-07-02 00:32:23 +080011052 if (status == CARD_STATUS_OFFLINE)
11053 audio_extn_sco_reset_configuration();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053011054 } else if (is_ext_device_status) {
11055 platform_set_parameters(adev->platform, parms);
11056 }
11057 }
11058 pthread_mutex_unlock(&adev->lock);
11059 return;
11060}
11061
Weiyin Jiang280ea742020-09-08 20:28:22 +080011062/* adev lock held */
11063int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011064{
11065 struct audio_usecase *uc_info;
Zhou Song407e5aa2020-12-27 19:13:04 +080011066 struct audio_usecase *usecase;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080011067 struct listnode devices;
Zhou Song407e5aa2020-12-27 19:13:04 +080011068 struct listnode *node;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011069
11070 uc_info = get_usecase_from_list(adev, out->usecase);
11071 if (uc_info == NULL) {
11072 ALOGE("%s: Could not find the usecase (%d) in the list",
11073 __func__, out->usecase);
11074 return -EINVAL;
11075 }
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080011076 list_init(&devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011077
Zhou Songbaddf9f2020-11-20 13:57:39 +080011078 ALOGD("%s: enter: usecase(%d: %s), a2dp muted %d", __func__,
11079 out->usecase, use_case_table[out->usecase], out->a2dp_muted);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011080
11081 if (restore) {
Weiyin Jiang280ea742020-09-08 20:28:22 +080011082 pthread_mutex_lock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011083 // restore A2DP device for active usecases and unmute if required
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080011084 if (is_a2dp_out_device_type(&out->device_list)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011085 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
Zhou Songe5225132019-09-26 15:33:36 +080011086 if (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)
11087 select_devices(adev, uc_info->id);
Zhou Songbaddf9f2020-11-20 13:57:39 +080011088
11089 if (is_offload_usecase(out->usecase)) {
11090 if (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)
Weiyin Jiang280ea742020-09-08 20:28:22 +080011091 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
Zhou Songbaddf9f2020-11-20 13:57:39 +080011092 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
11093 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
11094 } else {
11095 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011096 }
Zhou Songbaddf9f2020-11-20 13:57:39 +080011097 out->a2dp_muted = false;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011098 }
Weiyin Jiang280ea742020-09-08 20:28:22 +080011099 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011100 } else {
Weiyin Jiang280ea742020-09-08 20:28:22 +080011101 pthread_mutex_lock(&out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +080011102 // mute stream and switch to speaker if suspended
11103 if (!out->a2dp_muted && !out->standby) {
Zhou Songbaddf9f2020-11-20 13:57:39 +080011104 assign_devices(&devices, &out->device_list);
11105 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Zhou Song407e5aa2020-12-27 19:13:04 +080011106 list_for_each(node, &adev->usecase_list) {
11107 usecase = node_to_item(node, struct audio_usecase, list);
Zhou Songe63b6fe2021-04-15 13:54:46 +080011108 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
11109 !is_a2dp_out_device_type(&usecase->stream.out->device_list) &&
Zhou Songcf77af02021-05-14 18:21:14 +080011110 !is_sco_out_device_type(&usecase->stream.out->device_list) &&
Zhou Songe63b6fe2021-04-15 13:54:46 +080011111 platform_check_backends_match(SND_DEVICE_OUT_SPEAKER,
11112 usecase->out_snd_device)) {
Zhou Song407e5aa2020-12-27 19:13:04 +080011113 assign_devices(&out->device_list, &usecase->stream.out->device_list);
11114 break;
11115 }
11116 }
Zhou Songcf77af02021-05-14 18:21:14 +080011117 if ((is_a2dp_out_device_type(&devices) && list_length(&devices) == 1) ||
11118 (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)) {
Zhou Song8edbbdb2021-01-14 16:48:03 +080011119 out->a2dp_muted = true;
11120 if (is_offload_usecase(out->usecase)) {
11121 if (out->offload_state == OFFLOAD_STATE_PLAYING)
11122 compress_pause(out->compr);
11123 out_set_compr_volume(&out->stream, (float)0, (float)0);
Zhou Song8edbbdb2021-01-14 16:48:03 +080011124 } else {
Weiyin Jiang906db3c2021-03-02 13:17:04 +080011125 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
11126 out_set_voip_volume(&out->stream, (float)0, (float)0);
11127 else
11128 out_set_pcm_volume(&out->stream, (float)0, (float)0);
11129
Zhou Song8edbbdb2021-01-14 16:48:03 +080011130 /* wait for stale pcm drained before switching to speaker */
11131 uint32_t latency =
11132 (out->config.period_count * out->config.period_size * 1000) /
11133 (out->config.rate);
11134 usleep(latency * 1000);
11135 }
Zhou Songbaddf9f2020-11-20 13:57:39 +080011136 }
11137 select_devices(adev, out->usecase);
Zhou Song8edbbdb2021-01-14 16:48:03 +080011138 ALOGD("%s: switched to device:%s and stream muted:%d", __func__,
11139 platform_get_snd_device_name(uc_info->out_snd_device), out->a2dp_muted);
Zhou Songbaddf9f2020-11-20 13:57:39 +080011140 if (is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011141 if (out->offload_state == OFFLOAD_STATE_PLAYING)
11142 compress_resume(out->compr);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011143 }
Zhou Songbaddf9f2020-11-20 13:57:39 +080011144 assign_devices(&out->device_list, &devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011145 }
Weiyin Jiang280ea742020-09-08 20:28:22 +080011146 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011147 }
Zhenlin Lian4f947842022-05-14 15:50:52 +053011148 clear_devices(&devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011149 ALOGV("%s: exit", __func__);
11150 return 0;
11151}
11152
Haynes Mathew George01156f92018-04-13 15:29:54 -070011153void adev_on_battery_status_changed(bool charging)
11154{
11155 pthread_mutex_lock(&adev->lock);
11156 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
11157 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +080011158 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -070011159 pthread_mutex_unlock(&adev->lock);
11160}
11161
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011162static int adev_open(const hw_module_t *module, const char *name,
11163 hw_device_t **device)
11164{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053011165 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -080011166 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053011167 char mixer_ctl_name[128] = {0};
11168 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053011169
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080011170 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011171 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
11172
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070011173 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -070011174 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070011175 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -070011176 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070011177 ALOGD("%s: returning existing instance of adev", __func__);
11178 ALOGD("%s: exit", __func__);
11179 pthread_mutex_unlock(&adev_init_lock);
11180 return 0;
11181 }
11182
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011183 adev = calloc(1, sizeof(struct audio_device));
11184
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -070011185 if (!adev) {
11186 pthread_mutex_unlock(&adev_init_lock);
11187 return -ENOMEM;
11188 }
11189
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -070011190 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
11191
Weiyin Jiange6ce6312019-01-28 18:28:22 +080011192 // register audio ext hidl at the earliest
11193 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053011194#ifdef DYNAMIC_LOG_ENABLED
11195 register_for_dynamic_logging("hal");
11196#endif
11197
Derek Chenf939fb72018-11-13 13:34:41 -080011198 /* default audio HAL major version */
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011199 uint32_t maj_version = 3;
Derek Chenf939fb72018-11-13 13:34:41 -080011200 if(property_get("vendor.audio.hal.maj.version", value, NULL))
11201 maj_version = atoi(value);
11202
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011203 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -080011204 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011205 adev->device.common.module = (struct hw_module_t *)module;
11206 adev->device.common.close = adev_close;
11207
11208 adev->device.init_check = adev_init_check;
11209 adev->device.set_voice_volume = adev_set_voice_volume;
11210 adev->device.set_master_volume = adev_set_master_volume;
11211 adev->device.get_master_volume = adev_get_master_volume;
11212 adev->device.set_master_mute = adev_set_master_mute;
11213 adev->device.get_master_mute = adev_get_master_mute;
11214 adev->device.set_mode = adev_set_mode;
11215 adev->device.set_mic_mute = adev_set_mic_mute;
11216 adev->device.get_mic_mute = adev_get_mic_mute;
11217 adev->device.set_parameters = adev_set_parameters;
11218 adev->device.get_parameters = adev_get_parameters;
11219 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
11220 adev->device.open_output_stream = adev_open_output_stream;
11221 adev->device.close_output_stream = adev_close_output_stream;
11222 adev->device.open_input_stream = adev_open_input_stream;
11223 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053011224 adev->device.create_audio_patch = adev_create_audio_patch;
11225 adev->device.release_audio_patch = adev_release_audio_patch;
11226 adev->device.get_audio_port = adev_get_audio_port;
11227 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011228 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +053011229 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011230
11231 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011232 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -080011233 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011234 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011235 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -080011236 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -070011237 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +053011238 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -070011239 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -070011240 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -070011241 /* Init audio and voice feature */
11242 audio_extn_feature_init();
11243 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070011244 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -080011245 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -080011246 list_init(&adev->active_inputs_list);
11247 list_init(&adev->active_outputs_list);
Rahul Sharma99770982019-03-06 17:05:26 +053011248 list_init(&adev->audio_patch_record_list);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011249 adev->io_streams_map = hashmapCreate(AUDIO_IO_PORTS_MAX, audio_extn_utils_hash_fn,
11250 audio_extn_utils_hash_eq);
11251 if (!adev->io_streams_map) {
11252 ALOGE("%s: Could not create io streams map", __func__);
11253 ret = -ENOMEM;
11254 goto adev_open_err;
11255 }
11256 adev->patch_map = hashmapCreate(AUDIO_PATCH_PORTS_MAX, audio_extn_utils_hash_fn,
11257 audio_extn_utils_hash_eq);
11258 if (!adev->patch_map) {
11259 ALOGE("%s: Could not create audio patch map", __func__);
11260 ret = -ENOMEM;
11261 goto adev_open_err;
11262 }
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -080011263 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -070011264 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +053011265 adev->pcm_record_uc_state = 0;
Kogara Naveen Kumarc5758232022-11-07 20:25:40 +053011266 adev->pcm_low_latency_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +053011267 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +053011268 adev->perf_lock_opts[0] = 0x101;
11269 adev->perf_lock_opts[1] = 0x20E;
11270 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +080011271 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -070011272 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053011273 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070011274 adev->adm_routing_changed = false;
Revathi Uddarajub26e3932020-06-10 14:51:02 +053011275 adev->a2dp_started = false;
Zhou Song503196b2021-07-23 17:31:05 +080011276 adev->ha_proxy_enable = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +053011277
Zhou Song68ebc352019-12-05 17:11:15 +080011278 audio_extn_perf_lock_init();
11279
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011280 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -070011281 adev->platform = platform_init(adev);
11282 if (!adev->platform) {
Eric Laurentb23d5282013-05-14 15:27:20 -070011283 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011284 ret = -EINVAL;
11285 goto adev_open_err;
Eric Laurentb23d5282013-05-14 15:27:20 -070011286 }
Eric Laurentc4aef752013-09-12 17:45:53 -070011287
Aalique Grahame22e49102018-12-18 14:23:57 -080011288 adev->extspk = audio_extn_extspk_init(adev);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053011289 if (audio_extn_qap_is_enabled()) {
11290 ret = audio_extn_qap_init(adev);
11291 if (ret < 0) {
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053011292 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011293 goto adev_open_err;
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053011294 }
11295 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
11296 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
11297 }
Aalique Grahame22e49102018-12-18 14:23:57 -080011298
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053011299 if (audio_extn_qaf_is_enabled()) {
11300 ret = audio_extn_qaf_init(adev);
11301 if (ret < 0) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053011302 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011303 goto adev_open_err;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053011304 }
11305
11306 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
11307 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
11308 }
11309
Derek Chenae7b0342019-02-08 15:17:04 -080011310 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -080011311 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
11312
Eric Laurentc4aef752013-09-12 17:45:53 -070011313 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
11314 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
11315 if (adev->visualizer_lib == NULL) {
11316 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
11317 } else {
11318 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
11319 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080011320 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070011321 "visualizer_hal_start_output");
11322 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080011323 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070011324 "visualizer_hal_stop_output");
11325 }
11326 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +053011327 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080011328 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -080011329 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +080011330 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +053011331 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070011332 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -070011333
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080011334 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
11335 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
11336 if (adev->offload_effects_lib == NULL) {
11337 ALOGE("%s: DLOPEN failed for %s", __func__,
11338 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
11339 } else {
11340 ALOGV("%s: DLOPEN successful for %s", __func__,
11341 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
11342 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +053011343 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080011344 "offload_effects_bundle_hal_start_output");
11345 adev->offload_effects_stop_output =
11346 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
11347 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080011348 adev->offload_effects_set_hpx_state =
11349 (int (*)(bool))dlsym(adev->offload_effects_lib,
11350 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +053011351 adev->offload_effects_get_parameters =
11352 (void (*)(struct str_parms *, struct str_parms *))
11353 dlsym(adev->offload_effects_lib,
11354 "offload_effects_bundle_get_parameters");
11355 adev->offload_effects_set_parameters =
11356 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
11357 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080011358 }
11359 }
11360
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070011361 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
11362 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
11363 if (adev->adm_lib == NULL) {
11364 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
11365 } else {
11366 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
11367 adev->adm_init = (adm_init_t)
11368 dlsym(adev->adm_lib, "adm_init");
11369 adev->adm_deinit = (adm_deinit_t)
11370 dlsym(adev->adm_lib, "adm_deinit");
11371 adev->adm_register_input_stream = (adm_register_input_stream_t)
11372 dlsym(adev->adm_lib, "adm_register_input_stream");
11373 adev->adm_register_output_stream = (adm_register_output_stream_t)
11374 dlsym(adev->adm_lib, "adm_register_output_stream");
11375 adev->adm_deregister_stream = (adm_deregister_stream_t)
11376 dlsym(adev->adm_lib, "adm_deregister_stream");
11377 adev->adm_request_focus = (adm_request_focus_t)
11378 dlsym(adev->adm_lib, "adm_request_focus");
11379 adev->adm_abandon_focus = (adm_abandon_focus_t)
11380 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -070011381 adev->adm_set_config = (adm_set_config_t)
11382 dlsym(adev->adm_lib, "adm_set_config");
11383 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
11384 dlsym(adev->adm_lib, "adm_request_focus_v2");
11385 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
11386 dlsym(adev->adm_lib, "adm_is_noirq_avail");
11387 adev->adm_on_routing_change = (adm_on_routing_change_t)
11388 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070011389 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
11390 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070011391 }
11392 }
11393
Aalique Grahame22e49102018-12-18 14:23:57 -080011394 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070011395 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +080011396 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Kunlei Zhanga3c4cb02021-03-05 16:03:54 +080011397 adev->fluence_nn_usecase_id = USECASE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -080011398 //initialize this to false for now,
11399 //this will be set to true through set param
11400 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070011401
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -070011402 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011403 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -080011404
11405 if (k_enable_extended_precision)
11406 adev_verify_devices(adev);
11407
Xiaojun Sang785b5da2017-08-03 15:52:29 +080011408 adev->dsp_bit_width_enforce_mode =
11409 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011410
Dhananjay Kumard6d32152016-10-13 16:11:03 +053011411 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
11412 &adev->streams_output_cfg_list,
11413 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070011414
Kiran Kandi910e1862013-10-29 13:29:42 -070011415 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070011416
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070011417 int trial;
Manisha Agarwalc75a0202019-12-06 18:48:25 +053011418 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070011419 trial = atoi(value);
11420 if (period_size_is_plausible_for_low_latency(trial)) {
11421 pcm_config_low_latency.period_size = trial;
11422 pcm_config_low_latency.start_threshold = trial / 4;
11423 pcm_config_low_latency.avail_min = trial / 4;
11424 configured_low_latency_capture_period_size = trial;
11425 }
11426 }
ronghuiz93177262021-04-21 19:58:13 +080011427 if (property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070011428 trial = atoi(value);
11429 if (period_size_is_plausible_for_low_latency(trial)) {
11430 configured_low_latency_capture_period_size = trial;
11431 }
11432 }
11433
Vignesh Kulothungan7d374312018-02-21 17:12:00 -080011434 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
11435
Eric Laurent4b084132018-10-19 17:33:43 -070011436 adev->camera_orientation = CAMERA_DEFAULT;
11437
Manisha Agarwalc75a0202019-12-06 18:48:25 +053011438 if (property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -070011439 af_period_multiplier = atoi(value);
11440 if (af_period_multiplier < 0)
11441 af_period_multiplier = 2;
11442 else if (af_period_multiplier > 4)
11443 af_period_multiplier = 4;
11444
11445 ALOGV("new period_multiplier = %d", af_period_multiplier);
11446 }
11447
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080011448 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080011449
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -070011450 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070011451 pthread_mutex_unlock(&adev_init_lock);
11452
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070011453 if (adev->adm_init)
11454 adev->adm_data = adev->adm_init();
11455
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053011456 qahwi_init(*device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080011457 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053011458
11459 audio_extn_snd_mon_init();
11460 pthread_mutex_lock(&adev->lock);
11461 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
11462 adev->card_status = CARD_STATUS_ONLINE;
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -050011463 adev->out_power_policy = POWER_POLICY_STATUS_ONLINE;
11464 adev->in_power_policy = POWER_POLICY_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -070011465 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
11466 /*
11467 * if the battery state callback happens before charging can be queried,
11468 * it will be guarded with the adev->lock held in the cb function and so
11469 * the callback value will reflect the latest state
11470 */
11471 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053011472 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +080011473 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -070011474 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +080011475 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053011476 /* Allocate memory for Device config params */
11477 adev->device_cfg_params = (struct audio_device_config_param*)
11478 calloc(platform_get_max_codec_backend(),
11479 sizeof(struct audio_device_config_param));
11480 if (adev->device_cfg_params == NULL)
11481 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053011482
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053011483 /*
11484 * Check if new PSPD matrix mixer control is supported. If not
11485 * supported, then set flag so that old mixer ctrl is sent while
11486 * sending pspd coefficients on older kernel version. Query mixer
11487 * control for default pcm id and channel value one.
11488 */
11489 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
11490 "AudStr %d ChMixer Weight Ch %d", 0, 1);
11491
11492 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
11493 if (!ctl) {
11494 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
11495 __func__, mixer_ctl_name);
11496 adev->use_old_pspd_mix_ctrl = true;
11497 }
11498
Jaideep Sharma0fa53812020-09-17 09:00:11 +053011499 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011500 return 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011501
11502adev_open_err:
11503 free_map(adev->patch_map);
11504 free_map(adev->io_streams_map);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080011505 free(adev->snd_dev_ref_cnt);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011506 pthread_mutex_destroy(&adev->lock);
11507 free(adev);
11508 adev = NULL;
11509 *device = NULL;
11510 pthread_mutex_unlock(&adev_init_lock);
11511 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011512}
11513
11514static struct hw_module_methods_t hal_module_methods = {
11515 .open = adev_open,
11516};
11517
11518struct audio_module HAL_MODULE_INFO_SYM = {
11519 .common = {
11520 .tag = HARDWARE_MODULE_TAG,
11521 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
11522 .hal_api_version = HARDWARE_HAL_API_VERSION,
11523 .id = AUDIO_HARDWARE_MODULE_ID,
11524 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -080011525 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011526 .methods = &hal_module_methods,
11527 },
11528};