blob: 2822751e92eac25c0f41114ffa9e16fe98a25651 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Ramu Gottipatifa5be522021-12-28 19:18:21 +05302 * Copyright (c) 2013-2022, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Sandhya Mutha Naga Venkataa597a962023-02-07 11:35:51 +053036 *
sasevsdec27fa2023-04-12 10:50:47 +053037 * Changes from Qualcomm Innovation Center are provided under the following license:
Sandhya Mutha Naga Venkataa597a962023-02-07 11:35:51 +053038 * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
sasevsdec27fa2023-04-12 10:50:47 +053039 * SPDX-License-Identifier: BSD-3-Clause-Clear
40 *
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080041 */
42
43#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070044#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080045/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070046/*#define VERY_VERY_VERBOSE_LOGGING*/
47#ifdef VERY_VERY_VERBOSE_LOGGING
48#define ALOGVV ALOGV
49#else
50#define ALOGVV(a...) do { } while(0)
51#endif
George Gao3018ede2019-10-23 13:23:00 -070052#include <limits.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <errno.h>
54#include <pthread.h>
55#include <stdint.h>
56#include <sys/time.h>
57#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080058#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070059#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070060#include <sys/resource.h>
61#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080062
Aalique Grahame22e49102018-12-18 14:23:57 -080063#include <log/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070064#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080065#include <cutils/str_parms.h>
66#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070067#include <cutils/atomic.h>
68#include <cutils/sched_policy.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070069#include <hardware/audio_effect.h>
Haynes Mathew George484e8d22017-07-31 18:55:17 -070070#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070071#include <system/thread_defs.h>
Haynes Mathew George16081042017-05-31 17:16:49 -070072#include <tinyalsa/asoundlib.h>
Andy Hunga1f48fa2019-07-01 18:14:53 -070073#include <utils/Timers.h> // systemTime
Eric Laurentb23d5282013-05-14 15:27:20 -070074#include <audio_effects/effect_aec.h>
75#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053076#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080077#include "audio_hw.h"
Wei Wangf7ca6c92017-11-21 14:51:20 -080078#include "audio_perf.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070079#include "platform_api.h"
80#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070081#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080082#include "voice_extn.h"
Ashish Jaind5694242017-09-05 20:09:06 +053083#include "ip_hdlr_intf.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080084
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070085#include "sound/compress_params.h"
Xiaojun Sang782e5b12020-06-29 21:13:06 +080086
87#ifdef AUDIO_GKI_ENABLED
88#include "sound/audio_compressed_formats.h"
89#endif
90
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080091#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080092
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053093#ifdef DYNAMIC_LOG_ENABLED
94#include <log_xml_parser.h>
95#define LOG_MASK HAL_MOD_FILE_AUDIO_HW
96#include <log_utils.h>
97#endif
98
Krishna Kishor Jhaaf83fd82022-11-15 17:54:07 +053099#define SKIP_INPUT_SOURCE_PRIORITY
100
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700101#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +0530102/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
103#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700104#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700105#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Arun Mirpuri5d170872019-03-26 13:21:31 -0700106#define MMAP_PLAYBACK_VOLUME_MAX 0x2000
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530107#define PCM_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530108#define DSD_VOLUME_MIN_DB (-110)
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700109#define INVALID_OUT_VOLUME -1
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700110#define AUDIO_IO_PORTS_MAX 32
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700111
Zhou Songbaddf9f2020-11-20 13:57:39 +0800112#define PLAYBACK_GAIN_MAX 1.0f
Aalique Grahame22e49102018-12-18 14:23:57 -0800113#define RECORD_GAIN_MIN 0.0f
114#define RECORD_GAIN_MAX 1.0f
115#define RECORD_VOLUME_CTL_MAX 0x2000
116
117/* treat as unsigned Q1.13 */
118#define APP_TYPE_GAIN_DEFAULT 0x2000
119
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700120#define PROXY_OPEN_RETRY_COUNT 100
121#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800122
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800123#define GET_USECASE_AUDIO_PLAYBACK_PRIMARY(db) \
124 (db)? USECASE_AUDIO_PLAYBACK_DEEP_BUFFER : \
125 USECASE_AUDIO_PLAYBACK_LOW_LATENCY
126#define GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(db) \
127 (db)? pcm_config_deep_buffer : pcm_config_low_latency
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800128
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700129#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700130#define DEFAULT_VOIP_BUF_DURATION_MS 20
131#define DEFAULT_VOIP_BIT_DEPTH_BYTE sizeof(int16_t)
132#define DEFAULT_VOIP_SAMP_RATE 48000
133
134#define VOIP_IO_BUF_SIZE(SR, DURATION_MS, BIT_DEPTH) (SR)/1000 * DURATION_MS * BIT_DEPTH
135
136struct pcm_config default_pcm_config_voip_copp = {
137 .channels = 1,
138 .rate = DEFAULT_VOIP_SAMP_RATE, /* changed when the stream is opened */
139 .period_size = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
140 .period_count = 2,
141 .format = PCM_FORMAT_S16_LE,
kunleiz95b597a2017-10-23 17:07:33 +0800142 .avail_min = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
143 .stop_threshold = INT_MAX,
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700144};
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700145
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700146#define MIN_CHANNEL_COUNT 1
147#define DEFAULT_CHANNEL_COUNT 2
148#define MAX_HIFI_CHANNEL_COUNT 8
149
Aalique Grahame22e49102018-12-18 14:23:57 -0800150#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
151#define MAX_CHANNEL_COUNT 1
152#else
153#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
154#define XSTR(x) STR(x)
155#define STR(x) #x
156#endif
157
Avinash Chandrad7296d42021-08-04 15:07:47 +0530158#define IS_USB_HIFI (MAX_HIFI_CHANNEL_COUNT >= MAX_CHANNEL_COUNT) ? \
159 true : false
160
Dechen Chai22768452021-07-30 09:29:16 +0530161#ifdef LINUX_ENABLED
162static inline int64_t audio_utils_ns_from_timespec(const struct timespec *ts)
163{
164 return ts->tv_sec * 1000000000LL + ts->tv_nsec;
165}
166#endif
167
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700168static unsigned int configured_low_latency_capture_period_size =
169 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
170
Haynes Mathew George16081042017-05-31 17:16:49 -0700171#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
172#define MMAP_PERIOD_COUNT_MIN 32
173#define MMAP_PERIOD_COUNT_MAX 512
174#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
175
Aalique Grahame22e49102018-12-18 14:23:57 -0800176/* This constant enables extended precision handling.
177 * TODO The flag is off until more testing is done.
178 */
179static const bool k_enable_extended_precision = false;
Arun Mirpurie008ed22019-03-21 11:21:04 -0700180extern int AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Aalique Grahame22e49102018-12-18 14:23:57 -0800181
Eric Laurentb23d5282013-05-14 15:27:20 -0700182struct pcm_config pcm_config_deep_buffer = {
183 .channels = 2,
184 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
185 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
186 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
187 .format = PCM_FORMAT_S16_LE,
188 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
189 .stop_threshold = INT_MAX,
190 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
191};
192
193struct pcm_config pcm_config_low_latency = {
194 .channels = 2,
195 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
196 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
197 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
198 .format = PCM_FORMAT_S16_LE,
199 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
200 .stop_threshold = INT_MAX,
201 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
202};
203
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800204struct pcm_config pcm_config_haptics_audio = {
205 .channels = 1,
206 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
207 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
208 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
209 .format = PCM_FORMAT_S16_LE,
210 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
211 .stop_threshold = INT_MAX,
212 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
213};
214
215struct pcm_config pcm_config_haptics = {
216 .channels = 1,
217 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
218 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
219 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
220 .format = PCM_FORMAT_S16_LE,
221 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
222 .stop_threshold = INT_MAX,
223 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
224};
225
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700226static int af_period_multiplier = 4;
227struct pcm_config pcm_config_rt = {
228 .channels = 2,
229 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
230 .period_size = ULL_PERIOD_SIZE, //1 ms
231 .period_count = 512, //=> buffer size is 512ms
232 .format = PCM_FORMAT_S16_LE,
233 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
234 .stop_threshold = INT_MAX,
235 .silence_threshold = 0,
236 .silence_size = 0,
237 .avail_min = ULL_PERIOD_SIZE, //1 ms
238};
239
Eric Laurentb23d5282013-05-14 15:27:20 -0700240struct pcm_config pcm_config_hdmi_multi = {
241 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
242 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
243 .period_size = HDMI_MULTI_PERIOD_SIZE,
244 .period_count = HDMI_MULTI_PERIOD_COUNT,
245 .format = PCM_FORMAT_S16_LE,
246 .start_threshold = 0,
247 .stop_threshold = INT_MAX,
248 .avail_min = 0,
249};
250
Haynes Mathew George16081042017-05-31 17:16:49 -0700251struct pcm_config pcm_config_mmap_playback = {
252 .channels = 2,
253 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
254 .period_size = MMAP_PERIOD_SIZE,
255 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
256 .format = PCM_FORMAT_S16_LE,
257 .start_threshold = MMAP_PERIOD_SIZE*8,
258 .stop_threshold = INT32_MAX,
259 .silence_threshold = 0,
260 .silence_size = 0,
261 .avail_min = MMAP_PERIOD_SIZE, //1 ms
262};
263
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700264struct pcm_config pcm_config_hifi = {
265 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
266 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
267 .period_size = HIFI_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
268 .period_count = HIFI_BUFFER_OUTPUT_PERIOD_COUNT,
269 .format = PCM_FORMAT_S24_3LE,
270 .start_threshold = 0,
271 .stop_threshold = INT_MAX,
272 .avail_min = 0,
273};
274
Eric Laurentb23d5282013-05-14 15:27:20 -0700275struct pcm_config pcm_config_audio_capture = {
276 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700277 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
278 .format = PCM_FORMAT_S16_LE,
279};
280
Haynes Mathew George16081042017-05-31 17:16:49 -0700281struct pcm_config pcm_config_mmap_capture = {
282 .channels = 2,
283 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
284 .period_size = MMAP_PERIOD_SIZE,
285 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
286 .format = PCM_FORMAT_S16_LE,
287 .start_threshold = 0,
288 .stop_threshold = INT_MAX,
289 .silence_threshold = 0,
290 .silence_size = 0,
291 .avail_min = MMAP_PERIOD_SIZE, //1 ms
292};
293
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700294#define AFE_PROXY_CHANNEL_COUNT 2
295#define AFE_PROXY_SAMPLING_RATE 48000
296
297#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
298#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
299
300struct pcm_config pcm_config_afe_proxy_playback = {
301 .channels = AFE_PROXY_CHANNEL_COUNT,
302 .rate = AFE_PROXY_SAMPLING_RATE,
303 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
304 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
305 .format = PCM_FORMAT_S16_LE,
306 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
307 .stop_threshold = INT_MAX,
308 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
309};
310
311#define AFE_PROXY_RECORD_PERIOD_SIZE 768
312#define AFE_PROXY_RECORD_PERIOD_COUNT 4
313
Aalique Grahame22e49102018-12-18 14:23:57 -0800314struct pcm_config pcm_config_audio_capture_rt = {
315 .channels = 2,
316 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
317 .period_size = ULL_PERIOD_SIZE,
318 .period_count = 512,
319 .format = PCM_FORMAT_S16_LE,
320 .start_threshold = 0,
321 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
322 .silence_threshold = 0,
323 .silence_size = 0,
324 .avail_min = ULL_PERIOD_SIZE, //1 ms
325};
326
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +0530327struct pcm_config pcm_config_audio_capture_rt_48KHz = {
328 .channels = 2,
329 .rate = 48000,
330 .period_size = 48,
331 .period_count = 512,
332 .format = PCM_FORMAT_S16_LE,
333 .start_threshold = 0,
334 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
335 .silence_threshold = 0,
336 .silence_size = 0,
337 .avail_min = 48, //1 ms
338};
339struct pcm_config pcm_config_audio_capture_rt_32KHz = {
340 .channels = 2,
341 .rate = 32000,
342 .period_size = 32,
343 .period_count = 512,
344 .format = PCM_FORMAT_S16_LE,
345 .start_threshold = 0,
346 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
347 .silence_threshold = 0,
348 .silence_size = 0,
349 .avail_min = 32, //1 ms
350};
351struct pcm_config pcm_config_audio_capture_rt_24KHz = {
352 .channels = 2,
353 .rate = 24000,
354 .period_size = 24,
355 .period_count = 512,
356 .format = PCM_FORMAT_S16_LE,
357 .start_threshold = 0,
358 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
359 .silence_threshold = 0,
360 .silence_size = 0,
361 .avail_min = 24, //1 ms
362};
363struct pcm_config pcm_config_audio_capture_rt_16KHz = {
364 .channels = 2,
365 .rate = 16000,
366 .period_size = 16,
367 .period_count = 512,
368 .format = PCM_FORMAT_S16_LE,
369 .start_threshold = 0,
370 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
371 .silence_threshold = 0,
372 .silence_size = 0,
373 .avail_min = 16, //1 ms
374};
375struct pcm_config pcm_config_audio_capture_rt_8KHz = {
376 .channels = 2,
377 .rate = 8000,
378 .period_size = 8,
379 .period_count = 512,
380 .format = PCM_FORMAT_S16_LE,
381 .start_threshold = 0,
382 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
383 .silence_threshold = 0,
384 .silence_size = 0,
385 .avail_min = 8, //1 ms
386};
387
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700388struct pcm_config pcm_config_afe_proxy_record = {
389 .channels = AFE_PROXY_CHANNEL_COUNT,
390 .rate = AFE_PROXY_SAMPLING_RATE,
391 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
392 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
393 .format = PCM_FORMAT_S16_LE,
394 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
395 .stop_threshold = INT_MAX,
396 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
397};
398
Ashish Jainf1eaa582016-05-23 20:54:24 +0530399#define AUDIO_MAX_PCM_FORMATS 7
400
401const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
402 [AUDIO_FORMAT_DEFAULT] = 0,
403 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
404 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
405 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
406 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
407 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
408 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
409};
410
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800411const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700412 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
413 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800414 [USECASE_AUDIO_PLAYBACK_WITH_HAPTICS] = "audio-with-haptics-playback",
Meng Wang51d8c2a2020-04-27 15:23:21 +0800415 [USECASE_AUDIO_PLAYBACK_HAPTICS] = "haptics-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700416 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
417 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700418 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700419 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700420 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
421 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
422 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
423 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
424 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
425 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
426 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
427 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
Haynes Mathew George16081042017-05-31 17:16:49 -0700428 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
429 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700430 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Aalique Grahame22e49102018-12-18 14:23:57 -0800431 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
vivek mehta0ea887a2015-08-26 14:01:20 -0700432
Eric Laurentb23d5282013-05-14 15:27:20 -0700433 [USECASE_AUDIO_RECORD] = "audio-record",
Krishna Kishor Jha0f4d8482022-02-18 10:56:05 +0530434 [USECASE_AUDIO_RECORD2] = "audio-record2",
435 [USECASE_AUDIO_RECORD3] = "audio-record3",
Mingming Yine62d7842013-10-25 16:26:03 -0700436 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530437 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
438 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
439 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Dhananjay Kumar376e38b2017-09-28 22:26:23 +0530440 [USECASE_AUDIO_RECORD_COMPRESS5] = "audio-record-compress5",
441 [USECASE_AUDIO_RECORD_COMPRESS6] = "audio-record-compress6",
Eric Laurentb23d5282013-05-14 15:27:20 -0700442 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Kogara Naveen Kumarc5758232022-11-07 20:25:40 +0530443 [USECASE_AUDIO_RECORD_LOW_LATENCY2] = "low-latency-record2",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700444 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700445 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700446 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700447
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800448 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800449 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Derek Chenf7092792017-05-23 12:23:53 -0400450 [USECASE_AUDIO_HFP_SCO_DOWNLINK] = "hfp-sco-downlink",
451 [USECASE_AUDIO_HFP_SCO_WB_DOWNLINK] = "hfp-sco-wb-downlink",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700452
Derek Chenf7092792017-05-23 12:23:53 -0400453 [USECASE_VOICE_CALL] = "voice-call",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700454 [USECASE_VOICE2_CALL] = "voice2-call",
455 [USECASE_VOLTE_CALL] = "volte-call",
456 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800457 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800458 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
459 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800460 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700461 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
462 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
463 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800464 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
465 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
466 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
467
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700468 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
469 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700470 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
471 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700472
473 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
474 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Zhou Song62ea0282020-03-22 19:53:01 +0800475 [USECASE_AUDIO_RECORD_AFE_PROXY2] = "afe-proxy-record2",
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +0530476 [USECASE_AUDIO_PLAYBACK_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700477
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530478 /* Transcode loopback cases */
Surendar Karka93cd25a2018-08-28 14:21:37 +0530479 [USECASE_AUDIO_TRANSCODE_LOOPBACK_RX] = "audio-transcode-loopback-rx",
480 [USECASE_AUDIO_TRANSCODE_LOOPBACK_TX] = "audio-transcode-loopback-tx",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700481
482 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
483 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Revathi Uddarajud9f23d92020-07-27 10:55:06 +0530484 [USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY] = "audio-record-voip-low-latency",
Varun Balaraje49253e2017-07-06 19:48:56 +0530485 /* For Interactive Audio Streams */
486 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
487 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
488 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
489 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
490 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
491 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
492 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
493 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700494
Aniket Kumar Lata7fd86e12018-02-20 19:26:10 -0800495 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture",
496
Derek Chenf6318be2017-06-12 17:16:24 -0400497 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
498
499 [USECASE_AUDIO_PLAYBACK_MEDIA] = "media-playback",
Kogara Naveen Kumarc5758232022-11-07 20:25:40 +0530500 [USECASE_AUDIO_PLAYBACK_MEDIA_LL] = "media-playback-ll",
Derek Chenf6318be2017-06-12 17:16:24 -0400501 [USECASE_AUDIO_PLAYBACK_SYS_NOTIFICATION] = "sys-notification-playback",
502 [USECASE_AUDIO_PLAYBACK_NAV_GUIDANCE] = "nav-guidance-playback",
Kogara Naveen Kumarc5758232022-11-07 20:25:40 +0530503 [USECASE_AUDIO_PLAYBACK_NAV_GUIDANCE_LL] = "nav-guidance-playback-ll",
Derek Chenf6318be2017-06-12 17:16:24 -0400504 [USECASE_AUDIO_PLAYBACK_PHONE] = "phone-playback",
Kogara Naveen Kumar65828fe2022-10-14 16:41:04 +0530505 [USECASE_AUDIO_PLAYBACK_PHONE_LL] = "phone-playback-ll",
Susan Wang117cf6f2022-04-06 20:11:46 -0400506 [USECASE_AUDIO_PLAYBACK_ALERTS] = "alerts-playback",
Kogara Naveen Kumarc5758232022-11-07 20:25:40 +0530507 [USECASE_AUDIO_PLAYBACK_ALERTS_LL] = "alerts-playback-ll",
Derek Chen1bcdc6b2020-02-06 22:44:53 -0800508 [USECASE_AUDIO_PLAYBACK_FRONT_PASSENGER] = "front-passenger-playback",
Derek Chendf05eea2019-08-01 13:57:49 -0700509 [USECASE_AUDIO_PLAYBACK_REAR_SEAT] = "rear-seat-playback",
Rahul Sharma99770982019-03-06 17:05:26 +0530510 [USECASE_AUDIO_FM_TUNER_EXT] = "fm-tuner-ext",
Derek Chena30a5f42019-12-03 11:17:09 -0500511 [USECASE_ICC_CALL] = "icc-call",
Huicheng Liu1404ba12020-09-11 01:03:25 -0400512
513 [USECASE_AUDIO_RECORD_BUS] = "audio-record",
514 [USECASE_AUDIO_RECORD_BUS_FRONT_PASSENGER] = "front-passenger-record",
515 [USECASE_AUDIO_RECORD_BUS_REAR_SEAT] = "rear-seat-record",
Fei Tongaffdf732020-02-20 20:39:05 +0800516 [USECASE_AUDIO_PLAYBACK_SYNTHESIZER] = "synth-loopback",
Susan Wange3959562021-03-11 11:50:26 -0500517 [USECASE_AUDIO_RECORD_ECHO_REF_EXT] = "echo-reference-external",
Eric Laurentb23d5282013-05-14 15:27:20 -0700518};
519
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700520static const audio_usecase_t offload_usecases[] = {
521 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700522 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
523 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
524 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
525 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
526 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
527 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
528 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
529 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700530};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800531
Varun Balaraje49253e2017-07-06 19:48:56 +0530532static const audio_usecase_t interactive_usecases[] = {
533 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
534 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
535 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
536 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
537 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
538 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
539 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
540 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
541};
542
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800543#define STRING_TO_ENUM(string) { #string, string }
544
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800545struct string_to_enum {
546 const char *name;
547 uint32_t value;
548};
549
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700550static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800551 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800552 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
553 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
554 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700555 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800556 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
557 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800558 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700559 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
560 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
561 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
562 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
563 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
564 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
565 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
566 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
567 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
568 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
569 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800570};
571
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700572static const struct string_to_enum formats_name_to_enum_table[] = {
573 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
574 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
575 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700576 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
577 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
578 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700579 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800580 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
581 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700582 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800583};
584
585//list of all supported sample rates by HDMI specification.
586static const int out_hdmi_sample_rates[] = {
587 32000, 44100, 48000, 88200, 96000, 176400, 192000,
588};
589
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700590static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800591 STRING_TO_ENUM(32000),
592 STRING_TO_ENUM(44100),
593 STRING_TO_ENUM(48000),
594 STRING_TO_ENUM(88200),
595 STRING_TO_ENUM(96000),
596 STRING_TO_ENUM(176400),
597 STRING_TO_ENUM(192000),
Mingshu pange8aedf12019-10-25 15:38:27 +0800598 STRING_TO_ENUM(352800),
599 STRING_TO_ENUM(384000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700600};
601
Carter Hsu2e429db2019-05-14 18:50:52 +0800602struct in_effect_list {
603 struct listnode list;
604 effect_handle_t handle;
605};
606
Krishna Kishor Jha0f4d8482022-02-18 10:56:05 +0530607static const audio_usecase_t record_usecases[] = {
608 USECASE_AUDIO_RECORD,
609 USECASE_AUDIO_RECORD2,
610 USECASE_AUDIO_RECORD3,
611};
612
Kogara Naveen Kumarc5758232022-11-07 20:25:40 +0530613static const audio_usecase_t low_latency_record_usecases[] = {
614 USECASE_AUDIO_RECORD_LOW_LATENCY,
615 USECASE_AUDIO_RECORD_LOW_LATENCY2,
616};
617
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700618static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700619static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700620static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700621//cache last MBDRC cal step level
622static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700623
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530624static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Arun Mirpuri5d170872019-03-26 13:21:31 -0700625static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800626static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530627static int out_set_pcm_volume(struct audio_stream_out *stream, float left, float right);
Krishna Kishor Jha10ad39f2022-02-21 17:02:47 +0530628#ifdef SOFT_VOLUME
629static int out_set_soft_volume_params(struct audio_stream_out *stream);
630#endif
Derek Chen6f293672019-04-01 01:40:24 -0700631static void adev_snd_mon_cb(void *cookie, struct str_parms *parms);
632static void in_snd_mon_cb(void * stream, struct str_parms * parms);
633static void out_snd_mon_cb(void * stream, struct str_parms * parms);
634
Zhou Song331c8e52019-08-26 14:16:12 +0800635static int configure_btsco_sample_rate(snd_device_t snd_device);
636
Vatsal Buchac09ae062018-11-14 13:25:08 +0530637#ifdef AUDIO_FEATURE_ENABLED_GCOV
638extern void __gcov_flush();
639static void enable_gcov()
640{
641 __gcov_flush();
642}
643#else
644static void enable_gcov()
645{
646}
647#endif
648
justinweng20fb6d82019-02-21 18:49:00 -0700649static int in_set_microphone_direction(const struct audio_stream_in *stream,
650 audio_microphone_direction_t dir);
651static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom);
652
Krishna Kishor Jha0f4d8482022-02-18 10:56:05 +0530653static bool is_pcm_record_usecase(audio_usecase_t uc_id)
654{
655 unsigned int record_uc_index;
656 unsigned int num_usecase = sizeof(record_usecases)/sizeof(record_usecases[0]);
657
658 for (record_uc_index = 0; record_uc_index < num_usecase; record_uc_index++) {
659 if (uc_id == record_usecases[record_uc_index])
660 return true;
661 }
662 return false;
663}
664
665static audio_usecase_t get_record_usecase(struct audio_device *adev)
666{
667 audio_usecase_t ret_uc = USECASE_INVALID;
668 unsigned int record_uc_index;
669 unsigned int num_usecase = sizeof(record_usecases)/sizeof(record_usecases[0]);
670
671 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
672 for (record_uc_index = 0; record_uc_index < num_usecase; record_uc_index++) {
673 if (!(adev->pcm_record_uc_state & (0x1 << record_uc_index))) {
674 adev->pcm_record_uc_state |= 0x1 << record_uc_index;
675 ret_uc = record_usecases[record_uc_index];
676 break;
677 }
678 }
679
680 ALOGV("%s: pcm record usecase is %d", __func__, ret_uc);
681 return ret_uc;
682}
683
684static void free_record_usecase(struct audio_device *adev,
685 audio_usecase_t uc_id)
686{
687 unsigned int record_uc_index;
688 unsigned int num_usecase = sizeof(record_usecases)/sizeof(record_usecases[0]);
689
690 for (record_uc_index = 0; record_uc_index < num_usecase; record_uc_index++) {
691 if (record_usecases[record_uc_index] == uc_id) {
692 adev->pcm_record_uc_state &= ~(0x1 << record_uc_index);
693 break;
694 }
695 }
696 ALOGV("%s: free pcm record usecase %d", __func__, uc_id);
697}
698
Kogara Naveen Kumarc5758232022-11-07 20:25:40 +0530699static bool is_pcm_low_latency_record_usecase(audio_usecase_t uc_id)
700{
701 unsigned int record_uc_index;
702 unsigned int num_usecase = sizeof(low_latency_record_usecases)/sizeof(low_latency_record_usecases[0]);
703 ALOGD("%s: Check low latency pcm record usecase", __func__);
704
705 for (record_uc_index = 0; record_uc_index < num_usecase; record_uc_index++) {
706 if (uc_id == low_latency_record_usecases[record_uc_index])
707 return true;
708 }
709 return false;
710}
711
712static audio_usecase_t get_low_latency_record_usecase(struct audio_device *adev)
713{
714 audio_usecase_t ret_uc = USECASE_INVALID;
715 unsigned int record_uc_index;
716 unsigned int num_usecase = sizeof(low_latency_record_usecases)/sizeof(low_latency_record_usecases[0]);
717
718 ALOGD("%s: get_low_latency_record_usecase: %d", __func__, num_usecase);
719 for (record_uc_index = 0; record_uc_index < num_usecase; record_uc_index++) {
720 if (!(adev->pcm_low_latency_record_uc_state & (0x1 << record_uc_index))) {
721 adev->pcm_low_latency_record_uc_state |= 0x1 << record_uc_index;
722 ALOGD("%s: get_low_latency_record_usecase: %d", __func__, record_uc_index);
723 ret_uc = low_latency_record_usecases[record_uc_index];
724 break;
725 }
726 }
727
728 ALOGD("%s: low latency pcm record usecase is %d", __func__, ret_uc);
729 return ret_uc;
730}
731
732static void free_low_latency_record_usecase(struct audio_device *adev,
733 audio_usecase_t uc_id)
734{
735 unsigned int record_uc_index;
736 unsigned int num_usecase = sizeof(low_latency_record_usecases)/sizeof(low_latency_record_usecases[0]);
737
738 for (record_uc_index = 0; record_uc_index < num_usecase; record_uc_index++) {
739 if (low_latency_record_usecases[record_uc_index] == uc_id) {
740 adev->pcm_low_latency_record_uc_state &= ~(0x1 << record_uc_index);
741 break;
742 }
743 }
744 ALOGD("%s: free low latency pcm record usecase %d", __func__, uc_id);
745}
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700746static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
747 int flags __unused)
748{
749 int dir = 0;
750 switch (uc_id) {
751 case USECASE_AUDIO_RECORD_LOW_LATENCY:
Revathi Uddarajud9f23d92020-07-27 10:55:06 +0530752 case USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY:
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700753 dir = 1;
754 case USECASE_AUDIO_PLAYBACK_ULL:
755 break;
756 default:
757 return false;
758 }
759
760 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
761 PCM_PLAYBACK : PCM_CAPTURE);
762 if (adev->adm_is_noirq_avail)
763 return adev->adm_is_noirq_avail(adev->adm_data,
764 adev->snd_card, dev_id, dir);
765 return false;
766}
767
768static void register_out_stream(struct stream_out *out)
769{
770 struct audio_device *adev = out->dev;
771 if (is_offload_usecase(out->usecase) ||
772 !adev->adm_register_output_stream)
773 return;
774
775 // register stream first for backward compatibility
776 adev->adm_register_output_stream(adev->adm_data,
777 out->handle,
778 out->flags);
779
780 if (!adev->adm_set_config)
781 return;
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +0530782#ifdef PLATFORM_AUTO
Kogara Naveen Kumar6db5fb02022-05-07 00:22:50 +0530783 if (out->realtime || (out->flags & AUDIO_OUTPUT_FLAG_SYS_NOTIFICATION))
784 adev->adm_set_config(adev->adm_data,
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700785 out->handle,
786 out->pcm, &out->config);
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +0530787#else
788 if (out->realtime)
789 adev->adm_set_config(adev->adm_data,
790 out->handle,
791 out->pcm, &out->config);
792#endif
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700793}
794
795static void register_in_stream(struct stream_in *in)
796{
797 struct audio_device *adev = in->dev;
798 if (!adev->adm_register_input_stream)
799 return;
800
801 adev->adm_register_input_stream(adev->adm_data,
802 in->capture_handle,
803 in->flags);
804
805 if (!adev->adm_set_config)
806 return;
807
808 if (in->realtime)
809 adev->adm_set_config(adev->adm_data,
810 in->capture_handle,
811 in->pcm,
812 &in->config);
813}
814
815static void request_out_focus(struct stream_out *out, long ns)
816{
817 struct audio_device *adev = out->dev;
818
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700819 if (adev->adm_request_focus_v2)
820 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
821 else if (adev->adm_request_focus)
822 adev->adm_request_focus(adev->adm_data, out->handle);
823}
824
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700825static int request_in_focus(struct stream_in *in, long ns)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700826{
827 struct audio_device *adev = in->dev;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700828 int ret = 0;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700829
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700830 if (adev->adm_request_focus_v2_1)
831 ret = adev->adm_request_focus_v2_1(adev->adm_data, in->capture_handle, ns);
832 else if (adev->adm_request_focus_v2)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700833 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
834 else if (adev->adm_request_focus)
835 adev->adm_request_focus(adev->adm_data, in->capture_handle);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700836
837 return ret;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700838}
839
840static void release_out_focus(struct stream_out *out)
841{
842 struct audio_device *adev = out->dev;
843
844 if (adev->adm_abandon_focus)
845 adev->adm_abandon_focus(adev->adm_data, out->handle);
846}
847
848static void release_in_focus(struct stream_in *in)
849{
850 struct audio_device *adev = in->dev;
851 if (adev->adm_abandon_focus)
852 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
853}
854
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530855static int parse_snd_card_status(struct str_parms *parms, int *card,
856 card_status_t *status)
857{
858 char value[32]={0};
859 char state[32]={0};
860
861 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
862 if (ret < 0)
863 return -1;
864
865 // sscanf should be okay as value is of max length 32.
866 // same as sizeof state.
867 if (sscanf(value, "%d,%s", card, state) < 2)
868 return -1;
869
870 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
871 CARD_STATUS_OFFLINE;
872 return 0;
873}
874
Avinash Chandrad7296d42021-08-04 15:07:47 +0530875bool is_combo_audio_input_device(struct listnode *devices){
876
Sandhya Mutha Naga Venkata153d95e2022-07-12 14:54:43 +0530877 if ((devices == NULL) || (!list_empty(devices)))
Avinash Chandrad7296d42021-08-04 15:07:47 +0530878 return false;
879
880 if(compare_device_type(devices, AUDIO_DEVICE_IN_BUILTIN_MIC|AUDIO_DEVICE_IN_SPEAKER_MIC2))
881 return true;
882 else
883 return false;
884}
885
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700886static inline void adjust_frames_for_device_delay(struct stream_out *out,
887 uint32_t *dsp_frames) {
888 // Adjustment accounts for A2dp encoder latency with offload usecases
889 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -0800890 if (is_a2dp_out_device_type(&out->device_list)) {
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700891 unsigned long offset =
892 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
893 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
894 }
895}
896
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700897static inline bool free_entry(void *key __unused,
898 void *value, void *context __unused)
899{
900 free(value);
901 return true;
902}
903
904static inline void free_map(Hashmap *map)
905{
906 if (map) {
907 hashmapForEach(map, free_entry, (void *) NULL);
908 hashmapFree(map);
909 }
910}
911
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800912static inline void patch_map_remove_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700913 audio_patch_handle_t patch_handle)
914{
915 if (patch_handle == AUDIO_PATCH_HANDLE_NONE)
916 return;
917
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700918 struct audio_patch_info *p_info =
919 hashmapGet(adev->patch_map, (void *) (intptr_t) patch_handle);
920 if (p_info) {
921 ALOGV("%s: Remove patch %d", __func__, patch_handle);
922 hashmapRemove(adev->patch_map, (void *) (intptr_t) patch_handle);
923 free(p_info->patch);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700924 free(p_info);
925 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700926}
927
928static inline int io_streams_map_insert(struct audio_device *adev,
929 struct audio_stream *stream,
930 audio_io_handle_t handle,
931 audio_patch_handle_t patch_handle)
932{
933 struct audio_stream_info *s_info =
934 (struct audio_stream_info *) calloc(1, sizeof(struct audio_stream_info));
935
936 if (s_info == NULL) {
937 ALOGE("%s: Could not allocate stream info", __func__);
938 return -ENOMEM;
939 }
940 s_info->stream = stream;
941 s_info->patch_handle = patch_handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700942
943 pthread_mutex_lock(&adev->lock);
944 struct audio_stream_info *stream_info =
945 hashmapPut(adev->io_streams_map, (void *) (intptr_t) handle, (void *) s_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700946 if (stream_info != NULL)
947 free(stream_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800948 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Latad13758f2020-08-06 15:11:36 -0700949 ALOGV("%s: Added stream in io_streams_map with handle %d", __func__, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700950 return 0;
951}
952
953static inline void io_streams_map_remove(struct audio_device *adev,
954 audio_io_handle_t handle)
955{
956 pthread_mutex_lock(&adev->lock);
957 struct audio_stream_info *s_info =
958 hashmapRemove(adev->io_streams_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700959 if (s_info == NULL)
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800960 goto done;
Aniket Kumar Latad13758f2020-08-06 15:11:36 -0700961 ALOGV("%s: Removed stream with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800962 patch_map_remove_l(adev, s_info->patch_handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700963 free(s_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800964done:
965 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700966 return;
967}
968
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800969static struct audio_patch_info* fetch_patch_info_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700970 audio_patch_handle_t handle)
971{
972 struct audio_patch_info *p_info = NULL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700973 p_info = (struct audio_patch_info *)
974 hashmapGet(adev->patch_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700975 return p_info;
976}
977
vivek mehtaa76401a2015-04-24 14:12:15 -0700978__attribute__ ((visibility ("default")))
979bool audio_hw_send_gain_dep_calibration(int level) {
980 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700981 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700982
983 pthread_mutex_lock(&adev_init_lock);
984
985 if (adev != NULL && adev->platform != NULL) {
986 pthread_mutex_lock(&adev->lock);
987 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700988
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530989 // cache level info for any of the use case which
990 // was not started.
991 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700992
vivek mehtaa76401a2015-04-24 14:12:15 -0700993 pthread_mutex_unlock(&adev->lock);
994 } else {
995 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
996 }
997
998 pthread_mutex_unlock(&adev_init_lock);
999
1000 return ret_val;
1001}
1002
Ashish Jain5106d362016-05-11 19:23:33 +05301003static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
1004{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08001005 bool gapless_enabled = false;
1006 const char *mixer_ctl_name = "Compress Gapless Playback";
1007 struct mixer_ctl *ctl;
1008
1009 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07001010 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +05301011
1012 /*Disable gapless if its AV playback*/
1013 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08001014
1015 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1016 if (!ctl) {
1017 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1018 __func__, mixer_ctl_name);
1019 return -EINVAL;
1020 }
1021
1022 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
1023 ALOGE("%s: Could not set gapless mode %d",
1024 __func__, gapless_enabled);
1025 return -EINVAL;
1026 }
1027 return 0;
1028}
Haynes Mathew George5191a852013-09-11 14:19:36 -07001029
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -07001030__attribute__ ((visibility ("default")))
1031int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
1032 int table_size) {
1033 int ret_val = 0;
1034 ALOGV("%s: enter ... ", __func__);
1035
1036 pthread_mutex_lock(&adev_init_lock);
1037 if (adev == NULL) {
1038 ALOGW("%s: adev is NULL .... ", __func__);
1039 goto done;
1040 }
1041
1042 pthread_mutex_lock(&adev->lock);
1043 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
1044 pthread_mutex_unlock(&adev->lock);
1045done:
1046 pthread_mutex_unlock(&adev_init_lock);
1047 ALOGV("%s: exit ... ", __func__);
1048 return ret_val;
1049}
1050
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001051bool audio_hw_send_qdsp_parameter(int stream_type, float vol, bool active)
Aalique Grahame22e49102018-12-18 14:23:57 -08001052{
1053 bool ret = false;
1054 ALOGV("%s: enter ...", __func__);
1055
1056 pthread_mutex_lock(&adev_init_lock);
1057
1058 if (adev != NULL && adev->platform != NULL) {
1059 pthread_mutex_lock(&adev->lock);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001060 ret = audio_extn_qdsp_set_state(adev, stream_type, vol, active);
Aalique Grahame22e49102018-12-18 14:23:57 -08001061 pthread_mutex_unlock(&adev->lock);
1062 }
1063
1064 pthread_mutex_unlock(&adev_init_lock);
1065
1066 ALOGV("%s: exit with ret %d", __func__, ret);
1067 return ret;
1068}
Aalique Grahame22e49102018-12-18 14:23:57 -08001069
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001070static bool is_supported_format(audio_format_t format)
1071{
Eric Laurent86e17132013-09-12 17:49:30 -07001072 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +05301073 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +05301074 format == AUDIO_FORMAT_AAC_LC ||
1075 format == AUDIO_FORMAT_AAC_HE_V1 ||
1076 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +05301077 format == AUDIO_FORMAT_AAC_ADTS_LC ||
1078 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
1079 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05301080 format == AUDIO_FORMAT_AAC_LATM_LC ||
1081 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
1082 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +05301083 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
1084 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +05301085 format == AUDIO_FORMAT_PCM_FLOAT ||
1086 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -07001087 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301088 format == AUDIO_FORMAT_AC3 ||
1089 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -07001090 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301091 format == AUDIO_FORMAT_DTS ||
1092 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001093 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301094 format == AUDIO_FORMAT_ALAC ||
1095 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301096 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301097 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001098 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05301099 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07001100 format == AUDIO_FORMAT_APTX ||
1101 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08001102 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001103
1104 return false;
1105}
1106
Kunlei Zhang67cc7072020-12-18 17:16:49 +08001107static bool is_supported_conc_usecase_for_power_mode_call(struct audio_device *adev)
1108{
1109 struct listnode *node;
1110 struct audio_usecase *usecase;
1111
1112 list_for_each(node, &adev->usecase_list) {
1113 usecase = node_to_item(node, struct audio_usecase, list);
1114 if (usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1115 ALOGD("%s: FM usecase is active, not setting power mode", __func__);
1116 return false;
1117 }
1118 }
1119
1120 return true;
1121}
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001122static inline bool is_mmap_usecase(audio_usecase_t uc_id)
1123{
1124 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
Zhou Song62ea0282020-03-22 19:53:01 +08001125 (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY2) ||
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001126 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
1127}
1128
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07001129static inline bool is_valid_volume(float left, float right)
1130{
1131 return ((left >= 0.0f && right >= 0.0f) ? true : false);
1132}
1133
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301134static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301135{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301136 ALOGV("%s", __func__);
1137 audio_route_apply_and_update_path(adev->audio_route,
1138 "asrc-mode");
1139 adev->asrc_mode_enabled = true;
1140}
1141
1142static void disable_asrc_mode(struct audio_device *adev)
1143{
1144 ALOGV("%s", __func__);
1145 audio_route_reset_and_update_path(adev->audio_route,
1146 "asrc-mode");
1147 adev->asrc_mode_enabled = false;
1148}
1149
Saurav Kumarc1411662020-10-14 10:50:45 +05301150static void check_and_configure_headphone(struct audio_device *adev,
1151 struct audio_usecase *uc_info,
1152 snd_device_t snd_device)
1153{
1154 struct listnode *node;
1155 struct audio_usecase *usecase;
1156 int new_backend_idx, usecase_backend_idx;
1157 bool spkr_hph_single_be_native_concurrency;
1158
1159 new_backend_idx = platform_get_backend_index(snd_device);
1160 spkr_hph_single_be_native_concurrency = platform_get_spkr_hph_single_be_native_concurrency_flag();
Zhou Songd4b18c42021-01-14 15:15:29 +08001161 if ((spkr_hph_single_be_native_concurrency && (new_backend_idx == DEFAULT_CODEC_BACKEND)) ||
1162 uc_info->id == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
Saurav Kumarc1411662020-10-14 10:50:45 +05301163 list_for_each(node, &adev->usecase_list) {
1164 usecase = node_to_item(node, struct audio_usecase, list);
1165 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
1166 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
1167 if (((usecase_backend_idx == HEADPHONE_BACKEND) ||
1168 (usecase_backend_idx == HEADPHONE_44_1_BACKEND)) &&
1169 ((usecase->stream.out->sample_rate % OUTPUT_SAMPLING_RATE_44100) == 0)) {
1170 disable_audio_route(adev, usecase);
1171 disable_snd_device(adev, usecase->out_snd_device);
1172 usecase->stream.out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Saurav Kumar70902382020-10-28 11:16:04 +05301173 platform_check_and_set_codec_backend_cfg(adev, usecase,
1174 usecase->out_snd_device);
Saurav Kumarc1411662020-10-14 10:50:45 +05301175 enable_snd_device(adev, usecase->out_snd_device);
Zhou Songd4b18c42021-01-14 15:15:29 +08001176 enable_audio_route(adev, usecase);
Saurav Kumarc1411662020-10-14 10:50:45 +05301177 }
1178 }
Revathi Uddaraju2c0eac02021-07-27 02:06:42 -07001179 else if ((usecase->type != PCM_CAPTURE) && (usecase == uc_info)) {
1180 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
1181 if (((usecase_backend_idx == HEADPHONE_BACKEND) ||
1182 (usecase_backend_idx == HEADPHONE_44_1_BACKEND)) &&
1183 ((usecase->stream.out->sample_rate % OUTPUT_SAMPLING_RATE_44100) == 0)) {
1184 usecase->stream.out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1185 platform_check_and_set_codec_backend_cfg(adev, usecase,
1186 usecase->out_snd_device);
1187 }
1188 }
Saurav Kumarc1411662020-10-14 10:50:45 +05301189 }
1190 }
1191}
1192
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301193/*
1194 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
1195 * 44.1 or Native DSD backends are enabled for any of current use case.
1196 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
1197 * - Disable current mix path use case(Headphone backend) and re-enable it with
1198 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
1199 * e.g. Naitve DSD or Headphone 44.1 -> + 48
1200 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301201static void check_and_set_asrc_mode(struct audio_device *adev,
1202 struct audio_usecase *uc_info,
1203 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301204{
1205 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301206 int i, num_new_devices = 0;
1207 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
1208 /*
1209 *Split snd device for new combo use case
1210 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
1211 */
1212 if (platform_split_snd_device(adev->platform,
1213 snd_device,
1214 &num_new_devices,
1215 split_new_snd_devices) == 0) {
1216 for (i = 0; i < num_new_devices; i++)
1217 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
1218 } else {
1219 int new_backend_idx = platform_get_backend_index(snd_device);
1220 if (((new_backend_idx == HEADPHONE_BACKEND) ||
1221 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
1222 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
1223 !adev->asrc_mode_enabled) {
1224 struct listnode *node = NULL;
1225 struct audio_usecase *uc = NULL;
1226 struct stream_out *curr_out = NULL;
1227 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
1228 int i, num_devices, ret = 0;
1229 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301230
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301231 list_for_each(node, &adev->usecase_list) {
1232 uc = node_to_item(node, struct audio_usecase, list);
1233 curr_out = (struct stream_out*) uc->stream.out;
1234 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
1235 /*
1236 *Split snd device for existing combo use case
1237 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
1238 */
1239 ret = platform_split_snd_device(adev->platform,
1240 uc->out_snd_device,
1241 &num_devices,
1242 split_snd_devices);
1243 if (ret < 0 || num_devices == 0) {
1244 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
1245 split_snd_devices[0] = uc->out_snd_device;
1246 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -08001247 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301248 for (i = 0; i < num_devices; i++) {
1249 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
1250 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
1251 if((new_backend_idx == HEADPHONE_BACKEND) &&
1252 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
1253 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07001254 ALOGV("%s:DSD or native stream detected enabling asrcmode in hardware",
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301255 __func__);
1256 enable_asrc_mode(adev);
1257 break;
1258 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
1259 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
1260 (usecase_backend_idx == HEADPHONE_BACKEND)) {
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07001261 ALOGV("%s: 48K stream detected, disabling and enabling it \
1262 with asrcmode in hardware", __func__);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301263 disable_audio_route(adev, uc);
1264 disable_snd_device(adev, uc->out_snd_device);
1265 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
1266 if (new_backend_idx == DSD_NATIVE_BACKEND)
1267 audio_route_apply_and_update_path(adev->audio_route,
1268 "hph-true-highquality-mode");
1269 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
1270 (curr_out->bit_width >= 24))
1271 audio_route_apply_and_update_path(adev->audio_route,
1272 "hph-highquality-mode");
1273 enable_asrc_mode(adev);
1274 enable_snd_device(adev, uc->out_snd_device);
1275 enable_audio_route(adev, uc);
1276 break;
1277 }
1278 }
1279 // reset split devices count
1280 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -08001281 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301282 if (adev->asrc_mode_enabled)
1283 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301284 }
1285 }
1286 }
1287}
1288
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001289static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
1290 struct audio_effect_config effect_config,
1291 unsigned int param_value)
1292{
1293 char mixer_ctl_name[] = "Audio Effect";
1294 struct mixer_ctl *ctl;
1295 long set_values[6];
Eric Laurent637e2d42018-11-15 12:24:31 -08001296 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001297
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001298 if (in == NULL) {
1299 ALOGE("%s: active input stream is NULL", __func__);
1300 return -EINVAL;
1301 }
1302
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001303 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1304 if (!ctl) {
1305 ALOGE("%s: Could not get mixer ctl - %s",
1306 __func__, mixer_ctl_name);
1307 return -EINVAL;
1308 }
1309
1310 set_values[0] = 1; //0:Rx 1:Tx
1311 set_values[1] = in->app_type_cfg.app_type;
1312 set_values[2] = (long)effect_config.module_id;
1313 set_values[3] = (long)effect_config.instance_id;
1314 set_values[4] = (long)effect_config.param_id;
1315 set_values[5] = param_value;
1316
1317 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
1318
1319 return 0;
1320
1321}
1322
1323static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
1324 int effect_type, unsigned int *param_value)
1325{
1326 int ret = 0;
1327 struct audio_effect_config other_effect_config;
1328 struct audio_usecase *usecase = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08001329 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001330
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001331 if (in == NULL) {
1332 ALOGE("%s: active input stream is NULL", __func__);
1333 return -EINVAL;
1334 }
1335
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001336 usecase = get_usecase_from_list(adev, in->usecase);
1337 if (!usecase)
1338 return -EINVAL;
1339
1340 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
1341 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
1342 if (ret < 0) {
1343 ALOGE("%s Failed to get effect params %d", __func__, ret);
1344 return ret;
1345 }
1346
1347 if (module_id == other_effect_config.module_id) {
1348 //Same module id for AEC/NS. Values need to be combined
1349 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
1350 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
1351 *param_value |= other_effect_config.param_value;
1352 }
1353 }
1354
1355 return ret;
1356}
1357
1358static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
Gangadhar Sb0210342019-02-22 17:39:41 +05301359{
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001360 struct audio_effect_config effect_config;
1361 struct audio_usecase *usecase = NULL;
1362 int ret = 0;
1363 unsigned int param_value = 0;
Eric Laurent637e2d42018-11-15 12:24:31 -08001364 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001365
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001366 if(!voice_extn_is_dynamic_ecns_enabled())
1367 return ENOSYS;
1368
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001369 if (!in) {
1370 ALOGE("%s: Invalid input stream", __func__);
1371 return -EINVAL;
1372 }
1373
1374 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
1375
1376 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +08001377 if (usecase == NULL) {
1378 ALOGE("%s: Could not find the usecase (%d) in the list",
1379 __func__, in->usecase);
1380 return -EINVAL;
1381 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001382
1383 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
1384 if (ret < 0) {
1385 ALOGE("%s Failed to get module id %d", __func__, ret);
1386 return ret;
1387 }
1388 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
1389 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
1390
1391 if(enable)
1392 param_value = effect_config.param_value;
1393
1394 /*Special handling for AEC & NS effects Param values need to be
1395 updated if module ids are same*/
1396
1397 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
1398 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
1399 if (ret < 0)
1400 return ret;
1401 }
1402
1403 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
1404
1405 return ret;
1406}
1407
1408static void check_and_enable_effect(struct audio_device *adev)
1409{
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001410 if(!voice_extn_is_dynamic_ecns_enabled())
1411 return;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001412
Eric Laurent637e2d42018-11-15 12:24:31 -08001413 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001414
Eric Laurent637e2d42018-11-15 12:24:31 -08001415 if (in != NULL && !in->standby) {
1416 if (in->enable_aec)
1417 enable_disable_effect(adev, EFFECT_AEC, true);
1418
1419 if (in->enable_ns &&
1420 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1421 enable_disable_effect(adev, EFFECT_NS, true);
1422 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001423 }
1424}
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001425
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001426int pcm_ioctl(struct pcm *pcm, int request, ...)
1427{
1428 va_list ap;
1429 void * arg;
1430 int pcm_fd = *(int*)pcm;
1431
1432 va_start(ap, request);
1433 arg = va_arg(ap, void *);
1434 va_end(ap);
1435
1436 return ioctl(pcm_fd, request, arg);
1437}
1438
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001439int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001440 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001441{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001442 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001443 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +05301444 struct stream_out *out = NULL;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301445 struct stream_in *in = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001446 struct listnode out_devices;
Soumya Managoli6993b762018-06-28 16:04:57 +05301447 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001448
1449 if (usecase == NULL)
1450 return -EINVAL;
1451
1452 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
1453
Carter Hsu2e429db2019-05-14 18:50:52 +08001454 if (usecase->type == PCM_CAPTURE) {
1455 struct stream_in *in = usecase->stream.in;
1456 struct audio_usecase *uinfo;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001457 snd_device = usecase->in_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001458
1459 if (in) {
1460 if (in->enable_aec || in->enable_ec_port) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001461 list_init(&out_devices);
1462 update_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "", true);
Carter Hsu2e429db2019-05-14 18:50:52 +08001463 struct listnode *node;
1464 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1465 USECASE_AUDIO_PLAYBACK_VOIP);
1466 if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001467 assign_devices(&out_devices,
1468 &voip_usecase->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001469 } else if (adev->primary_output &&
1470 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001471 assign_devices(&out_devices,
1472 &adev->primary_output->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001473 } else {
1474 list_for_each(node, &adev->usecase_list) {
1475 uinfo = node_to_item(node, struct audio_usecase, list);
1476 if (uinfo->type != PCM_CAPTURE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001477 assign_devices(&out_devices,
1478 &uinfo->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001479 break;
1480 }
1481 }
1482 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001483
1484 platform_set_echo_reference(adev, true, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001485 in->ec_opened = true;
Zhenlin Lian4f947842022-05-14 15:50:52 +05301486 clear_devices(&out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001487 }
1488 }
Guodong Huf5e614d2019-06-24 18:42:03 +08001489 } else if ((usecase->type == TRANSCODE_LOOPBACK_TX) || ((usecase->type == PCM_HFP_CALL) &&
1490 ((usecase->id == USECASE_AUDIO_HFP_SCO) || (usecase->id == USECASE_AUDIO_HFP_SCO_WB)) &&
1491 (usecase->in_snd_device == SND_DEVICE_IN_VOICE_SPEAKER_MIC_HFP_MMSECNS))) {
Carter Hsu2e429db2019-05-14 18:50:52 +08001492 snd_device = usecase->in_snd_device;
1493 } else {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001494 snd_device = usecase->out_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001495 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001496
Kunlei Zhanga3c4cb02021-03-05 16:03:54 +08001497 if (usecase->type == PCM_CAPTURE) {
1498 if (platform_get_fluence_nn_state(adev->platform) == 0) {
1499 platform_set_fluence_nn_state(adev->platform, true);
1500 ALOGD("%s: set fluence nn capture state", __func__);
1501 }
1502 }
1503
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001504#ifdef DS1_DOLBY_DAP_ENABLED
1505 audio_extn_dolby_set_dmid(adev);
1506 audio_extn_dolby_set_endpoint(adev);
1507#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001508 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001509 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301510 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001511 audio_extn_utils_send_app_type_cfg(adev, usecase);
Jasmine Cha4dcc1092019-03-04 18:12:47 +08001512 if (audio_extn_is_maxx_audio_enabled())
1513 audio_extn_ma_set_device(usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301514 audio_extn_utils_send_audio_calibration(adev, usecase);
Zhou Songbaddf9f2020-11-20 13:57:39 +08001515 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1516 out = usecase->stream.out;
1517 if (out && out->compr)
Manish Dewangan58229382017-02-02 15:48:41 +05301518 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1519 }
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301520
1521 if (usecase->type == PCM_CAPTURE) {
Kunlei Zhanga3c4cb02021-03-05 16:03:54 +08001522 if (platform_get_fluence_nn_state(adev->platform) == 1 &&
1523 adev->fluence_nn_usecase_id == USECASE_INVALID ) {
1524 adev->fluence_nn_usecase_id = usecase->id;
1525 ALOGD("%s: assign fluence nn usecase %d", __func__, usecase->id);
1526 }
1527 }
1528
1529 if (usecase->type == PCM_CAPTURE) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301530 in = usecase->stream.in;
Avinash Chandrad7296d42021-08-04 15:07:47 +05301531 if ((in && is_loopback_input_device(get_device_types(&in->device_list))) ||
1532 (in && is_combo_audio_input_device(&in->device_list)) ||
1533 (in && ((compare_device_type(&in->device_list, AUDIO_DEVICE_IN_BUILTIN_MIC) ||
1534 compare_device_type(&in->device_list, AUDIO_DEVICE_IN_LINE)) &&
1535 (snd_device == SND_DEVICE_IN_HANDSET_GENERIC_6MIC)))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301536 ALOGD("%s: set custom mtmx params v1", __func__);
1537 audio_extn_set_custom_mtmx_params_v1(adev, usecase, true);
1538 }
1539 } else {
1540 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
1541 }
Manish Dewangan58229382017-02-02 15:48:41 +05301542
Andy Hung756ecc12018-10-19 17:47:12 -07001543 // we shouldn't truncate mixer_path
1544 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1545 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1546 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001547 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001548 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301549 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1550 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1551 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1552 if (parms) {
1553 audio_extn_fm_set_parameters(adev, parms);
1554 str_parms_destroy(parms);
1555 }
1556 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001557 ALOGV("%s: exit", __func__);
1558 return 0;
1559}
1560
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001561int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001562 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001563{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001564 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001565 char mixer_path[MIXER_PATH_MAX_LENGTH];
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301566 struct stream_in *in = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001567
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301568 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001569 return -EINVAL;
1570
1571 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301572 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001573 snd_device = usecase->in_snd_device;
1574 else
1575 snd_device = usecase->out_snd_device;
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001576
1577 /* disable island and power mode on supported device for voice call */
1578 if (usecase->type == VOICE_CALL) {
1579 if (usecase->in_snd_device != SND_DEVICE_NONE) {
1580 if (platform_get_island_cfg_on_device(adev->platform, usecase->in_snd_device) &&
1581 platform_get_power_mode_on_device(adev->platform, usecase->in_snd_device)) {
1582 platform_set_island_cfg_on_device(adev, usecase->in_snd_device, false);
1583 platform_set_power_mode_on_device(adev, usecase->in_snd_device, false);
1584 platform_reset_island_power_status(adev->platform, usecase->in_snd_device);
Kunlei Zhang91c4b332020-07-20 17:53:14 +08001585 if (voice_is_lte_call_active(adev))
1586 platform_set_tx_lpi_mode(adev->platform, false);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001587 ALOGD("%s: disable island cfg and power mode in voice tx path",
1588 __func__);
1589 }
1590 }
1591 if (usecase->out_snd_device != SND_DEVICE_NONE) {
1592 if (platform_get_island_cfg_on_device(adev->platform, usecase->out_snd_device) &&
1593 platform_get_power_mode_on_device(adev->platform, usecase->out_snd_device)) {
1594 platform_set_island_cfg_on_device(adev, usecase->out_snd_device, false);
1595 platform_set_power_mode_on_device(adev, usecase->out_snd_device, false);
1596 platform_reset_island_power_status(adev->platform, usecase->out_snd_device);
1597 ALOGD("%s: disable island cfg and power mode in voice rx path",
1598 __func__);
1599 }
1600 }
1601 }
1602
Andy Hung756ecc12018-10-19 17:47:12 -07001603 // we shouldn't truncate mixer_path
1604 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1605 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1606 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001607 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001608 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001609 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Carter Hsu2e429db2019-05-14 18:50:52 +08001610 if (usecase->type == PCM_CAPTURE) {
1611 struct stream_in *in = usecase->stream.in;
1612 if (in && in->ec_opened) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001613 struct listnode out_devices;
1614 list_init(&out_devices);
1615 platform_set_echo_reference(in->dev, false, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001616 in->ec_opened = false;
Zhenlin Lian4f947842022-05-14 15:50:52 +05301617 clear_devices(&out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001618 }
1619 }
Kunlei Zhanga3c4cb02021-03-05 16:03:54 +08001620 if (usecase->id == adev->fluence_nn_usecase_id) {
1621 platform_set_fluence_nn_state(adev->platform, false);
1622 adev->fluence_nn_usecase_id = USECASE_INVALID;
1623 ALOGD("%s: reset fluence nn capture state", __func__);
1624 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001625 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301626 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301627
1628 if (usecase->type == PCM_CAPTURE) {
1629 in = usecase->stream.in;
Avinash Chandrad7296d42021-08-04 15:07:47 +05301630 if ((in && is_loopback_input_device(get_device_types(&in->device_list))) ||
1631 (in && is_combo_audio_input_device(&in->device_list)) ||
1632 (in && ((compare_device_type(&in->device_list, AUDIO_DEVICE_IN_BUILTIN_MIC) ||
1633 compare_device_type(&in->device_list, AUDIO_DEVICE_IN_LINE)) &&
1634 (snd_device == SND_DEVICE_IN_HANDSET_GENERIC_6MIC)))){
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301635 ALOGD("%s: reset custom mtmx params v1", __func__);
1636 audio_extn_set_custom_mtmx_params_v1(adev, usecase, false);
1637 }
1638 } else {
1639 audio_extn_set_custom_mtmx_params_v2(adev, usecase, false);
1640 }
1641
Weiyin Jiang298ffd92019-06-03 14:29:30 +08001642 if ((usecase->type == PCM_PLAYBACK) &&
1643 (usecase->stream.out != NULL))
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05301644 usecase->stream.out->pspd_coeff_sent = false;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301645
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001646 ALOGV("%s: exit", __func__);
1647 return 0;
1648}
1649
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001650int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001651 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001652{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301653 int i, num_devices = 0;
1654 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001655 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1656
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001657 if (snd_device < SND_DEVICE_MIN ||
1658 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001659 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001660 return -EINVAL;
1661 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001662
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001663 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001664 ALOGE("%s: Invalid sound device returned", __func__);
1665 return -EINVAL;
1666 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001667
1668 adev->snd_dev_ref_cnt[snd_device]++;
1669
1670 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1671 (platform_split_snd_device(adev->platform,
1672 snd_device,
1673 &num_devices,
1674 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001675 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001676 __func__, snd_device, device_name);
Aniket Kumar Lata990de552019-07-11 14:20:23 -07001677 /* Set backend config for A2DP to ensure slimbus configuration
1678 is correct if A2DP is already active and backend is closed
1679 and re-opened */
1680 if (snd_device == SND_DEVICE_OUT_BT_A2DP)
1681 audio_extn_a2dp_set_source_backend_cfg();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001682 return 0;
1683 }
1684
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001685 if (audio_extn_spkr_prot_is_enabled())
1686 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001687
Aalique Grahame22e49102018-12-18 14:23:57 -08001688 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1689
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001690 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1691 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001692 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1693 goto err;
1694 }
1695 audio_extn_dev_arbi_acquire(snd_device);
1696 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001697 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001698 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001699 goto err;
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001700 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001701 } else if (platform_split_snd_device(adev->platform,
1702 snd_device,
1703 &num_devices,
1704 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301705 for (i = 0; i < num_devices; i++) {
1706 enable_snd_device(adev, new_snd_devices[i]);
1707 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001708 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001709 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001710 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301711
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001712 /* enable island and power mode on supported device */
1713 if (platform_get_island_cfg_on_device(adev->platform, snd_device) &&
1714 platform_get_power_mode_on_device(adev->platform, snd_device)) {
1715 platform_set_island_cfg_on_device(adev, snd_device, true);
1716 platform_set_power_mode_on_device(adev, snd_device, true);
Kunlei Zhang91c4b332020-07-20 17:53:14 +08001717 if (voice_is_lte_call_active(adev) &&
1718 (snd_device >= SND_DEVICE_IN_BEGIN &&
1719 snd_device < SND_DEVICE_IN_END))
1720 platform_set_tx_lpi_mode(adev->platform, true);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001721 ALOGD("%s: enable island cfg and power mode on: %s",
1722 __func__, device_name);
1723 }
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301724
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301725 if (SND_DEVICE_OUT_BT_A2DP == snd_device) {
Ramjee Singh2d2944a2021-12-14 14:13:41 +05301726
1727 struct audio_usecase *usecase;
1728 struct listnode *node;
1729 /* Disable SCO Devices and enable handset mic for active input stream */
1730 list_for_each(node, &adev->usecase_list) {
1731 usecase = node_to_item(node, struct audio_usecase, list);
1732 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
1733 is_sco_in_device_type(&usecase->stream.in->device_list)) {
1734 ALOGD("a2dp resumed, switch bt sco mic to handset mic");
1735 reassign_device_list(&usecase->stream.in->device_list,
1736 AUDIO_DEVICE_IN_BUILTIN_MIC, "");
1737 select_devices(adev, usecase->id);
1738 }
1739 }
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301740 if (audio_extn_a2dp_start_playback() < 0) {
1741 ALOGE(" fail to configure A2dp Source control path ");
1742 goto err;
1743 } else {
1744 adev->a2dp_started = true;
1745 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001746 }
Florian Pfister1a84f312018-07-19 14:38:18 +02001747
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001748 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1749 (audio_extn_a2dp_start_capture() < 0)) {
1750 ALOGE(" fail to configure A2dp Sink control path ");
1751 goto err;
1752 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301753
Mingshu Pang7be5b1d2020-03-04 15:24:38 +08001754 if ((SND_DEVICE_OUT_BT_SCO_SWB == snd_device) ||
1755 (SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC == snd_device) ||
1756 (SND_DEVICE_IN_BT_SCO_MIC_SWB == snd_device)) {
1757 if (!adev->bt_sco_on || (audio_extn_sco_start_configuration() < 0)) {
1758 ALOGE(" fail to configure sco control path ");
1759 goto err;
1760 }
Zhou Song12c29502019-03-16 10:37:18 +08001761 }
1762
Zhou Song331c8e52019-08-26 14:16:12 +08001763 configure_btsco_sample_rate(snd_device);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001764 /* due to the possibility of calibration overwrite between listen
1765 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001766 audio_extn_sound_trigger_update_device_status(snd_device,
1767 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301768 audio_extn_listen_update_device_status(snd_device,
1769 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001770 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001771 audio_extn_sound_trigger_update_device_status(snd_device,
1772 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301773 audio_extn_listen_update_device_status(snd_device,
1774 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001775 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001776 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001777 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001778 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301779
1780 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1781 !adev->native_playback_enabled &&
1782 audio_is_true_native_stream_active(adev)) {
1783 ALOGD("%s: %d: napb: enabling native mode in hardware",
1784 __func__, __LINE__);
1785 audio_route_apply_and_update_path(adev->audio_route,
1786 "true-native-mode");
1787 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301788 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301789 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1790 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001791 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001792 ALOGD("%s: init ec ref loopback", __func__);
1793 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1794 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001795 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001796 return 0;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001797err:
1798 adev->snd_dev_ref_cnt[snd_device]--;
1799 return -EINVAL;;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001800}
1801
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001802int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001803 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001804{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301805 int i, num_devices = 0;
1806 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001807 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1808
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001809 if (snd_device < SND_DEVICE_MIN ||
1810 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001811 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001812 return -EINVAL;
1813 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001814
1815 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1816 ALOGE("%s: Invalid sound device returned", __func__);
1817 return -EINVAL;
1818 }
1819
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001820 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1821 ALOGE("%s: device ref cnt is already 0", __func__);
1822 return -EINVAL;
1823 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001824
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001825 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001826
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001827
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001828 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001829 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301830
Aalique Grahame22e49102018-12-18 14:23:57 -08001831 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1832
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001833 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1834 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001835 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001836
1837 // when speaker device is disabled, reset swap.
1838 // will be renabled on usecase start
1839 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001840 } else if (platform_split_snd_device(adev->platform,
1841 snd_device,
1842 &num_devices,
1843 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301844 for (i = 0; i < num_devices; i++) {
1845 disable_snd_device(adev, new_snd_devices[i]);
1846 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001847 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001848 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001849 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001850 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001851
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301852 if (snd_device == SND_DEVICE_OUT_BT_A2DP) {
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301853 audio_extn_a2dp_stop_playback();
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301854 adev->a2dp_started = false;
1855 } else if (snd_device == SND_DEVICE_IN_BT_A2DP)
Florian Pfister1a84f312018-07-19 14:38:18 +02001856 audio_extn_a2dp_stop_capture();
Zhou Songd6d71752019-05-21 18:08:51 +08001857 else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001858 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
Ashish Jain81eb2a82015-05-13 10:52:34 +05301859 adev->is_channel_status_set = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001860 else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301861 adev->native_playback_enabled) {
1862 ALOGD("%s: %d: napb: disabling native mode in hardware",
1863 __func__, __LINE__);
1864 audio_route_reset_and_update_path(adev->audio_route,
1865 "true-native-mode");
1866 adev->native_playback_enabled = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001867 } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301868 adev->asrc_mode_enabled) {
1869 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301870 disable_asrc_mode(adev);
1871 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001872 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301873 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001874 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001875 ALOGD("%s: deinit ec ref loopback", __func__);
1876 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1877 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001878
1879 audio_extn_utils_release_snd_device(snd_device);
1880 } else {
1881 if (platform_split_snd_device(adev->platform,
1882 snd_device,
1883 &num_devices,
1884 new_snd_devices) == 0) {
1885 for (i = 0; i < num_devices; i++) {
1886 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1887 }
1888 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001889 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001890
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001891 return 0;
1892}
1893
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001894/*
1895 legend:
1896 uc - existing usecase
1897 new_uc - new usecase
1898 d1, d11, d2 - SND_DEVICE enums
1899 a1, a2 - corresponding ANDROID device enums
1900 B1, B2 - backend strings
1901
1902case 1
1903 uc->dev d1 (a1) B1
1904 new_uc->dev d1 (a1), d2 (a2) B1, B2
1905
1906 resolution: disable and enable uc->dev on d1
1907
1908case 2
1909 uc->dev d1 (a1) B1
1910 new_uc->dev d11 (a1) B1
1911
1912 resolution: need to switch uc since d1 and d11 are related
1913 (e.g. speaker and voice-speaker)
1914 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1915
1916case 3
1917 uc->dev d1 (a1) B1
1918 new_uc->dev d2 (a2) B2
1919
1920 resolution: no need to switch uc
1921
1922case 4
1923 uc->dev d1 (a1) B1
1924 new_uc->dev d2 (a2) B1
1925
1926 resolution: disable enable uc-dev on d2 since backends match
1927 we cannot enable two streams on two different devices if they
1928 share the same backend. e.g. if offload is on speaker device using
1929 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1930 using the same backend, offload must also be switched to voice-handset.
1931
1932case 5
1933 uc->dev d1 (a1) B1
1934 new_uc->dev d1 (a1), d2 (a2) B1
1935
1936 resolution: disable enable uc-dev on d2 since backends match
1937 we cannot enable two streams on two different devices if they
1938 share the same backend.
1939
1940case 6
1941 uc->dev d1 (a1) B1
1942 new_uc->dev d2 (a1) B2
1943
1944 resolution: no need to switch
1945
1946case 7
1947 uc->dev d1 (a1), d2 (a2) B1, B2
1948 new_uc->dev d1 (a1) B1
1949
1950 resolution: no need to switch
1951
Zhou Song4ba65882018-07-09 14:48:07 +08001952case 8
1953 uc->dev d1 (a1) B1
1954 new_uc->dev d11 (a1), d2 (a2) B1, B2
1955 resolution: compared to case 1, for this case, d1 and d11 are related
1956 then need to do the same as case 2 to siwtch to new uc
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301957
1958case 9
1959 uc->dev d1 (a1), d2(a2) B1 B2
1960 new_uc->dev d1 (a1), d22 (a2) B1, B2
1961 resolution: disable enable uc-dev on d2 since backends match
1962 we cannot enable two streams on two different devices if they
1963 share the same backend. This is special case for combo use case
1964 with a2dp and sco devices which uses same backend.
1965 e.g. speaker-a2dp and speaker-btsco
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001966*/
1967static snd_device_t derive_playback_snd_device(void * platform,
1968 struct audio_usecase *uc,
1969 struct audio_usecase *new_uc,
1970 snd_device_t new_snd_device)
1971{
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001972 struct listnode a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001973
1974 snd_device_t d1 = uc->out_snd_device;
1975 snd_device_t d2 = new_snd_device;
Sandhya Mutha Naga Venkataa597a962023-02-07 11:35:51 +05301976 int ret = 0;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001977
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001978 list_init(&a1);
1979 list_init(&a2);
1980
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301981 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301982 case TRANSCODE_LOOPBACK_RX :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001983 assign_devices(&a1, &uc->stream.inout->out_config.device_list);
1984 assign_devices(&a2, &new_uc->stream.inout->out_config.device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301985 break;
1986 default :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001987 assign_devices(&a1, &uc->stream.out->device_list);
1988 assign_devices(&a2, &new_uc->stream.out->device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301989 break;
1990 }
1991
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001992 // Treat as a special case when a1 and a2 are not disjoint
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001993 if (!compare_devices(&a1, &a2) &&
1994 compare_devices_for_any_match(&a1 ,&a2)) {
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001995 snd_device_t d3[2];
1996 int num_devices = 0;
Sandhya Mutha Naga Venkataa597a962023-02-07 11:35:51 +05301997 ret = platform_split_snd_device(platform,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001998 list_length(&a1) > 1 ? d1 : d2,
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001999 &num_devices,
2000 d3);
2001 if (ret < 0) {
2002 if (ret != -ENOSYS) {
2003 ALOGW("%s failed to split snd_device %d",
2004 __func__,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002005 list_length(&a1) > 1 ? d1 : d2);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07002006 }
Sandhya Mutha Naga Venkata4c6fc9f2022-10-14 19:38:02 +05302007 ret = d2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07002008 goto end;
2009 }
2010
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07002011 if (platform_check_backends_match(d3[0], d3[1])) {
Sandhya Mutha Naga Venkata4c6fc9f2022-10-14 19:38:02 +05302012 ret = d2;
2013 goto end; // case 5
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07002014 } else {
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05302015 if ((list_length(&a1) > 1) && (list_length(&a2) > 1) &&
Sandhya Mutha Naga Venkata4c6fc9f2022-10-14 19:38:02 +05302016 platform_check_backends_match(d1, d2)) {
2017 ret = d2;
2018 goto end; //case 9
2019 }
2020 if (list_length(&a1) > 1) {
2021 ret = d1;
2022 goto end; //case 7
2023 }
Garmond Leungb9eeba42018-09-18 11:10:41 -07002024 // check if d1 is related to any of d3's
Sandhya Mutha Naga Venkata4c6fc9f2022-10-14 19:38:02 +05302025 if (d1 == d3[0] || d1 == d3[1]) {
2026 ret = d1;
2027 goto end; // case 1
2028 } else {
2029 ret = d3[1];
2030 goto end; // case 8
2031 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07002032 }
2033 } else {
2034 if (platform_check_backends_match(d1, d2)) {
Sandhya Mutha Naga Venkata4c6fc9f2022-10-14 19:38:02 +05302035 ret = d2;
2036 goto end; // case 2, 4
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07002037 } else {
Sandhya Mutha Naga Venkata4c6fc9f2022-10-14 19:38:02 +05302038 ret = d1;
2039 goto end; // case 6, 3
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07002040 }
2041 }
2042
2043end:
Sandhya Mutha Naga Venkata4c6fc9f2022-10-14 19:38:02 +05302044 clear_devices(&a1);
2045 clear_devices(&a2);
2046 return ret; // return whatever was calculated before.
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07002047}
2048
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002049static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05302050 struct audio_usecase *uc_info,
2051 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002052{
2053 struct listnode *node;
2054 struct audio_usecase *usecase;
2055 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05302056 snd_device_t uc_derive_snd_device;
2057 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08002058 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
2059 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08002060 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302061 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002062 /*
2063 * This function is to make sure that all the usecases that are active on
2064 * the hardware codec backend are always routed to any one device that is
2065 * handled by the hardware codec.
2066 * For example, if low-latency and deep-buffer usecases are currently active
2067 * on speaker and out_set_parameters(headset) is received on low-latency
2068 * output, then we have to make sure deep-buffer is also switched to headset,
2069 * because of the limitation that both the devices cannot be enabled
2070 * at the same time as they share the same backend.
2071 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07002072 /*
2073 * This call is to check if we need to force routing for a particular stream
2074 * If there is a backend configuration change for the device when a
2075 * new stream starts, then ADM needs to be closed and re-opened with the new
2076 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08002077 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07002078 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08002079 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
2080 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302081 /* For a2dp device reconfigure all active sessions
2082 * with new AFE encoder format based on a2dp state
2083 */
2084 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05302085 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device ||
2086 SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP == snd_device) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302087 audio_extn_a2dp_is_force_device_switch()) {
2088 force_routing = true;
2089 force_restart_session = true;
2090 }
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08002091
2092 /*
2093 * Island cfg and power mode config needs to set before AFE port start.
2094 * Set force routing in case of voice device was enable before.
2095 */
2096 if (uc_info->type == VOICE_CALL &&
2097 voice_extn_is_voice_power_mode_supported() &&
Kunlei Zhang67cc7072020-12-18 17:16:49 +08002098 is_supported_conc_usecase_for_power_mode_call(adev) &&
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08002099 platform_check_and_update_island_power_status(adev->platform,
2100 uc_info,
2101 snd_device)) {
2102 force_routing = true;
2103 ALOGD("%s:becf: force routing %d for power mode supported device",
2104 __func__, force_routing);
2105 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302106 ALOGD("%s:becf: force routing %d", __func__, force_routing);
2107
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002108 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002109 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002110 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002111 for (i = 0; i < AUDIO_USECASE_MAX; i++)
2112 switch_device[i] = false;
2113
2114 list_for_each(node, &adev->usecase_list) {
2115 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08002116
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05302117 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
2118 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302119 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05302120 platform_get_snd_device_name(usecase->out_snd_device),
2121 platform_check_backends_match(snd_device, usecase->out_snd_device));
Rahul Sharma99770982019-03-06 17:05:26 +05302122 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
2123 (usecase->type != PCM_PASSTHROUGH)) {
Ashish Jain6a65b352017-03-21 17:24:40 +05302124 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
2125 usecase, uc_info, snd_device);
2126 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002127 (is_codec_backend_out_device_type(&usecase->device_list) ||
2128 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
2129 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_DEVICE) ||
2130 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_HEADSET) ||
2131 is_a2dp_out_device_type(&usecase->device_list) ||
2132 is_sco_out_device_type(&usecase->device_list)) &&
Ashish Jain6a65b352017-03-21 17:24:40 +05302133 ((force_restart_session) ||
2134 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05302135 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
2136 __func__, use_case_table[usecase->id],
2137 platform_get_snd_device_name(usecase->out_snd_device));
2138 disable_audio_route(adev, usecase);
2139 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05302140 /* Enable existing usecase on derived playback device */
2141 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05302142 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05302143 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002144 }
2145 }
2146
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302147 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
2148 num_uc_to_switch);
2149
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002150 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07002151 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002152
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05302153 /* Make sure the previous devices to be disabled first and then enable the
2154 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002155 list_for_each(node, &adev->usecase_list) {
2156 usecase = node_to_item(node, struct audio_usecase, list);
2157 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08002158 /* Check if output sound device to be switched can be split and if any
2159 of the split devices match with derived sound device */
2160 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
2161 &num_devices, split_snd_devices) == 0) {
2162 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
2163 for (i = 0; i < num_devices; i++) {
2164 /* Disable devices that do not match with derived sound device */
2165 if (split_snd_devices[i] != derive_snd_device[usecase->id])
2166 disable_snd_device(adev, split_snd_devices[i]);
2167 }
2168 } else {
2169 disable_snd_device(adev, usecase->out_snd_device);
2170 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002171 }
2172 }
2173
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07002174 list_for_each(node, &adev->usecase_list) {
2175 usecase = node_to_item(node, struct audio_usecase, list);
2176 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08002177 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
2178 &num_devices, split_snd_devices) == 0) {
2179 /* Enable derived sound device only if it does not match with
2180 one of the split sound devices. This is because the matching
2181 sound device was not disabled */
2182 bool should_enable = true;
2183 for (i = 0; i < num_devices; i++) {
2184 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
2185 should_enable = false;
2186 break;
2187 }
2188 }
2189 if (should_enable)
2190 enable_snd_device(adev, derive_snd_device[usecase->id]);
2191 } else {
2192 enable_snd_device(adev, derive_snd_device[usecase->id]);
2193 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07002194 }
2195 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002196
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002197 /* Re-route all the usecases on the shared backend other than the
2198 specified usecase to new snd devices */
2199 list_for_each(node, &adev->usecase_list) {
2200 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05302201 /* Update the out_snd_device only before enabling the audio route */
2202 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05302203 usecase->out_snd_device = derive_snd_device[usecase->id];
Lakshman Chaluvarajuab7e5572020-10-28 19:29:23 +05302204 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
2205 use_case_table[usecase->id],
2206 platform_get_snd_device_name(usecase->out_snd_device));
2207 /* Update voc calibration before enabling Voice/VoIP route */
2208 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL)
2209 status = platform_switch_voice_call_device_post(adev->platform,
2210 usecase->out_snd_device,
2211 platform_get_input_snd_device(
2212 adev->platform, NULL,
2213 &uc_info->device_list,
2214 usecase->type));
2215 enable_audio_route(adev, usecase);
2216 if (usecase->stream.out && usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
2217 out_set_voip_volume(&usecase->stream.out->stream,
2218 usecase->stream.out->volume_l,
2219 usecase->stream.out->volume_r);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05302220 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002221 }
2222 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002223 }
2224}
2225
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302226static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002227 struct audio_usecase *uc_info,
2228 snd_device_t snd_device)
2229{
2230 struct listnode *node;
2231 struct audio_usecase *usecase;
2232 bool switch_device[AUDIO_USECASE_MAX];
2233 int i, num_uc_to_switch = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002234 int backend_check_cond = is_codec_backend_out_device_type(&uc_info->device_list);
kunleiz5cd52b82016-11-07 17:22:52 +08002235 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002236
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302237 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
2238 snd_device);
2239 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05302240
2241 /*
2242 * Make sure out devices is checked against out codec backend device and
2243 * also in devices against in codec backend. Checking out device against in
2244 * codec backend or vice versa causes issues.
2245 */
2246 if (uc_info->type == PCM_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002247 backend_check_cond = is_codec_backend_in_device_type(&uc_info->device_list);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08002248
2249 /*
2250 * Island cfg and power mode config needs to set before AFE port start.
2251 * Set force routing in case of voice device was enable before.
2252 */
2253
2254 if (uc_info->type == VOICE_CALL &&
2255 voice_extn_is_voice_power_mode_supported() &&
Kunlei Zhang67cc7072020-12-18 17:16:49 +08002256 is_supported_conc_usecase_for_power_mode_call(adev) &&
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08002257 platform_check_and_update_island_power_status(adev->platform,
2258 uc_info,
2259 snd_device)) {
2260 force_routing = true;
2261 ALOGD("%s:becf: force routing %d for power mode supported device",
2262 __func__, force_routing);
2263 }
2264
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002265 /*
2266 * This function is to make sure that all the active capture usecases
2267 * are always routed to the same input sound device.
2268 * For example, if audio-record and voice-call usecases are currently
2269 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
2270 * is received for voice call then we have to make sure that audio-record
2271 * usecase is also switched to earpiece i.e. voice-dmic-ef,
2272 * because of the limitation that two devices cannot be enabled
2273 * at the same time if they share the same backend.
2274 */
2275 for (i = 0; i < AUDIO_USECASE_MAX; i++)
2276 switch_device[i] = false;
2277
2278 list_for_each(node, &adev->usecase_list) {
2279 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05302280 /*
2281 * TODO: Enhance below condition to handle BT sco/USB multi recording
2282 */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302283
2284 bool capture_uc_needs_routing = usecase->type != PCM_PLAYBACK && (usecase != uc_info &&
2285 (usecase->in_snd_device != snd_device || force_routing));
2286 bool call_proxy_snd_device = platform_is_call_proxy_snd_device(snd_device) ||
2287 platform_is_call_proxy_snd_device(usecase->in_snd_device);
2288 if (capture_uc_needs_routing && !call_proxy_snd_device &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002289 ((backend_check_cond &&
2290 (is_codec_backend_in_device_type(&usecase->device_list) ||
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08002291 (usecase->type == VOIP_CALL))) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08002292 ((uc_info->type == VOICE_CALL &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002293 is_single_device_type_equal(&usecase->device_list,
2294 AUDIO_DEVICE_IN_VOICE_CALL)) ||
Anver sadhique4fdc6992022-01-21 12:26:28 +05302295 platform_check_all_backends_match(snd_device,\
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002296 usecase->in_snd_device))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07002297 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05302298 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..",
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002299 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07002300 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002301 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002302 switch_device[usecase->id] = true;
2303 num_uc_to_switch++;
2304 }
2305 }
2306
2307 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07002308 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002309
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05302310 /* Make sure the previous devices to be disabled first and then enable the
2311 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002312 list_for_each(node, &adev->usecase_list) {
2313 usecase = node_to_item(node, struct audio_usecase, list);
2314 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002315 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08002316 }
2317 }
2318
2319 list_for_each(node, &adev->usecase_list) {
2320 usecase = node_to_item(node, struct audio_usecase, list);
2321 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002322 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002323 }
2324 }
2325
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002326 /* Re-route all the usecases on the shared backend other than the
2327 specified usecase to new snd devices */
2328 list_for_each(node, &adev->usecase_list) {
2329 usecase = node_to_item(node, struct audio_usecase, list);
2330 /* Update the in_snd_device only before enabling the audio route */
2331 if (switch_device[usecase->id] ) {
2332 usecase->in_snd_device = snd_device;
Lakshman Chaluvarajuab7e5572020-10-28 19:29:23 +05302333 /* Update voc calibration before enabling Voice/VoIP route */
2334 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
2335 snd_device_t voip_snd_device;
2336 voip_snd_device = platform_get_output_snd_device(adev->platform,
2337 usecase->stream.out,
2338 usecase->type);
2339 status = platform_switch_voice_call_device_post(adev->platform,
2340 voip_snd_device,
2341 usecase->in_snd_device);
kunleiz5cd52b82016-11-07 17:22:52 +08002342 }
Lakshman Chaluvarajuab7e5572020-10-28 19:29:23 +05302343 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002344 }
2345 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002346 }
2347}
2348
Mingming Yin3a941d42016-02-17 18:08:05 -08002349static void reset_hdmi_sink_caps(struct stream_out *out) {
2350 int i = 0;
2351
2352 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
2353 out->supported_channel_masks[i] = 0;
2354 }
2355 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
2356 out->supported_formats[i] = 0;
2357 }
2358 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
2359 out->supported_sample_rates[i] = 0;
2360 }
2361}
2362
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002363/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08002364static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002365{
Mingming Yin3a941d42016-02-17 18:08:05 -08002366 int ret = 0, i = 0, j = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002367 int channels = platform_edid_get_max_channels_v2(out->dev->platform,
2368 out->extconn.cs.controller,
2369 out->extconn.cs.stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002370
Mingming Yin3a941d42016-02-17 18:08:05 -08002371 reset_hdmi_sink_caps(out);
2372
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002373 /* Cache ext disp type */
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002374 ret = platform_get_ext_disp_type_v2(adev->platform,
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002375 out->extconn.cs.controller,
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002376 out->extconn.cs.stream);
2377 if(ret < 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002378 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07002379 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002380 }
2381
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002382 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002383 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08002384 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002385 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08002386 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
2387 case 6:
2388 ALOGV("%s: HDMI supports 5.1 channels", __func__);
2389 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
2390 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
2391 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
2392 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
2393 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002394 break;
2395 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08002396 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002397 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002398 break;
2399 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002400
2401 // check channel format caps
2402 i = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002403 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_AC3,
2404 out->extconn.cs.controller,
2405 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002406 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
2407 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
2408 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
2409 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
2410 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
2411 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
2412 }
2413
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002414 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD,
2415 out->extconn.cs.controller,
2416 out->extconn.cs.stream)) {
Ben Romberger1aaaf862017-04-06 17:49:46 -07002417 ALOGV(":%s HDMI supports TRUE HD format", __func__);
2418 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
2419 }
2420
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002421 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS,
2422 out->extconn.cs.controller,
2423 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002424 ALOGV(":%s HDMI supports DTS format", __func__);
2425 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
2426 }
2427
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002428 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS_HD,
2429 out->extconn.cs.controller,
2430 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002431 ALOGV(":%s HDMI supports DTS HD format", __func__);
2432 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
2433 }
2434
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002435 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_IEC61937,
2436 out->extconn.cs.controller,
2437 out->extconn.cs.stream)) {
Naresh Tanniru928f0862017-04-07 16:44:23 -07002438 ALOGV(":%s HDMI supports IEC61937 format", __func__);
2439 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
2440 }
2441
Mingming Yin3a941d42016-02-17 18:08:05 -08002442
2443 // check sample rate caps
2444 i = 0;
2445 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002446 if (platform_is_edid_supported_sample_rate_v2(out->dev->platform, out_hdmi_sample_rates[j],
2447 out->extconn.cs.controller,
2448 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002449 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
2450 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
2451 }
2452 }
2453
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002454 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002455}
2456
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002457static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
2458 uint32_t *supported_sample_rates __unused,
2459 uint32_t max_rates __unused)
2460{
2461 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
2462 supported_sample_rates,
2463 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05302464 ssize_t i = 0;
2465
2466 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002467 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
2468 supported_sample_rates[i]);
2469 }
2470 return count;
2471}
2472
2473static inline int read_usb_sup_channel_masks(bool is_playback,
2474 audio_channel_mask_t *supported_channel_masks,
2475 uint32_t max_masks)
2476{
2477 int channels = audio_extn_usb_get_max_channels(is_playback);
2478 int channel_count;
2479 uint32_t num_masks = 0;
2480 if (channels > MAX_HIFI_CHANNEL_COUNT)
2481 channels = MAX_HIFI_CHANNEL_COUNT;
2482
2483 if (is_playback) {
Eric Laurent68a87112019-05-01 18:07:29 -07002484 // start from 2 channels as framework currently doesn't support mono.
2485 if (channels >= FCC_2) {
2486 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(FCC_2);
2487 }
2488 for (channel_count = FCC_2;
2489 channel_count <= channels && num_masks < max_masks;
2490 ++channel_count) {
2491 supported_channel_masks[num_masks++] =
2492 audio_channel_mask_for_index_assignment_from_count(channel_count);
2493 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002494 } else {
vincenttewf51c94e2019-05-07 10:28:53 +08002495 // For capture we report all supported channel masks from 1 channel up.
2496 channel_count = MIN_CHANNEL_COUNT;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002497 // audio_channel_in_mask_from_count() does the right conversion to either positional or
2498 // indexed mask
Eric Laurent68a87112019-05-01 18:07:29 -07002499 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
2500 audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
2501 if (channel_count <= FCC_2) {
2502 mask = audio_channel_in_mask_from_count(channel_count);
2503 supported_channel_masks[num_masks++] = mask;
2504 }
2505 const audio_channel_mask_t index_mask =
2506 audio_channel_mask_for_index_assignment_from_count(channel_count);
2507 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
2508 supported_channel_masks[num_masks++] = index_mask;
2509 }
2510 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002511 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302512
vincenttewf51c94e2019-05-07 10:28:53 +08002513 for (size_t i = 0; i < num_masks; ++i) {
2514 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
2515 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302516 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002517 return num_masks;
2518}
2519
2520static inline int read_usb_sup_formats(bool is_playback __unused,
2521 audio_format_t *supported_formats,
2522 uint32_t max_formats __unused)
2523{
2524 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
2525 switch (bitwidth) {
2526 case 24:
2527 // XXX : usb.c returns 24 for s24 and s24_le?
2528 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
2529 break;
2530 case 32:
2531 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
2532 break;
2533 case 16:
2534 default :
2535 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
2536 break;
2537 }
2538 ALOGV("%s: %s supported format %d", __func__,
2539 is_playback ? "P" : "C", bitwidth);
2540 return 1;
2541}
2542
2543static inline int read_usb_sup_params_and_compare(bool is_playback,
2544 audio_format_t *format,
2545 audio_format_t *supported_formats,
2546 uint32_t max_formats,
2547 audio_channel_mask_t *mask,
2548 audio_channel_mask_t *supported_channel_masks,
2549 uint32_t max_masks,
2550 uint32_t *rate,
2551 uint32_t *supported_sample_rates,
2552 uint32_t max_rates) {
2553 int ret = 0;
2554 int num_formats;
2555 int num_masks;
2556 int num_rates;
2557 int i;
2558
2559 num_formats = read_usb_sup_formats(is_playback, supported_formats,
2560 max_formats);
2561 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
2562 max_masks);
2563
2564 num_rates = read_usb_sup_sample_rates(is_playback,
2565 supported_sample_rates, max_rates);
2566
2567#define LUT(table, len, what, dflt) \
2568 for (i=0; i<len && (table[i] != what); i++); \
2569 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
2570
2571 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
2572 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
2573 LUT(supported_sample_rates, num_rates, *rate, 0);
2574
2575#undef LUT
2576 return ret < 0 ? -EINVAL : 0; // HACK TBD
2577}
2578
Alexy Josephb1379942016-01-29 15:49:38 -08002579audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002580 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002581{
2582 struct audio_usecase *usecase;
2583 struct listnode *node;
2584
2585 list_for_each(node, &adev->usecase_list) {
2586 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002587 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002588 ALOGV("%s: usecase id %d", __func__, usecase->id);
2589 return usecase->id;
2590 }
2591 }
2592 return USECASE_INVALID;
2593}
2594
Alexy Josephb1379942016-01-29 15:49:38 -08002595struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002596 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002597{
2598 struct audio_usecase *usecase;
2599 struct listnode *node;
2600
2601 list_for_each(node, &adev->usecase_list) {
2602 usecase = node_to_item(node, struct audio_usecase, list);
2603 if (usecase->id == uc_id)
2604 return usecase;
2605 }
2606 return NULL;
2607}
2608
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302609/*
2610 * is a true native playback active
2611 */
2612bool audio_is_true_native_stream_active(struct audio_device *adev)
2613{
2614 bool active = false;
2615 int i = 0;
2616 struct listnode *node;
2617
2618 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
2619 ALOGV("%s:napb: not in true mode or non hdphones device",
2620 __func__);
2621 active = false;
2622 goto exit;
2623 }
2624
2625 list_for_each(node, &adev->usecase_list) {
2626 struct audio_usecase *uc;
2627 uc = node_to_item(node, struct audio_usecase, list);
2628 struct stream_out *curr_out =
2629 (struct stream_out*) uc->stream.out;
2630
2631 if (curr_out && PCM_PLAYBACK == uc->type) {
2632 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
2633 "(%d) device %s", __func__, i++, use_case_table[uc->id],
2634 uc->id, curr_out->sample_rate,
2635 curr_out->bit_width,
2636 platform_get_snd_device_name(uc->out_snd_device));
2637
2638 if (is_offload_usecase(uc->id) &&
2639 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
2640 active = true;
2641 ALOGD("%s:napb:native stream detected", __func__);
2642 }
2643 }
2644 }
2645exit:
2646 return active;
2647}
2648
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002649uint32_t adev_get_dsp_bit_width_enforce_mode()
2650{
2651 if (adev == NULL) {
2652 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
2653 return 0;
2654 }
2655 return adev->dsp_bit_width_enforce_mode;
2656}
2657
2658static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
2659{
2660 char value[PROPERTY_VALUE_MAX];
2661 int trial;
2662 uint32_t dsp_bit_width_enforce_mode = 0;
2663
2664 if (!mixer) {
2665 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
2666 __func__);
2667 return 0;
2668 }
2669
2670 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
2671 value, NULL) > 0) {
2672 trial = atoi(value);
2673 switch (trial) {
2674 case 16:
2675 dsp_bit_width_enforce_mode = 16;
2676 break;
2677 case 24:
2678 dsp_bit_width_enforce_mode = 24;
2679 break;
2680 case 32:
2681 dsp_bit_width_enforce_mode = 32;
2682 break;
2683 default:
2684 dsp_bit_width_enforce_mode = 0;
2685 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
2686 break;
2687 }
2688 }
2689
2690 return dsp_bit_width_enforce_mode;
2691}
2692
2693static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
2694 uint32_t enforce_mode,
2695 bool enable)
2696{
2697 struct mixer_ctl *ctl = NULL;
2698 const char *mixer_ctl_name = "ASM Bit Width";
2699 uint32_t asm_bit_width_mode = 0;
2700
2701 if (enforce_mode == 0) {
2702 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
2703 return;
2704 }
2705
2706 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
2707 if (!ctl) {
2708 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2709 __func__, mixer_ctl_name);
2710 return;
2711 }
2712
2713 if (enable)
2714 asm_bit_width_mode = enforce_mode;
2715 else
2716 asm_bit_width_mode = 0;
2717
2718 ALOGV("%s DSP bit width feature status is %d width=%d",
2719 __func__, enable, asm_bit_width_mode);
2720 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2721 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2722 asm_bit_width_mode);
2723
2724 return;
2725}
2726
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302727/*
2728 * if native DSD playback active
2729 */
2730bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2731{
2732 bool active = false;
2733 struct listnode *node = NULL;
2734 struct audio_usecase *uc = NULL;
2735 struct stream_out *curr_out = NULL;
2736
2737 list_for_each(node, &adev->usecase_list) {
2738 uc = node_to_item(node, struct audio_usecase, list);
2739 curr_out = (struct stream_out*) uc->stream.out;
2740
2741 if (curr_out && PCM_PLAYBACK == uc->type &&
2742 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2743 active = true;
2744 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302745 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302746 }
2747 }
2748 return active;
2749}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302750
2751static bool force_device_switch(struct audio_usecase *usecase)
2752{
2753 bool ret = false;
2754 bool is_it_true_mode = false;
2755
Zhou Song30f2c3e2018-02-08 14:02:15 +08002756 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302757 usecase->type == TRANSCODE_LOOPBACK_RX ||
2758 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002759 return false;
2760 }
2761
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002762 if(usecase->stream.out == NULL) {
2763 ALOGE("%s: stream.out is NULL", __func__);
2764 return false;
2765 }
2766
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302767 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002768 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002769 (compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADSET) ||
2770 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADPHONE))) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302771 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2772 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2773 (!is_it_true_mode && adev->native_playback_enabled)){
2774 ret = true;
2775 ALOGD("napb: time to toggle native mode");
2776 }
2777 }
2778
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302779 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302780 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2781 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002782 if(is_a2dp_out_device_type(&usecase->stream.out->device_list) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302783 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302784 ALOGD("Force a2dp device switch to update new encoder config");
2785 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002786 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302787
Florian Pfister1a84f312018-07-19 14:38:18 +02002788 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302789 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2790 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002791 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302792 return ret;
2793}
2794
Aalique Grahame22e49102018-12-18 14:23:57 -08002795static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2796{
2797 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2798}
2799
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302800bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2801{
2802 bool ret=false;
2803 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
Zhou Song5657f492019-08-07 11:30:39 +08002804 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
2805 out_snd_device == SND_DEVICE_OUT_BT_SCO_SWB) ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302806 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2807 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
Zhou Song5657f492019-08-07 11:30:39 +08002808 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302809 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
Mingshu Pang16093502020-04-20 11:21:16 +08002810 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC ||
2811 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC)
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302812 ret = true;
2813
2814 return ret;
2815}
2816
2817bool is_a2dp_device(snd_device_t out_snd_device)
2818{
2819 bool ret=false;
2820 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2821 ret = true;
2822
2823 return ret;
2824}
2825
2826bool is_bt_soc_on(struct audio_device *adev)
2827{
2828 struct mixer_ctl *ctl;
2829 char *mixer_ctl_name = "BT SOC status";
2830 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2831 bool bt_soc_status = true;
2832 if (!ctl) {
2833 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2834 __func__, mixer_ctl_name);
2835 /*This is to ensure we dont break targets which dont have the kernel change*/
2836 return true;
2837 }
2838 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2839 ALOGD("BT SOC status: %d",bt_soc_status);
2840 return bt_soc_status;
2841}
2842
Zhou Song331c8e52019-08-26 14:16:12 +08002843static int configure_btsco_sample_rate(snd_device_t snd_device)
2844{
2845 struct mixer_ctl *ctl = NULL;
2846 struct mixer_ctl *ctl_sr_rx = NULL, *ctl_sr_tx = NULL, *ctl_sr = NULL;
2847 char *rate_str = NULL;
2848 bool is_rx_dev = true;
2849
2850 if (is_btsco_device(snd_device, snd_device)) {
2851 ctl_sr_tx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate TX");
2852 ctl_sr_rx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate RX");
2853 if (!ctl_sr_tx || !ctl_sr_rx) {
2854 ctl_sr = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate");
2855 if (!ctl_sr)
2856 return -ENOSYS;
2857 }
2858
2859 switch (snd_device) {
2860 case SND_DEVICE_OUT_BT_SCO:
2861 rate_str = "KHZ_8";
2862 break;
2863 case SND_DEVICE_IN_BT_SCO_MIC_NREC:
2864 case SND_DEVICE_IN_BT_SCO_MIC:
2865 rate_str = "KHZ_8";
2866 is_rx_dev = false;
2867 break;
2868 case SND_DEVICE_OUT_BT_SCO_WB:
2869 rate_str = "KHZ_16";
2870 break;
2871 case SND_DEVICE_IN_BT_SCO_MIC_WB_NREC:
2872 case SND_DEVICE_IN_BT_SCO_MIC_WB:
2873 rate_str = "KHZ_16";
2874 is_rx_dev = false;
2875 break;
2876 default:
2877 return 0;
2878 }
2879
2880 ctl = (ctl_sr == NULL) ? (is_rx_dev ? ctl_sr_rx : ctl_sr_tx) : ctl_sr;
2881 if (mixer_ctl_set_enum_by_string(ctl, rate_str) != 0)
2882 return -ENOSYS;
2883 }
2884 return 0;
2885}
2886
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302887int out_standby_l(struct audio_stream *stream);
2888
Eric Laurent637e2d42018-11-15 12:24:31 -08002889struct stream_in *adev_get_active_input(const struct audio_device *adev)
2890{
2891 struct listnode *node;
2892 struct stream_in *last_active_in = NULL;
2893
2894 /* Get last added active input.
2895 * TODO: We may use a priority mechanism to pick highest priority active source */
2896 list_for_each(node, &adev->usecase_list)
2897 {
2898 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2899 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL)
2900 last_active_in = usecase->stream.in;
2901 }
2902
2903 return last_active_in;
2904}
2905
2906struct stream_in *get_voice_communication_input(const struct audio_device *adev)
2907{
2908 struct listnode *node;
2909
2910 /* First check active inputs with voice communication source and then
2911 * any input if audio mode is in communication */
2912 list_for_each(node, &adev->usecase_list)
2913 {
2914 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2915 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
2916 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
2917 return usecase->stream.in;
2918 }
2919 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION)
2920 return adev_get_active_input(adev);
2921
2922 return NULL;
2923}
2924
Carter Hsu2e429db2019-05-14 18:50:52 +08002925/*
2926 * Aligned with policy.h
2927 */
2928static inline int source_priority(int inputSource)
2929{
2930 switch (inputSource) {
2931 case AUDIO_SOURCE_VOICE_COMMUNICATION:
2932 return 9;
2933 case AUDIO_SOURCE_CAMCORDER:
2934 return 8;
2935 case AUDIO_SOURCE_VOICE_PERFORMANCE:
2936 return 7;
2937 case AUDIO_SOURCE_UNPROCESSED:
2938 return 6;
2939 case AUDIO_SOURCE_MIC:
2940 return 5;
2941 case AUDIO_SOURCE_ECHO_REFERENCE:
2942 return 4;
2943 case AUDIO_SOURCE_FM_TUNER:
2944 return 3;
2945 case AUDIO_SOURCE_VOICE_RECOGNITION:
2946 return 2;
2947 case AUDIO_SOURCE_HOTWORD:
2948 return 1;
2949 default:
2950 break;
2951 }
2952 return 0;
2953}
2954
2955static struct stream_in *get_priority_input(struct audio_device *adev)
2956{
2957 struct listnode *node;
2958 struct audio_usecase *usecase;
2959 int last_priority = 0, priority;
2960 struct stream_in *priority_in = NULL;
2961 struct stream_in *in;
2962
2963 list_for_each(node, &adev->usecase_list) {
2964 usecase = node_to_item(node, struct audio_usecase, list);
2965 if (usecase->type == PCM_CAPTURE) {
2966 in = usecase->stream.in;
2967 if (!in)
2968 continue;
Krishna Kishor Jha0b7175d2022-07-28 22:33:46 +05302969
2970 if (USECASE_AUDIO_RECORD_FM_VIRTUAL == usecase->id)
2971 continue;
Krishna Kishor Jhaaf83fd82022-11-15 17:54:07 +05302972#ifdef SKIP_INPUT_SOURCE_PRIORITY
2973 // temporary fix to resolve issue when accessing Google Assistant while FM is active.
2974 if (USECASE_AUDIO_RECORD_ECHO_REF_EXT == usecase->id) {
2975 continue;
2976 }
2977#endif
Carter Hsu2e429db2019-05-14 18:50:52 +08002978 priority = source_priority(in->source);
2979
2980 if (priority > last_priority) {
2981 last_priority = priority;
2982 priority_in = in;
2983 }
2984 }
2985 }
2986 return priority_in;
2987}
2988
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002989int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002990{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002991 snd_device_t out_snd_device = SND_DEVICE_NONE;
2992 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002993 struct audio_usecase *usecase = NULL;
2994 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002995 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002996 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302997 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002998 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002999 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003000
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05303001 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
3002
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003003 usecase = get_usecase_from_list(adev, uc_id);
3004 if (usecase == NULL) {
3005 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
3006 return -EINVAL;
3007 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003008
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003009 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08003010 (usecase->type == VOIP_CALL) ||
Derek Chena30a5f42019-12-03 11:17:09 -05003011 (usecase->type == PCM_HFP_CALL)||
Fei Tongaffdf732020-02-20 20:39:05 +08003012 (usecase->type == ICC_CALL) ||
3013 (usecase->type == SYNTH_LOOPBACK)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05303014 if(usecase->stream.out == NULL) {
3015 ALOGE("%s: stream.out is NULL", __func__);
3016 return -EINVAL;
3017 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003018 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS)) {
Guodong Hu267bdf82019-08-12 19:22:32 +08003019 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev,
3020 uc_id);
3021 in_snd_device = audio_extn_auto_hal_get_input_snd_device(adev,
3022 uc_id);
3023 } else {
3024 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05303025 usecase->stream.out, usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08003026 in_snd_device = platform_get_input_snd_device(adev->platform,
3027 NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05303028 &usecase->stream.out->device_list,
3029 usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08003030 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003031 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05303032 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05303033 if (usecase->stream.inout == NULL) {
3034 ALOGE("%s: stream.inout is NULL", __func__);
3035 return -EINVAL;
3036 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003037 assign_devices(&stream_out.device_list, &usecase->stream.inout->out_config.device_list);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05303038 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
3039 stream_out.format = usecase->stream.inout->out_config.format;
3040 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
Jaideep Sharma477917f2020-03-13 18:13:33 +05303041 out_snd_device = platform_get_output_snd_device(adev->platform, &stream_out, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003042 assign_devices(&usecase->device_list,
3043 &usecase->stream.inout->out_config.device_list);
Zhenlin Lian4f947842022-05-14 15:50:52 +05303044 clear_devices(&stream_out.device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05303045 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
3046 if (usecase->stream.inout == NULL) {
3047 ALOGE("%s: stream.inout is NULL", __func__);
3048 return -EINVAL;
3049 }
Manisha Agarwal03297972020-04-17 15:36:55 +05303050 struct listnode out_devices;
3051 list_init(&out_devices);
3052 in_snd_device = platform_get_input_snd_device(adev->platform, NULL,
3053 &out_devices, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003054 assign_devices(&usecase->device_list,
3055 &usecase->stream.inout->in_config.device_list);
Zhenlin Lian4f947842022-05-14 15:50:52 +05303056 clear_devices(&out_devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003057 } else {
3058 /*
3059 * If the voice call is active, use the sound devices of voice call usecase
3060 * so that it would not result any device switch. All the usecases will
3061 * be switched to new device when select_devices() is called for voice call
3062 * usecase. This is to avoid switching devices for voice call when
3063 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07003064 * choose voice call device only if the use case device is
3065 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003066 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08003067 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003068 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08003069 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003070 if ((vc_usecase) && ((is_codec_backend_out_device_type(&vc_usecase->device_list) &&
3071 is_codec_backend_out_device_type(&usecase->device_list)) ||
3072 (is_codec_backend_out_device_type(&vc_usecase->device_list) &&
3073 is_codec_backend_in_device_type(&usecase->device_list)) ||
3074 is_single_device_type_equal(&vc_usecase->device_list,
3075 AUDIO_DEVICE_OUT_HEARING_AID) ||
3076 is_single_device_type_equal(&usecase->device_list,
Robert Lee8a6aaf32019-09-20 16:40:19 +08003077 AUDIO_DEVICE_IN_VOICE_CALL) ||
3078 (is_single_device_type_equal(&usecase->device_list,
Gautam Manam8fa06162021-09-24 10:41:29 +05303079 AUDIO_DEVICE_IN_BUILTIN_MIC) &&
3080 is_single_device_type_equal(&vc_usecase->device_list,
3081 AUDIO_DEVICE_OUT_USB_HEADSET)) ||
3082 (is_single_device_type_equal(&usecase->device_list,
Robert Lee8a6aaf32019-09-20 16:40:19 +08003083 AUDIO_DEVICE_IN_USB_HEADSET) &&
3084 is_single_device_type_equal(&vc_usecase->device_list,
Kamalakar Yalasiri5edba852021-01-28 14:52:38 +05303085 AUDIO_DEVICE_OUT_USB_HEADSET))||
Gautam Manamf4002142021-09-13 22:05:56 +05303086 (is_single_device_type_equal(&usecase->device_list,
3087 AUDIO_DEVICE_IN_USB_HEADSET) &&
3088 is_codec_backend_out_device_type(&vc_usecase->device_list)) ||
Kamalakar Yalasiri5edba852021-01-28 14:52:38 +05303089 (is_single_device_type_equal(&usecase->device_list,
3090 AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) &&
3091 is_codec_backend_out_device_type(&vc_usecase->device_list)))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003092 in_snd_device = vc_usecase->in_snd_device;
3093 out_snd_device = vc_usecase->out_snd_device;
3094 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003095 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08003096 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08003097 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08003098 if ((voip_usecase != NULL) &&
3099 (usecase->type == PCM_PLAYBACK) &&
3100 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08003101 out_snd_device_backend_match = platform_check_backends_match(
3102 voip_usecase->out_snd_device,
3103 platform_get_output_snd_device(
3104 adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05303105 usecase->stream.out, usecase->type));
yidongh02ef86f2017-04-21 15:36:04 +08003106 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003107 if ((voip_usecase) && (is_codec_backend_out_device_type(&voip_usecase->device_list) &&
3108 (is_codec_backend_out_device_type(&usecase->device_list) ||
3109 is_codec_backend_in_device_type(&usecase->device_list)) &&
yidongh02ef86f2017-04-21 15:36:04 +08003110 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07003111 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003112 in_snd_device = voip_usecase->in_snd_device;
3113 out_snd_device = voip_usecase->out_snd_device;
3114 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08003115 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08003116 hfp_ucid = audio_extn_hfp_get_usecase();
3117 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003118 if ((hfp_usecase) && is_codec_backend_out_device_type(&hfp_usecase->device_list)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08003119 in_snd_device = hfp_usecase->in_snd_device;
3120 out_snd_device = hfp_usecase->out_snd_device;
3121 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003122 }
3123 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05303124 if (usecase->stream.out == NULL) {
3125 ALOGE("%s: stream.out is NULL", __func__);
3126 return -EINVAL;
3127 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003128 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003129 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003130 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003131 struct stream_out *voip_out = adev->primary_output;
3132 struct stream_in *voip_in = get_voice_communication_input(adev);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003133 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS))
Guodong Hu267bdf82019-08-12 19:22:32 +08003134 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev, uc_id);
3135 else
3136 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05303137 usecase->stream.out,
3138 usecase->type);
kunleizdcf967a2018-08-07 17:09:11 +08003139 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizdcf967a2018-08-07 17:09:11 +08003140
Eric Laurent637e2d42018-11-15 12:24:31 -08003141 if (voip_usecase)
3142 voip_out = voip_usecase->stream.out;
3143
3144 if (usecase->stream.out == voip_out && voip_in != NULL)
3145 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003146 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003147 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05303148 if (usecase->stream.in == NULL) {
3149 ALOGE("%s: stream.in is NULL", __func__);
3150 return -EINVAL;
3151 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003152 assign_devices(&usecase->device_list, &usecase->stream.in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003153 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003154 if (in_snd_device == SND_DEVICE_NONE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003155 struct listnode out_devices;
Eric Laurent637e2d42018-11-15 12:24:31 -08003156 struct stream_in *voip_in = get_voice_communication_input(adev);
Carter Hsu2e429db2019-05-14 18:50:52 +08003157 struct stream_in *priority_in = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08003158
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003159 list_init(&out_devices);
Eric Laurent637e2d42018-11-15 12:24:31 -08003160 if (voip_in != NULL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003161 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
3162 USECASE_AUDIO_PLAYBACK_VOIP);
3163
Carter Hsu2e429db2019-05-14 18:50:52 +08003164 usecase->stream.in->enable_ec_port = false;
3165
Zhou Song503196b2021-07-23 17:31:05 +08003166 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY ||
3167 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY2) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003168 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_TELEPHONY_TX, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08003169 } else if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003170 assign_devices(&out_devices, &voip_usecase->stream.out->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08003171 } else if (adev->primary_output &&
3172 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003173 assign_devices(&out_devices, &adev->primary_output->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08003174 } else {
3175 /* forcing speaker o/p device to get matching i/p pair
3176 in case o/p is not routed from same primary HAL */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003177 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08003178 }
Carter Hsu2e429db2019-05-14 18:50:52 +08003179 priority_in = voip_in;
3180 } else {
Krishna Kishor Jhaaf83fd82022-11-15 17:54:07 +05303181#ifdef SKIP_INPUT_SOURCE_PRIORITY
Kogara Naveen Kumar912313f2022-11-23 09:38:28 +05303182 ALOGD("%s: Skipping get_priority_input for use-case-id:%d(%s).", __func__, uc_id, use_case_table[uc_id]);
Krishna Kishor Jhaaf83fd82022-11-15 17:54:07 +05303183#else
Carter Hsu2e429db2019-05-14 18:50:52 +08003184 priority_in = get_priority_input(adev);
Krishna Kishor Jhaaf83fd82022-11-15 17:54:07 +05303185#endif
Carter Hsu2e429db2019-05-14 18:50:52 +08003186
Susan Wang727dd6b2021-03-26 11:28:59 -04003187 if (!priority_in ||
3188 audio_extn_auto_hal_overwrite_priority_for_auto(usecase->stream.in))
Carter Hsu2e429db2019-05-14 18:50:52 +08003189 priority_in = usecase->stream.in;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003190 }
Huicheng Liu1404ba12020-09-11 01:03:25 -04003191 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_IN_BUS)){
3192 in_snd_device = audio_extn_auto_hal_get_snd_device_for_car_audio_stream(priority_in->car_audio_stream);
3193 }
3194 else
3195 in_snd_device = platform_get_input_snd_device(adev->platform,
3196 priority_in,
3197 &out_devices,
3198 usecase->type);
Zhenlin Lian4f947842022-05-14 15:50:52 +05303199 clear_devices(&out_devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003200 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003201 }
3202 }
3203
3204 if (out_snd_device == usecase->out_snd_device &&
3205 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05303206
3207 if (!force_device_switch(usecase))
3208 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003209 }
3210
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003211 if (!compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS) &&
Guodong Hu267bdf82019-08-12 19:22:32 +08003212 ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003213 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready()))) {
Guodong Hu267bdf82019-08-12 19:22:32 +08003214 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
3215 return 0;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303216 }
3217
Aalique Grahame22e49102018-12-18 14:23:57 -08003218 if (out_snd_device != SND_DEVICE_NONE &&
3219 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
3220 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
3221 __func__,
3222 use_case_table[uc_id],
3223 adev->last_logged_snd_device[uc_id][0],
3224 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
3225 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
3226 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
3227 -1,
3228 out_snd_device,
3229 platform_get_snd_device_name(out_snd_device),
3230 platform_get_snd_device_acdb_id(out_snd_device));
3231 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
3232 }
3233 if (in_snd_device != SND_DEVICE_NONE &&
3234 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
3235 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
3236 __func__,
3237 use_case_table[uc_id],
3238 adev->last_logged_snd_device[uc_id][1],
3239 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
3240 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
3241 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
3242 -1,
3243 in_snd_device,
3244 platform_get_snd_device_name(in_snd_device),
3245 platform_get_snd_device_acdb_id(in_snd_device));
3246 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
3247 }
3248
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003249
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003250 /*
3251 * Limitation: While in call, to do a device switch we need to disable
3252 * and enable both RX and TX devices though one of them is same as current
3253 * device.
3254 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07003255 if ((usecase->type == VOICE_CALL) &&
3256 (usecase->in_snd_device != SND_DEVICE_NONE) &&
3257 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07003258 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07003259 }
3260
3261 if (((usecase->type == VOICE_CALL) ||
3262 (usecase->type == VOIP_CALL)) &&
3263 (usecase->out_snd_device != SND_DEVICE_NONE)) {
3264 /* Disable sidetone only if voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303265 if (voice_is_call_state_active_in_call(adev) ||
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07003266 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07003267 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003268
3269 /* Disable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303270 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003271 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08003272 }
3273
Aalique Grahame22e49102018-12-18 14:23:57 -08003274 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
3275 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003276 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303277 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08003278 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
3279 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
3280 else
3281 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303282 }
3283
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003284 /* Disable current sound devices */
3285 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003286 disable_audio_route(adev, usecase);
3287 disable_snd_device(adev, usecase->out_snd_device);
Gautam Manam274f4752021-09-24 10:58:49 +05303288 if (usecase->id == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
3289 disable_snd_device(adev, SND_DEVICE_OUT_HAPTICS);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003290 }
3291
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003292 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003293 disable_audio_route(adev, usecase);
3294 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003295 }
3296
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08003297 /* Applicable only on the targets that has external modem.
3298 * New device information should be sent to modem before enabling
3299 * the devices to reduce in-call device switch time.
3300 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07003301 if ((usecase->type == VOICE_CALL) &&
3302 (usecase->in_snd_device != SND_DEVICE_NONE) &&
3303 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08003304 status = platform_switch_voice_call_enable_device_config(adev->platform,
3305 out_snd_device,
3306 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07003307 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08003308
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003309 /* Enable new sound devices */
3310 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08003311 check_usecases_codec_backend(adev, usecase, out_snd_device);
Saurav Kumarc1411662020-10-14 10:50:45 +05303312 check_and_configure_headphone(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05303313 if (platform_check_codec_asrc_support(adev->platform))
3314 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003315 enable_snd_device(adev, out_snd_device);
Zhou Songd9bd9302020-08-04 16:34:45 +08003316 /* Enable haptics device for haptic usecase */
3317 if (usecase->id == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
3318 enable_snd_device(adev, SND_DEVICE_OUT_HAPTICS);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003319 }
3320
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07003321 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303322 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003323 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07003324 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003325
Lakshman Chaluvarajuab7e5572020-10-28 19:29:23 +05303326 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL)
Eric Laurentb23d5282013-05-14 15:27:20 -07003327 status = platform_switch_voice_call_device_post(adev->platform,
3328 out_snd_device,
3329 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08003330
sangwoo170731f2013-06-08 15:36:36 +09003331 usecase->in_snd_device = in_snd_device;
3332 usecase->out_snd_device = out_snd_device;
3333
Dhananjay Kumard6d32152016-10-13 16:11:03 +05303334 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
3335 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05303336 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003337 if ((24 == usecase->stream.out->bit_width) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003338 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_SPEAKER)) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003339 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3340 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
3341 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
3342 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
3343 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
3344 /*
3345 * To best utlize DSP, check if the stream sample rate is supported/multiple of
3346 * configured device sample rate, if not update the COPP rate to be equal to the
3347 * device sample rate, else open COPP at stream sample rate
3348 */
3349 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
3350 usecase->stream.out->sample_rate,
3351 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05303352 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
Preetam Singh Ranawat590d0432019-09-30 14:39:47 +05303353 out_snd_device != SND_DEVICE_OUT_HEADPHONES &&
3354 out_snd_device != SND_DEVICE_OUT_HEADPHONES_HIFI_FILTER &&
Ashish Jain4826f6c2017-02-06 13:33:20 +05303355 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003356 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
3357 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +05303358#ifdef PLATFORM_AUTO
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +05303359 if (!(compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS) && ((usecase->stream.out->flags &
3360 (audio_output_flags_t)AUDIO_OUTPUT_FLAG_SYS_NOTIFICATION) || (usecase->stream.out->flags &
Kogara Naveen Kumare88ee942022-12-22 17:01:12 +05303361 (audio_output_flags_t)AUDIO_OUTPUT_FLAG_PHONE) || (usecase->stream.out->flags &
3362 (audio_output_flags_t)AUDIO_OUTPUT_FLAG_NAV_GUIDANCE) || (usecase->stream.out->flags &
3363 (audio_output_flags_t)AUDIO_OUTPUT_FLAG_ALERTS)))) {
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +05303364 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3365 }
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +05303366#else
3367 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3368#endif
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003369 }
Weiyin Jiangcdece202019-07-08 16:13:16 +08003370 }
3371 enable_audio_route(adev, usecase);
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003372
Shalini Manjunatha5e610912020-12-29 13:02:25 +05303373 if (uc_id == USECASE_AUDIO_PLAYBACK_VOIP) {
3374 struct stream_in *voip_in = get_voice_communication_input(adev);
3375 struct audio_usecase *voip_in_usecase = NULL;
3376 voip_in_usecase = get_usecase_from_list(adev, USECASE_AUDIO_RECORD_VOIP);
3377 if (voip_in != NULL &&
3378 voip_in_usecase != NULL &&
3379 !(out_snd_device == AUDIO_DEVICE_OUT_SPEAKER ||
3380 out_snd_device == AUDIO_DEVICE_OUT_SPEAKER_SAFE) &&
3381 (voip_in_usecase->in_snd_device ==
3382 platform_get_input_snd_device(adev->platform, voip_in,
3383 &usecase->stream.out->device_list,usecase->type))) {
3384 /*
3385 * if VOIP TX is enabled before VOIP RX, needs to re-route the TX path
3386 * for enabling echo-reference-voip with correct port
3387 */
3388 ALOGD("%s: VOIP TX is enabled before VOIP RX,needs to re-route the TX path",__func__);
3389 disable_audio_route(adev, voip_in_usecase);
3390 disable_snd_device(adev, voip_in_usecase->in_snd_device);
3391 enable_snd_device(adev, voip_in_usecase->in_snd_device);
3392 enable_audio_route(adev, voip_in_usecase);
3393 }
3394 }
Ramjee Singhcdf67af2021-09-29 14:20:27 +05303395 if (voice_extn_compress_voip_is_active(adev)) {
3396 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
3397 USECASE_COMPRESS_VOIP_CALL);
3398 /*
3399 * If only compress voip input is opened voip out will be primary out.
3400 * Need to consider re-routing to select correct i/p pair
3401 */
3402 if ((voip_usecase != NULL) &&
3403 (usecase->type == PCM_PLAYBACK) &&
3404 (usecase->stream.out == voip_usecase->stream.out)) {
3405 in_snd_device = platform_get_input_snd_device(adev->platform,
3406 NULL,
3407 &usecase->stream.out->device_list,
3408 usecase->type);
3409 if (voip_usecase->in_snd_device != in_snd_device ) {
3410 ALOGD("%s:Re routing compress voip tx snd device matching voip rx pair",
3411 __func__);
3412 disable_audio_route(adev, voip_usecase);
3413 disable_snd_device(adev, voip_usecase->in_snd_device);
3414 voip_usecase->in_snd_device = in_snd_device;
3415 voip_usecase->out_snd_device = usecase->out_snd_device;
3416 /* Route all TX usecase to Compress voip BE */
3417 check_usecases_capture_codec_backend(adev, voip_usecase, in_snd_device);
3418 enable_snd_device(adev, in_snd_device);
3419 /* Send Voice related calibration for RX /TX pair */
3420 status = platform_switch_voice_call_device_post(adev->platform,
3421 out_snd_device,
3422 in_snd_device);
3423 enable_audio_route(adev, voip_usecase);
3424 }
3425 }
3426 }
Shalini Manjunatha5e610912020-12-29 13:02:25 +05303427
3428
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08003429 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08003430
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003431 /* If input stream is already running then effect needs to be
3432 applied on the new input device that's being enabled here. */
Eric Laurent637e2d42018-11-15 12:24:31 -08003433 if (in_snd_device != SND_DEVICE_NONE)
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003434 check_and_enable_effect(adev);
3435
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003436 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003437 /* Enable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303438 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003439 voice_check_and_update_aanc_path(adev, out_snd_device, true);
3440
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003441 /* Enable sidetone only if other voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303442 if (voice_is_call_state_active_in_call(adev) ||
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003443 voice_extn_compress_voip_is_started(adev))
3444 voice_set_sidetone(adev, out_snd_device, true);
3445 }
3446
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003447 /* Applicable only on the targets that has external modem.
3448 * Enable device command should be sent to modem only after
3449 * enabling voice call mixer controls
3450 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07003451 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003452 status = platform_switch_voice_call_usecase_route_post(adev->platform,
3453 out_snd_device,
3454 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303455
3456 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003457 struct stream_in *in = adev_get_active_input(adev);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303458 if (usecase->type == VOIP_CALL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003459 if (in != NULL && !in->standby) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303460 if (is_bt_soc_on(adev) == false){
3461 ALOGD("BT SCO MIC disconnected while in connection");
Eric Laurent637e2d42018-11-15 12:24:31 -08003462 if (in->pcm != NULL)
3463 pcm_stop(in->pcm);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303464 }
3465 }
3466 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
3467 && usecase->stream.out->started) {
3468 if (is_bt_soc_on(adev) == false) {
3469 ALOGD("BT SCO/A2DP disconnected while in connection");
3470 out_standby_l(&usecase->stream.out->stream.common);
3471 }
3472 }
3473 } else if ((usecase->stream.out != NULL) &&
3474 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05303475 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
3476 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Weiyin Jiang0d373242019-07-25 13:18:17 +08003477 (usecase->type != PCM_CAPTURE) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303478 usecase->stream.out->started) {
3479 if (is_bt_soc_on(adev) == false) {
3480 ALOGD("BT SCO/A2dp disconnected while in connection");
3481 out_standby_l(&usecase->stream.out->stream.common);
3482 }
3483 }
3484 }
3485
Yung Ti Su70cb8242018-06-22 17:38:47 +08003486 if (usecase->type != PCM_CAPTURE && usecase == voip_usecase) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003487 struct stream_out *voip_out = voip_usecase->stream.out;
3488 audio_extn_utils_send_app_type_gain(adev,
3489 voip_out->app_type_cfg.app_type,
3490 &voip_out->app_type_cfg.gain[0]);
3491 }
3492
Ajender Reddyb940b832021-07-07 11:51:42 +05303493 ALOGD("%s: done",__func__);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303494
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003495 return status;
3496}
3497
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003498static int stop_input_stream(struct stream_in *in)
3499{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303500 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003501 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05303502
3503 if (in == NULL) {
3504 ALOGE("%s: stream_in ptr is NULL", __func__);
3505 return -EINVAL;
3506 }
3507
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003508 struct audio_device *adev = in->dev;
Carter Hsu2e429db2019-05-14 18:50:52 +08003509 struct stream_in *priority_in = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003510
Eric Laurent994a6932013-07-17 11:51:42 -07003511 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003512 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003513 uc_info = get_usecase_from_list(adev, in->usecase);
3514 if (uc_info == NULL) {
3515 ALOGE("%s: Could not find the usecase (%d) in the list",
3516 __func__, in->usecase);
3517 return -EINVAL;
3518 }
Krishna Kishor Jhaaf83fd82022-11-15 17:54:07 +05303519#ifdef SKIP_INPUT_SOURCE_PRIORITY
3520 // Skip (1)fm-virtual-record and (2)echo-reference-external from get-priority-input logic.
3521 // See comment in function select_devices() before call to get_priority_input()
3522 if ((in->usecase == USECASE_AUDIO_RECORD_FM_VIRTUAL || in->usecase == USECASE_AUDIO_RECORD_ECHO_REF_EXT)){
3523 ALOGD("%s: Skipping get_priority_input for use-case-id:%d/%s.", __func__, in->usecase, use_case_table[in->usecase]);
3524 } else {
3525 priority_in = get_priority_input(adev);
3526 }
3527#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003528
Carter Hsu2e429db2019-05-14 18:50:52 +08003529 priority_in = get_priority_input(adev);
3530
Krishna Kishor Jhaaf83fd82022-11-15 17:54:07 +05303531#endif
3532
Derek Chenea197282019-01-07 17:35:01 -08003533 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3534 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003535
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003536 /* Close in-call recording streams */
3537 voice_check_and_stop_incall_rec_usecase(adev, in);
3538
Eric Laurent150dbfe2013-02-27 14:31:02 -08003539 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003540 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003541
3542 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003543 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003544
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003545 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303546 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_PRIMARY);
3547
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003548 list_remove(&uc_info->list);
Zhenlin Lian4f947842022-05-14 15:50:52 +05303549 clear_devices(&uc_info->device_list);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003550 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003551
Carter Hsu2e429db2019-05-14 18:50:52 +08003552 if (priority_in == in) {
3553 priority_in = get_priority_input(adev);
Sujin Panicker110f7942021-08-26 17:01:22 +05303554 if (priority_in) {
3555 if (is_usb_in_device_type(&priority_in->device_list)) {
3556 if (audio_extn_usb_connected(NULL))
3557 select_devices(adev, priority_in->usecase);
3558 } else {
3559 select_devices(adev, priority_in->usecase);
3560 }
3561 }
Carter Hsu2e429db2019-05-14 18:50:52 +08003562 }
3563
Vatsal Buchac09ae062018-11-14 13:25:08 +05303564 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07003565 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003566 return ret;
3567}
3568
3569int start_input_stream(struct stream_in *in)
3570{
3571 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08003572 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003573 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05303574
3575 if (in == NULL) {
3576 ALOGE("%s: stream_in ptr is NULL", __func__);
3577 return -EINVAL;
3578 }
3579
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003580 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07003581 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07003582 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003583
Mingming Yin2664a5b2015-09-03 10:53:11 -07003584 if (get_usecase_from_list(adev, usecase) == NULL)
3585 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303586 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
3587 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003588
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303589 if (CARD_STATUS_OFFLINE == in->card_status||
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05003590 CARD_STATUS_OFFLINE == adev->card_status ||
3591 POWER_POLICY_STATUS_OFFLINE == adev->in_power_policy) {
3592 ALOGW("in->card_status or adev->card_status or adev->input_power offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303593 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303594 goto error_config;
3595 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303596
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003597 if (is_sco_in_device_type(&in->device_list)) {
Lakshman Chaluvaraju87f53aa2021-02-02 15:50:11 +05303598 if (!adev->bt_sco_on || audio_extn_a2dp_source_is_ready()) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303599 ALOGE("%s: SCO profile is not ready, return error", __func__);
3600 ret = -EIO;
3601 goto error_config;
3602 }
3603 }
3604
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003605 /* Check if source matches incall recording usecase criteria */
3606 ret = voice_check_and_set_incall_rec_usecase(adev, in);
3607 if (ret)
3608 goto error_config;
3609 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07003610 ALOGV("%s: usecase(%d)", __func__, in->usecase);
3611
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303612 if (audio_extn_cin_attached_usecase(in))
3613 audio_extn_cin_acquire_usecase(in);
3614
Mingming Yin2664a5b2015-09-03 10:53:11 -07003615 if (get_usecase_from_list(adev, in->usecase) != NULL) {
3616 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
3617 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Weiyin Jiang38c0e612020-09-10 16:10:51 +08003618 ret = -EINVAL;
3619 goto error_config;
Mingming Yin2664a5b2015-09-03 10:53:11 -07003620 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003621
Eric Laurentb23d5282013-05-14 15:27:20 -07003622 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003623 if (in->pcm_device_id < 0) {
3624 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
3625 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08003626 ret = -EINVAL;
3627 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003628 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003629
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003630 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003631
3632 if (!uc_info) {
3633 ret = -ENOMEM;
3634 goto error_config;
3635 }
3636
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003637 uc_info->id = in->usecase;
3638 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003639 uc_info->stream.in = in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003640 list_init(&uc_info->device_list);
3641 assign_devices(&uc_info->device_list, &in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003642 uc_info->in_snd_device = SND_DEVICE_NONE;
3643 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003644
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003645 list_add_tail(&adev->usecase_list, &uc_info->list);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003646 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303647 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3648 adev->perf_lock_opts,
3649 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003650 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003651
Derek Chenea197282019-01-07 17:35:01 -08003652 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3653 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003654
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05303655 android_atomic_acquire_cas(true, false, &(in->capture_stopped));
3656
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303657 if (audio_extn_cin_attached_usecase(in)) {
Manish Dewangan46e07982018-12-13 18:18:59 +05303658 ret = audio_extn_cin_open_input_stream(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303659 if (ret)
3660 goto error_open;
3661 else
3662 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003663 }
3664
Haynes Mathew George16081042017-05-31 17:16:49 -07003665 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003666 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003667 ALOGE("%s: pcm stream not ready", __func__);
3668 goto error_open;
3669 }
3670 ret = pcm_start(in->pcm);
3671 if (ret < 0) {
3672 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3673 goto error_open;
3674 }
3675 } else {
3676 unsigned int flags = PCM_IN | PCM_MONOTONIC;
3677 unsigned int pcm_open_retry_count = 0;
3678
Zhou Song62ea0282020-03-22 19:53:01 +08003679 if ((in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) ||
3680 (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003681 flags |= PCM_MMAP | PCM_NOIRQ;
3682 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
3683 } else if (in->realtime) {
3684 flags |= PCM_MMAP | PCM_NOIRQ;
3685 }
3686
Garmond Leunge2433c32017-09-28 21:51:22 -07003687 if (audio_extn_ffv_get_stream() == in) {
3688 ALOGD("%s: ffv stream, update pcm config", __func__);
3689 audio_extn_ffv_update_pcm_config(&config);
3690 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003691 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3692 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3693
3694 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003695 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07003696 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07003697 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003698 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303699 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303700 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3701 adev->card_status = CARD_STATUS_OFFLINE;
3702 in->card_status = CARD_STATUS_OFFLINE;
3703 ret = -EIO;
3704 goto error_open;
3705 }
3706
Haynes Mathew George16081042017-05-31 17:16:49 -07003707 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3708 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3709 if (in->pcm != NULL) {
3710 pcm_close(in->pcm);
3711 in->pcm = NULL;
3712 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003713 if (pcm_open_retry_count == 0) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003714 ret = -EIO;
3715 goto error_open;
3716 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003717 pcm_open_retry_count--;
Haynes Mathew George16081042017-05-31 17:16:49 -07003718 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3719 continue;
3720 }
3721 break;
3722 }
3723
3724 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003725 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07003726 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003727 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003728 if (ret < 0) {
3729 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3730 pcm_close(in->pcm);
3731 in->pcm = NULL;
3732 goto error_open;
3733 }
Vaibhav Raut5f3bf222023-02-06 17:45:22 +05303734 if (in->flags & (AUDIO_INPUT_FLAG_FAST | AUDIO_INPUT_FLAG_RAW))
Narsinga Rao Chellaa6e1f702021-10-22 13:57:32 +05303735 register_in_stream(in);
Haynes Mathew George16081042017-05-31 17:16:49 -07003736 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003737 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07003738 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003739 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003740 if (ret < 0) {
3741 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003742 pcm_close(in->pcm);
3743 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003744 goto error_open;
3745 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003746 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003747 }
3748
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003749 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07003750 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
3751 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003752
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003753 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303754 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
3755
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303756done_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003757 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303758 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Manisha Agarwal4c2402e2020-10-21 12:02:57 +05303759 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303760 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003761 return ret;
3762
3763error_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003764 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303765 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003766 stop_input_stream(in);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003767
Eric Laurentc8400632013-02-14 19:04:54 -08003768error_config:
Weiyin Jiang38c0e612020-09-10 16:10:51 +08003769 if (audio_extn_cin_attached_usecase(in))
3770 audio_extn_cin_close_input_stream(in);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303771 /*
3772 * sleep 50ms to allow sufficient time for kernel
3773 * drivers to recover incases like SSR.
3774 */
3775 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003776 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303777 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003778 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003779}
3780
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003781void lock_input_stream(struct stream_in *in)
3782{
3783 pthread_mutex_lock(&in->pre_lock);
3784 pthread_mutex_lock(&in->lock);
3785 pthread_mutex_unlock(&in->pre_lock);
3786}
3787
3788void lock_output_stream(struct stream_out *out)
3789{
3790 pthread_mutex_lock(&out->pre_lock);
3791 pthread_mutex_lock(&out->lock);
3792 pthread_mutex_unlock(&out->pre_lock);
3793}
3794
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003795/* must be called with out->lock locked */
3796static int send_offload_cmd_l(struct stream_out* out, int command)
3797{
3798 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
3799
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003800 if (!cmd) {
3801 ALOGE("failed to allocate mem for command 0x%x", command);
3802 return -ENOMEM;
3803 }
3804
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003805 ALOGVV("%s %d", __func__, command);
3806
3807 cmd->cmd = command;
3808 list_add_tail(&out->offload_cmd_list, &cmd->node);
3809 pthread_cond_signal(&out->offload_cond);
3810 return 0;
3811}
3812
Gautam Manam14c198b2020-12-24 14:08:04 +05303813/* must be called with out->lock */
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003814static void stop_compressed_output_l(struct stream_out *out)
3815{
Gautam Manam14c198b2020-12-24 14:08:04 +05303816 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003817 out->offload_state = OFFLOAD_STATE_IDLE;
Gautam Manam14c198b2020-12-24 14:08:04 +05303818 pthread_mutex_unlock(&out->latch_lock);
Weiyin Jiang906db3c2021-03-02 13:17:04 +08003819
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003820 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003821 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003822 if (out->compr != NULL) {
3823 compress_stop(out->compr);
3824 while (out->offload_thread_blocked) {
3825 pthread_cond_wait(&out->cond, &out->lock);
3826 }
3827 }
3828}
3829
Varun Balaraje49253e2017-07-06 19:48:56 +05303830bool is_interactive_usecase(audio_usecase_t uc_id)
3831{
3832 unsigned int i;
3833 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
3834 if (uc_id == interactive_usecases[i])
3835 return true;
3836 }
3837 return false;
3838}
3839
3840static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
3841{
3842 audio_usecase_t ret_uc = USECASE_INVALID;
3843 unsigned int intract_uc_index;
3844 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3845
3846 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
3847 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
3848 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
3849 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
3850 ret_uc = interactive_usecases[intract_uc_index];
3851 break;
3852 }
3853 }
3854
3855 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
3856 return ret_uc;
3857}
3858
3859static void free_interactive_usecase(struct audio_device *adev,
3860 audio_usecase_t uc_id)
3861{
3862 unsigned int interact_uc_index;
3863 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3864
3865 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
3866 if (interactive_usecases[interact_uc_index] == uc_id) {
3867 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
3868 break;
3869 }
3870 }
3871 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
3872}
3873
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003874bool is_offload_usecase(audio_usecase_t uc_id)
3875{
3876 unsigned int i;
3877 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
3878 if (uc_id == offload_usecases[i])
3879 return true;
3880 }
3881 return false;
3882}
3883
Dhananjay Kumarac341582017-02-23 23:42:25 +05303884static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003885{
vivek mehta446c3962015-09-14 10:57:35 -07003886 audio_usecase_t ret_uc = USECASE_INVALID;
3887 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003888 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003889 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05303890 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07003891 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
3892 else
3893 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003894
vivek mehta446c3962015-09-14 10:57:35 -07003895 pthread_mutex_lock(&adev->lock);
3896 if (get_usecase_from_list(adev, ret_uc) != NULL)
3897 ret_uc = USECASE_INVALID;
3898 pthread_mutex_unlock(&adev->lock);
3899
3900 return ret_uc;
3901 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003902
3903 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003904 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3905 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3906 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3907 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003908 break;
3909 }
3910 }
vivek mehta446c3962015-09-14 10:57:35 -07003911
3912 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3913 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003914}
3915
3916static void free_offload_usecase(struct audio_device *adev,
3917 audio_usecase_t uc_id)
3918{
vivek mehta446c3962015-09-14 10:57:35 -07003919 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003920 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003921
3922 if (!adev->multi_offload_enable)
3923 return;
3924
3925 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3926 if (offload_usecases[offload_uc_index] == uc_id) {
3927 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003928 break;
3929 }
3930 }
3931 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3932}
3933
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003934static void *offload_thread_loop(void *context)
3935{
3936 struct stream_out *out = (struct stream_out *) context;
3937 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003938 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003939
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003940 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08003941 set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003942 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3943
3944 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003945 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003946 out->offload_state = OFFLOAD_STATE_IDLE;
3947 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003948 for (;;) {
3949 struct offload_cmd *cmd = NULL;
3950 stream_callback_event_t event;
3951 bool send_callback = false;
3952
3953 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3954 __func__, list_empty(&out->offload_cmd_list),
3955 out->offload_state);
3956 if (list_empty(&out->offload_cmd_list)) {
3957 ALOGV("%s SLEEPING", __func__);
3958 pthread_cond_wait(&out->offload_cond, &out->lock);
3959 ALOGV("%s RUNNING", __func__);
3960 continue;
3961 }
3962
3963 item = list_head(&out->offload_cmd_list);
3964 cmd = node_to_item(item, struct offload_cmd, node);
3965 list_remove(item);
3966
3967 ALOGVV("%s STATE %d CMD %d out->compr %p",
3968 __func__, out->offload_state, cmd->cmd, out->compr);
3969
3970 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3971 free(cmd);
3972 break;
3973 }
3974
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003975 // allow OFFLOAD_CMD_ERROR reporting during standby
3976 // this is needed to handle failures during compress_open
3977 // Note however that on a pause timeout, the stream is closed
3978 // and no offload usecase will be active. Therefore this
3979 // special case is needed for compress_open failures alone
3980 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3981 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003982 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003983 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003984 pthread_cond_signal(&out->cond);
3985 continue;
3986 }
3987 out->offload_thread_blocked = true;
3988 pthread_mutex_unlock(&out->lock);
3989 send_callback = false;
3990 switch(cmd->cmd) {
3991 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003992 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003993 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003994 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003995 send_callback = true;
3996 event = STREAM_CBK_EVENT_WRITE_READY;
3997 break;
3998 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003999 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05304000 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004001 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05304002 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004003 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05304004 if (ret < 0)
4005 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05304006 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05304007 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08004008 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08004009 else
4010 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08004011 if (-ENETRESET != ret && !(-EINTR == ret &&
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05004012 (CARD_STATUS_OFFLINE == out->card_status ||
4013 POWER_POLICY_STATUS_OFFLINE == adev->out_power_policy))) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05304014 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304015 pthread_mutex_lock(&out->lock);
4016 out->send_new_metadata = 1;
4017 out->send_next_track_params = true;
4018 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05304019 event = STREAM_CBK_EVENT_DRAIN_READY;
4020 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
4021 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304022 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004023 break;
4024 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004025 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08004026 ret = compress_drain(out->compr);
4027 ALOGD("copl(%p):out of compress_drain", out);
4028 // EINTR check avoids drain interruption due to SSR
4029 if (-ENETRESET != ret && !(-EINTR == ret &&
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05004030 (CARD_STATUS_OFFLINE == out->card_status ||
4031 POWER_POLICY_STATUS_OFFLINE == adev->out_power_policy))) {
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08004032 send_callback = true;
4033 event = STREAM_CBK_EVENT_DRAIN_READY;
4034 } else
4035 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004036 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304037 case OFFLOAD_CMD_ERROR:
4038 ALOGD("copl(%p): sending error callback to AF", out);
4039 send_callback = true;
4040 event = STREAM_CBK_EVENT_ERROR;
4041 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004042 default:
4043 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
4044 break;
4045 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004046 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004047 out->offload_thread_blocked = false;
4048 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004049 if (send_callback && out->client_callback) {
4050 ALOGVV("%s: sending client_callback event %d", __func__, event);
4051 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07004052 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004053 free(cmd);
4054 }
4055
4056 pthread_cond_signal(&out->cond);
4057 while (!list_empty(&out->offload_cmd_list)) {
4058 item = list_head(&out->offload_cmd_list);
4059 list_remove(item);
4060 free(node_to_item(item, struct offload_cmd, node));
4061 }
4062 pthread_mutex_unlock(&out->lock);
4063
4064 return NULL;
4065}
4066
4067static int create_offload_callback_thread(struct stream_out *out)
4068{
4069 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
4070 list_init(&out->offload_cmd_list);
4071 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
4072 offload_thread_loop, out);
4073 return 0;
4074}
4075
4076static int destroy_offload_callback_thread(struct stream_out *out)
4077{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004078 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004079 stop_compressed_output_l(out);
4080 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
4081
4082 pthread_mutex_unlock(&out->lock);
4083 pthread_join(out->offload_thread, (void **) NULL);
4084 pthread_cond_destroy(&out->offload_cond);
4085
4086 return 0;
4087}
4088
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004089static int stop_output_stream(struct stream_out *out)
4090{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304091 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004092 struct audio_usecase *uc_info;
4093 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08004094 bool has_voip_usecase =
4095 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004096
Eric Laurent994a6932013-07-17 11:51:42 -07004097 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004098 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004099 uc_info = get_usecase_from_list(adev, out->usecase);
4100 if (uc_info == NULL) {
4101 ALOGE("%s: Could not find the usecase (%d) in the list",
4102 __func__, out->usecase);
4103 return -EINVAL;
4104 }
4105
Zhou Songbaddf9f2020-11-20 13:57:39 +08004106 out->a2dp_muted = false;
4107
Derek Chenea197282019-01-07 17:35:01 -08004108 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
4109 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08004110
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004111 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304112 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004113 if (adev->visualizer_stop_output != NULL)
4114 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004115
4116 audio_extn_dts_remove_state_notifier_node(out->usecase);
4117
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004118 if (adev->offload_effects_stop_output != NULL)
4119 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07004120 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
4121 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4122 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004123 }
Eric Laurentc4aef752013-09-12 17:45:53 -07004124
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004125 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
4126 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07004127 voice_set_device_mute_flag(adev, false);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004128 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07004129
Eric Laurent150dbfe2013-02-27 14:31:02 -08004130 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07004131 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004132
4133 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07004134 disable_snd_device(adev, uc_info->out_snd_device);
Zhou Songd9bd9302020-08-04 16:34:45 +08004135 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
4136 disable_snd_device(adev, SND_DEVICE_OUT_HAPTICS);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004137
Aalique Grahame22e49102018-12-18 14:23:57 -08004138 audio_extn_extspk_update(adev->extspk);
4139
Xiaojun Sang785b5da2017-08-03 15:52:29 +08004140 if (is_offload_usecase(out->usecase)) {
4141 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
4142 adev->dsp_bit_width_enforce_mode,
4143 false);
4144 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004145 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07004146 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
4147 false);
4148
4149 if (ret != 0)
4150 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
4151 /* default service interval was successfully updated,
4152 reopen USB backend with new service interval */
4153 ret = 0;
4154 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08004155
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004156 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304157 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004158 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304159 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004160 ALOGV("Disable passthrough , reset mixer to pcm");
4161 /* NO_PASSTHROUGH */
Meng Wang4c32fb42020-01-16 17:57:11 +08004162#ifdef AUDIO_GKI_ENABLED
4163 /* out->compr_config.codec->reserved[0] is for compr_passthr */
4164 out->compr_config.codec->reserved[0] = 0;
4165#else
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004166 out->compr_config.codec->compr_passthr = 0;
Meng Wang4c32fb42020-01-16 17:57:11 +08004167#endif
Mingming Yin21854652016-04-13 11:54:02 -07004168 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004169 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
4170 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07004171
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304172 /* Must be called after removing the usecase from list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004173 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL))
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05304174 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304175
Manish Dewangan21a850a2017-08-14 12:03:55 +05304176 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07004177 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
4178 if (ret < 0)
4179 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
4180 }
4181
Zhou Song642ec432020-12-23 16:11:10 +08004182 /* trigger voip input to reroute when voip output changes to hearing aid */
Aalique Grahame22e49102018-12-18 14:23:57 -08004183 if (has_voip_usecase ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004184 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08004185 struct listnode *node;
4186 struct audio_usecase *usecase;
4187 list_for_each(node, &adev->usecase_list) {
4188 usecase = node_to_item(node, struct audio_usecase, list);
Zhou Song642ec432020-12-23 16:11:10 +08004189 if (usecase->type == PCM_PLAYBACK || usecase == uc_info ||
4190 (usecase->type == PCM_CAPTURE &&
Revathi Uddarajud9f23d92020-07-27 10:55:06 +05304191 usecase->id != USECASE_AUDIO_RECORD_VOIP &&
Zhou Song642ec432020-12-23 16:11:10 +08004192 usecase->id != USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY))
Aalique Grahame22e49102018-12-18 14:23:57 -08004193 continue;
4194
4195 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
4196 __func__, usecase->id, use_case_table[usecase->id],
4197 out->usecase, use_case_table[out->usecase]);
4198 select_devices(adev, usecase->id);
4199 }
4200 }
4201
Zhenlin Lian4f947842022-05-14 15:50:52 +05304202 clear_devices(&uc_info->device_list);
Garmond Leung5fd0b552018-04-17 11:56:12 -07004203 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07004204 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004205 return ret;
4206}
4207
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004208struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
4209 unsigned int flags, unsigned int pcm_open_retry_count,
4210 struct pcm_config *config)
4211{
4212 struct pcm* pcm = NULL;
4213
4214 while (1) {
4215 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
4216 if (pcm == NULL || !pcm_is_ready(pcm)) {
4217 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
4218 if (pcm != NULL) {
4219 pcm_close(pcm);
4220 pcm = NULL;
4221 }
Weiyin Jiang72197252019-10-09 11:49:32 +08004222 if (pcm_open_retry_count == 0)
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004223 return NULL;
4224
Weiyin Jiang72197252019-10-09 11:49:32 +08004225 pcm_open_retry_count--;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004226 usleep(PROXY_OPEN_WAIT_TIME * 1000);
4227 continue;
4228 }
4229 break;
4230 }
4231
4232 if (pcm_is_ready(pcm)) {
4233 int ret = pcm_prepare(pcm);
4234 if (ret < 0) {
4235 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
4236 pcm_close(pcm);
4237 pcm = NULL;
4238 }
4239 }
4240
4241 return pcm;
4242}
4243
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004244int start_output_stream(struct stream_out *out)
4245{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004246 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004247 struct audio_usecase *uc_info;
4248 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004249 char mixer_ctl_name[128];
4250 struct mixer_ctl *ctl = NULL;
4251 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304252 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004253 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004254
Haynes Mathew George380745d2017-10-04 15:27:45 -07004255 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004256 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
4257 ret = -EINVAL;
4258 goto error_config;
4259 }
4260
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004261 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304262 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004263 get_device_types(&out->device_list), is_haptic_usecase);
4264
4265 bool is_speaker_active = compare_device_type(&out->device_list,
4266 AUDIO_DEVICE_OUT_SPEAKER);
4267 bool is_speaker_safe_active = compare_device_type(&out->device_list,
4268 AUDIO_DEVICE_OUT_SPEAKER_SAFE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304269
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304270 if (CARD_STATUS_OFFLINE == out->card_status ||
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05004271 CARD_STATUS_OFFLINE == adev->card_status ||
4272 POWER_POLICY_STATUS_OFFLINE == adev->out_power_policy) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304273 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05304274 ret = -EIO;
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004275 goto error_fatal;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304276 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05304277
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004278 //Update incall music usecase to reflect correct voice session
4279 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
4280 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
4281 if (ret != 0) {
4282 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
4283 __func__, ret);
4284 goto error_config;
4285 }
4286 }
4287
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004288 if (is_a2dp_out_device_type(&out->device_list)) {
Florian Pfister1a84f312018-07-19 14:38:18 +02004289 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004290 if (is_speaker_active || is_speaker_safe_active) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304291 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304292 } else {
Zhou Songd01e7a22020-09-23 22:49:01 +08004293 if (!is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304294 ALOGE("%s: A2DP profile is not ready, return error", __func__);
4295 ret = -EAGAIN;
4296 goto error_config;
4297 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304298 }
4299 }
4300 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004301 if (is_sco_out_device_type(&out->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304302 if (!adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004303 if (is_speaker_active) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304304 //combo usecase just by pass a2dp
4305 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004306 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304307 } else {
4308 ALOGE("%s: SCO profile is not ready, return error", __func__);
4309 ret = -EAGAIN;
4310 goto error_config;
4311 }
4312 }
4313 }
4314
Eric Laurentb23d5282013-05-14 15:27:20 -07004315 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004316 if (out->pcm_device_id < 0) {
4317 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
4318 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004319 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004320 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004321 }
4322
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004323 if (is_haptic_usecase) {
Meng Wang51d8c2a2020-04-27 15:23:21 +08004324 adev->haptic_pcm_device_id = platform_get_pcm_device_id(
4325 USECASE_AUDIO_PLAYBACK_HAPTICS, PCM_PLAYBACK);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004326 if (adev->haptic_pcm_device_id < 0) {
4327 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
4328 __func__, adev->haptic_pcm_device_id, out->usecase);
4329 ret = -EINVAL;
4330 goto error_config;
4331 }
4332 }
4333
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004334 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004335
4336 if (!uc_info) {
4337 ret = -ENOMEM;
4338 goto error_config;
4339 }
4340
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004341 uc_info->id = out->usecase;
4342 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004343 uc_info->stream.out = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004344 list_init(&uc_info->device_list);
4345 assign_devices(&uc_info->device_list, &out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004346 uc_info->in_snd_device = SND_DEVICE_NONE;
4347 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07004348
4349 /* This must be called before adding this usecase to the list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004350 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07004351 audio_extn_usb_check_and_set_svc_int(uc_info, true);
4352 /* USB backend is not reopened immediately.
4353 This is eventually done as part of select_devices */
4354 }
4355
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004356 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004357
Wei Wangf7ca6c92017-11-21 14:51:20 -08004358 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304359 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4360 adev->perf_lock_opts,
4361 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304362
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004363 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05304364 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304365 if (audio_extn_passthru_is_enabled() &&
4366 audio_extn_passthru_is_passthrough_stream(out)) {
4367 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304368 }
4369 }
4370
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004371 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02004372 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304373 if (!a2dp_combo) {
4374 check_a2dp_restore_l(adev, out, false);
4375 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004376 struct listnode dev;
4377 list_init(&dev);
4378 assign_devices(&dev, &out->device_list);
4379 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4380 reassign_device_list(&out->device_list,
4381 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aalique Grahame22e49102018-12-18 14:23:57 -08004382 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004383 reassign_device_list(&out->device_list,
4384 AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304385 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004386 assign_devices(&out->device_list, &dev);
Zhenlin Lian4f947842022-05-14 15:50:52 +05304387 clear_devices(&dev);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304388 }
4389 } else {
Revathi Uddarajub26e3932020-06-10 14:51:02 +05304390 select_devices(adev, out->usecase);
4391 if (is_a2dp_out_device_type(&out->device_list) &&
4392 !adev->a2dp_started) {
4393 if (is_speaker_active || is_speaker_safe_active) {
4394 struct listnode dev;
4395 list_init(&dev);
4396 assign_devices(&dev, &out->device_list);
4397 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4398 reassign_device_list(&out->device_list,
4399 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
4400 else
4401 reassign_device_list(&out->device_list,
4402 AUDIO_DEVICE_OUT_SPEAKER, "");
4403 select_devices(adev, out->usecase);
4404 assign_devices(&out->device_list, &dev);
Zhenlin Lian4f947842022-05-14 15:50:52 +05304405 clear_devices(&dev);
Revathi Uddarajub26e3932020-06-10 14:51:02 +05304406 } else {
4407 ret = -EINVAL;
4408 goto error_open;
4409 }
4410 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304411 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004412
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004413 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
4414 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07004415 voice_set_device_mute_flag(adev, true);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004416 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07004417
Derek Chenea197282019-01-07 17:35:01 -08004418 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
4419 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08004420
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004421 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
4422 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07004423
4424 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07004425 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07004426 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4427 ALOGE("%s: pcm stream not ready", __func__);
4428 goto error_open;
4429 }
4430 ret = pcm_start(out->pcm);
4431 if (ret < 0) {
4432 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
4433 goto error_open;
4434 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07004435 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07004436 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004437 unsigned int flags = PCM_OUT;
4438 unsigned int pcm_open_retry_count = 0;
4439 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
4440 flags |= PCM_MMAP | PCM_NOIRQ;
4441 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004442 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08004443 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004444 } else
4445 flags |= PCM_MONOTONIC;
4446
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004447 if ((adev->vr_audio_mode_enabled) &&
4448 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
4449 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4450 "PCM_Dev %d Topology", out->pcm_device_id);
4451 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4452 if (!ctl) {
4453 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
4454 __func__, mixer_ctl_name);
4455 } else {
4456 //if success use ULLPP
4457 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
4458 __func__, mixer_ctl_name, out->pcm_device_id);
4459 //There is a still a possibility that some sessions
4460 // that request for FAST|RAW when 3D audio is active
4461 //can go through ULLPP. Ideally we expects apps to
4462 //listen to audio focus and stop concurrent playback
4463 //Also, we will look for mode flag (voice_in_communication)
4464 //before enabling the realtime flag.
4465 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
4466 }
4467 }
4468
Vatsal Bucha3f39f222021-06-29 16:16:55 +05304469 platform_set_stream_channel_map(adev->platform, out->channel_mask,
4470 out->pcm_device_id, -1, &out->channel_map_param.channel_map[0]);
Surendar Karka91fa3682018-07-02 18:12:12 +05304471
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004472 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
4473 flags, pcm_open_retry_count,
4474 &(out->config));
4475 if (out->pcm == NULL) {
4476 ret = -EIO;
4477 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004478 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004479
4480 if (is_haptic_usecase) {
4481 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
4482 adev->haptic_pcm_device_id,
4483 flags, pcm_open_retry_count,
4484 &(adev->haptics_config));
4485 // failure to open haptics pcm shouldnt stop audio,
4486 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07004487
4488 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
4489 ALOGD("%s: enable haptic audio synchronization", __func__);
4490 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
4491 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004492 }
4493
Zhou Song2b8f28f2017-09-11 10:51:38 +08004494 // apply volume for voip playback after path is set up
4495 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
4496 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05304497 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
4498 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304499 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
4500 out->apply_volume = false;
Derek Chenf13dd492018-11-13 14:53:51 -08004501 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
4502 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Krishna Kishor Jha10ad39f2022-02-21 17:02:47 +05304503#ifdef SOFT_VOLUME
4504 out_set_soft_volume_params(&out->stream);
4505#endif
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304506 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004507 } else {
Zhou Song79929fe2020-01-20 17:57:43 +08004508 /*
4509 * set custom channel map if:
4510 * 1. neither mono nor stereo clips i.e. channels > 2 OR
4511 * 2. custom channel map has been set by client
4512 * else default channel map of FC/FR/FL can always be set to DSP
4513 */
4514 if (popcount(out->channel_mask) > 2 || out->channel_map_param.channel_map[0])
4515 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Weiyin Jiang810a80d2021-01-18 16:04:31 +08004516 out->pcm_device_id, -1, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08004517 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
4518 adev->dsp_bit_width_enforce_mode,
4519 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004520 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07004521 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004522 out->compr = compress_open(adev->snd_card,
4523 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004524 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004525 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05304526 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05304527 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
4528 adev->card_status = CARD_STATUS_OFFLINE;
4529 out->card_status = CARD_STATUS_OFFLINE;
4530 ret = -EIO;
4531 goto error_open;
4532 }
4533
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004534 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004535 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004536 compress_close(out->compr);
4537 out->compr = NULL;
4538 ret = -EIO;
4539 goto error_open;
4540 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304541 /* compress_open sends params of the track, so reset the flag here */
4542 out->is_compr_metadata_avail = false;
4543
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004544 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004545 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07004546
Fred Oh3f43e742015-03-04 18:42:34 -08004547 /* Since small bufs uses blocking writes, a write will be blocked
4548 for the default max poll time (20s) in the event of an SSR.
4549 Reduce the poll time to observe and deal with SSR faster.
4550 */
Ashish Jain5106d362016-05-11 19:23:33 +05304551 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08004552 compress_set_max_poll_wait(out->compr, 1000);
4553 }
4554
Manish Dewangan69426c82017-01-30 17:35:36 +05304555 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05304556 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05304557
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004558 audio_extn_dts_create_state_notifier_node(out->usecase);
4559 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4560 popcount(out->channel_mask),
4561 out->playback_started);
4562
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004563#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304564 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004565 audio_extn_dolby_send_ddp_endp_params(adev);
4566#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05304567 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
4568 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004569 if (adev->visualizer_start_output != NULL)
4570 adev->visualizer_start_output(out->handle, out->pcm_device_id);
4571 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05304572 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004573 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004574 }
Derek Chenf13dd492018-11-13 14:53:51 -08004575
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004576 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf13dd492018-11-13 14:53:51 -08004577 /* Update cached volume from media to offload/direct stream */
4578 struct listnode *node = NULL;
4579 list_for_each(node, &adev->active_outputs_list) {
4580 streams_output_ctxt_t *out_ctxt = node_to_item(node,
4581 streams_output_ctxt_t,
4582 list);
4583 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
4584 out->volume_l = out_ctxt->output->volume_l;
4585 out->volume_r = out_ctxt->output->volume_r;
4586 }
4587 }
4588 out_set_compr_volume(&out->stream,
4589 out->volume_l, out->volume_r);
4590 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004591 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004592
4593 if (ret == 0) {
Vaibhav Raut5f3bf222023-02-06 17:45:22 +05304594 if (out->flags & (AUDIO_OUTPUT_FLAG_FAST | AUDIO_OUTPUT_FLAG_RAW))
Narsinga Rao Chellaa6e1f702021-10-22 13:57:32 +05304595 register_out_stream(out);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004596 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07004597 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4598 ALOGE("%s: pcm stream not ready", __func__);
4599 goto error_open;
4600 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004601 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004602 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004603 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004604 if (ret < 0)
4605 goto error_open;
4606 }
4607 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004608 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304609 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Jaideep Sharma0fa53812020-09-17 09:00:11 +05304610 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004611
vivek mehtad15d2bf2019-05-17 13:35:10 -07004612 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
4613 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4614 audio_low_latency_hint_start();
4615 }
4616
Manish Dewangan21a850a2017-08-14 12:03:55 +05304617 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07004618 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07004619 if (ret < 0)
4620 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
4621 }
4622
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004623 // consider a scenario where on pause lower layers are tear down.
4624 // so on resume, swap mixer control need to be sent only when
4625 // backend is active, hence rather than sending from enable device
4626 // sending it from start of streamtream
4627
4628 platform_set_swap_channels(adev, true);
4629
Haynes Mathew George380745d2017-10-04 15:27:45 -07004630 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304631 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004632 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004633error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004634 if (adev->haptic_pcm) {
4635 pcm_close(adev->haptic_pcm);
4636 adev->haptic_pcm = NULL;
4637 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004638 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304639 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004640 stop_output_stream(out);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004641error_fatal:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05304642 /*
4643 * sleep 50ms to allow sufficient time for kernel
4644 * drivers to recover incases like SSR.
4645 */
4646 usleep(50000);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004647error_config:
Haynes Mathew George380745d2017-10-04 15:27:45 -07004648 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304649 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004650 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004651}
4652
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004653static int check_input_parameters(uint32_t sample_rate,
4654 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08004655 int channel_count,
4656 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004657{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004658 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004659
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304660 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
4661 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
4662 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07004663 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02004664 !audio_extn_compr_cap_format_supported(format) &&
4665 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004666 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004667
Aalique Grahame22e49102018-12-18 14:23:57 -08004668 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
4669 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
4670 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
4671 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
4672 return -EINVAL;
4673 }
4674
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004675 switch (channel_count) {
4676 case 1:
4677 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304678 case 3:
4679 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004680 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07004681 case 8:
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05304682 case 10:
4683 case 12:
4684 case 14:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004685 break;
4686 default:
4687 ret = -EINVAL;
4688 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004689
4690 switch (sample_rate) {
4691 case 8000:
4692 case 11025:
4693 case 12000:
4694 case 16000:
4695 case 22050:
4696 case 24000:
4697 case 32000:
4698 case 44100:
4699 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004700 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304701 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004702 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304703 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004704 break;
4705 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004706 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004707 }
4708
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004709 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004710}
4711
Naresh Tanniru04f71882018-06-26 17:46:22 +05304712
4713/** Add a value in a list if not already present.
4714 * @return true if value was successfully inserted or already present,
4715 * false if the list is full and does not contain the value.
4716 */
4717static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
4718 for (size_t i = 0; i < list_length; i++) {
4719 if (list[i] == value) return true; // value is already present
4720 if (list[i] == 0) { // no values in this slot
4721 list[i] = value;
4722 return true; // value inserted
4723 }
4724 }
4725 return false; // could not insert value
4726}
4727
4728/** Add channel_mask in supported_channel_masks if not already present.
4729 * @return true if channel_mask was successfully inserted or already present,
4730 * false if supported_channel_masks is full and does not contain channel_mask.
4731 */
4732static void register_channel_mask(audio_channel_mask_t channel_mask,
4733 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
4734 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
4735 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
4736}
4737
4738/** Add format in supported_formats if not already present.
4739 * @return true if format was successfully inserted or already present,
4740 * false if supported_formats is full and does not contain format.
4741 */
4742static void register_format(audio_format_t format,
4743 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
4744 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
4745 "%s: stream can not declare supporting its format %x", __func__, format);
4746}
4747/** Add sample_rate in supported_sample_rates if not already present.
4748 * @return true if sample_rate was successfully inserted or already present,
4749 * false if supported_sample_rates is full and does not contain sample_rate.
4750 */
4751static void register_sample_rate(uint32_t sample_rate,
4752 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
4753 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
4754 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
4755}
4756
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004757static inline uint32_t lcm(uint32_t num1, uint32_t num2)
4758{
4759 uint32_t high = num1, low = num2, temp = 0;
4760
4761 if (!num1 || !num2)
4762 return 0;
4763
4764 if (num1 < num2) {
4765 high = num2;
4766 low = num1;
4767 }
4768
4769 while (low != 0) {
4770 temp = low;
4771 low = high % low;
4772 high = temp;
4773 }
4774 return (num1 * num2)/high;
4775}
4776
4777static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
4778{
4779 uint32_t remainder = 0;
4780
4781 if (!multiplier)
4782 return num;
4783
4784 remainder = num % multiplier;
4785 if (remainder)
4786 num += (multiplier - remainder);
4787
4788 return num;
4789}
4790
Aalique Grahame22e49102018-12-18 14:23:57 -08004791static size_t get_stream_buffer_size(size_t duration_ms,
4792 uint32_t sample_rate,
4793 audio_format_t format,
4794 int channel_count,
4795 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004796{
4797 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004798 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004799
Aalique Grahame22e49102018-12-18 14:23:57 -08004800 size = (sample_rate * duration_ms) / 1000;
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +05304801 if (is_low_latency){
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +05304802#ifndef PLATFORM_AUTO
4803 size = configured_low_latency_capture_period_size;
4804#else
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +05304805 switch(sample_rate) {
4806 case 48000:
4807 size = 240;
4808 break;
4809 case 32000:
4810 size = 160;
4811 break;
4812 case 24000:
4813 size = 120;
4814 break;
4815 case 16000:
4816 size = 80;
4817 break;
4818 case 8000:
4819 size = 40;
4820 break;
4821 default:
4822 size = 240;
4823 }
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +05304824#endif
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +05304825 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304826
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004827 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08004828 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004829
Ralf Herzbd08d632018-09-28 15:50:49 +02004830 /* make sure the size is multiple of 32 bytes and additionally multiple of
4831 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004832 * At 48 kHz mono 16-bit PCM:
4833 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
4834 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004835 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004836 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004837 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07004838
4839 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004840}
4841
Aalique Grahame22e49102018-12-18 14:23:57 -08004842static size_t get_input_buffer_size(uint32_t sample_rate,
4843 audio_format_t format,
4844 int channel_count,
4845 bool is_low_latency)
4846{
Avinash Chandrad7296d42021-08-04 15:07:47 +05304847 bool is_usb_hifi = IS_USB_HIFI;
Aalique Grahame22e49102018-12-18 14:23:57 -08004848 /* Don't know if USB HIFI in this context so use true to be conservative */
4849 if (check_input_parameters(sample_rate, format, channel_count,
Avinash Chandrad7296d42021-08-04 15:07:47 +05304850 is_usb_hifi) != 0)
Aalique Grahame22e49102018-12-18 14:23:57 -08004851 return 0;
4852
4853 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4854 sample_rate,
4855 format,
4856 channel_count,
4857 is_low_latency);
4858}
4859
Derek Chenf6318be2017-06-12 17:16:24 -04004860size_t get_output_period_size(uint32_t sample_rate,
4861 audio_format_t format,
4862 int channel_count,
4863 int duration /*in millisecs*/)
Ashish Jain058165c2016-09-28 23:18:48 +05304864{
4865 size_t size = 0;
4866 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
4867
4868 if ((duration == 0) || (sample_rate == 0) ||
4869 (bytes_per_sample == 0) || (channel_count == 0)) {
4870 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
4871 bytes_per_sample, channel_count);
4872 return -EINVAL;
4873 }
4874
4875 size = (sample_rate *
4876 duration *
4877 bytes_per_sample *
4878 channel_count) / 1000;
4879 /*
4880 * To have same PCM samples for all channels, the buffer size requires to
4881 * be multiple of (number of channels * bytes per sample)
4882 * For writes to succeed, the buffer must be written at address which is multiple of 32
4883 */
4884 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
4885
4886 return (size/(channel_count * bytes_per_sample));
4887}
4888
Zhou Song48453a02018-01-10 17:50:59 +08004889static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05304890{
4891 uint64_t actual_frames_rendered = 0;
Weiyin Jiang4813da12020-05-28 00:37:28 +08004892 uint64_t written_frames = 0;
4893 uint64_t kernel_frames = 0;
4894 uint64_t dsp_frames = 0;
4895 uint64_t signed_frames = 0;
4896 size_t kernel_buffer_size = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304897
4898 /* This adjustment accounts for buffering after app processor.
4899 * It is based on estimated DSP latency per use case, rather than exact.
4900 */
George Gao9ba8a142020-07-23 14:30:03 -07004901 dsp_frames = platform_render_latency(out) *
Weiyin Jiang4813da12020-05-28 00:37:28 +08004902 out->sample_rate / 1000000LL;
Ashish Jain5106d362016-05-11 19:23:33 +05304903
Zhou Song48453a02018-01-10 17:50:59 +08004904 pthread_mutex_lock(&out->position_query_lock);
Weiyin Jiang4813da12020-05-28 00:37:28 +08004905 written_frames = out->written /
4906 (audio_bytes_per_sample(out->hal_ip_format) * popcount(out->channel_mask));
4907
Ashish Jain5106d362016-05-11 19:23:33 +05304908 /* not querying actual state of buffering in kernel as it would involve an ioctl call
4909 * which then needs protection, this causes delay in TS query for pcm_offload usecase
4910 * hence only estimate.
4911 */
Weiyin Jiang4813da12020-05-28 00:37:28 +08004912 kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
4913 kernel_frames = kernel_buffer_size /
4914 (audio_bytes_per_sample(out->hal_op_format) * popcount(out->channel_mask));
Ashish Jain5106d362016-05-11 19:23:33 +05304915
Weiyin Jiang4813da12020-05-28 00:37:28 +08004916 if (written_frames >= (kernel_frames + dsp_frames))
4917 signed_frames = written_frames - kernel_frames - dsp_frames;
Ashish Jain5106d362016-05-11 19:23:33 +05304918
Zhou Song48453a02018-01-10 17:50:59 +08004919 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05304920 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08004921 if (timestamp != NULL )
4922 *timestamp = out->writeAt;
4923 } else if (timestamp != NULL) {
4924 clock_gettime(CLOCK_MONOTONIC, timestamp);
4925 }
4926 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304927
Weiyin Jiang4813da12020-05-28 00:37:28 +08004928 ALOGVV("%s signed frames %lld written frames %lld kernel frames %lld dsp frames %lld",
4929 __func__, signed_frames, written_frames, kernel_frames, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05304930
4931 return actual_frames_rendered;
4932}
4933
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004934static uint32_t out_get_sample_rate(const struct audio_stream *stream)
4935{
4936 struct stream_out *out = (struct stream_out *)stream;
4937
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004938 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004939}
4940
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004941static int out_set_sample_rate(struct audio_stream *stream __unused,
4942 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004943{
4944 return -ENOSYS;
4945}
4946
4947static size_t out_get_buffer_size(const struct audio_stream *stream)
4948{
4949 struct stream_out *out = (struct stream_out *)stream;
4950
Varun Balaraje49253e2017-07-06 19:48:56 +05304951 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05304952 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05304953 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304954 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4955 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
4956 else
4957 return out->compr_config.fragment_size;
4958 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004959 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304960 else if (is_offload_usecase(out->usecase) &&
4961 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304962 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004963
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004964 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004965 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004966}
4967
4968static uint32_t out_get_channels(const struct audio_stream *stream)
4969{
4970 struct stream_out *out = (struct stream_out *)stream;
4971
4972 return out->channel_mask;
4973}
4974
4975static audio_format_t out_get_format(const struct audio_stream *stream)
4976{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004977 struct stream_out *out = (struct stream_out *)stream;
4978
4979 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004980}
4981
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004982static int out_set_format(struct audio_stream *stream __unused,
4983 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004984{
4985 return -ENOSYS;
4986}
4987
4988static int out_standby(struct audio_stream *stream)
4989{
4990 struct stream_out *out = (struct stream_out *)stream;
4991 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07004992 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004993
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304994 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4995 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004996
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004997 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004998 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004999 if (adev->adm_deregister_stream)
5000 adev->adm_deregister_stream(adev->adm_data, out->handle);
5001
Weiyin Jiang280ea742020-09-08 20:28:22 +08005002 if (is_offload_usecase(out->usecase)) {
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07005003 stop_compressed_output_l(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08005004 }
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07005005
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08005006 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005007 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08005008 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
5009 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305010 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08005011 pthread_mutex_unlock(&adev->lock);
5012 pthread_mutex_unlock(&out->lock);
5013 ALOGD("VOIP output entered standby");
5014 return 0;
5015 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005016 if (out->pcm) {
5017 pcm_close(out->pcm);
5018 out->pcm = NULL;
5019 }
Meng Wanga09da002020-04-20 12:56:04 +08005020 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
5021 if (adev->haptic_pcm) {
5022 pcm_close(adev->haptic_pcm);
5023 adev->haptic_pcm = NULL;
5024 }
5025
5026 if (adev->haptic_buffer != NULL) {
5027 free(adev->haptic_buffer);
5028 adev->haptic_buffer = NULL;
5029 adev->haptic_buffer_size = 0;
5030 }
5031 adev->haptic_pcm_device_id = 0;
5032 }
5033
Haynes Mathew George16081042017-05-31 17:16:49 -07005034 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5035 do_stop = out->playback_started;
5036 out->playback_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07005037
5038 if (out->mmap_shared_memory_fd >= 0) {
5039 ALOGV("%s: closing mmap_shared_memory_fd = %d",
5040 __func__, out->mmap_shared_memory_fd);
5041 close(out->mmap_shared_memory_fd);
5042 out->mmap_shared_memory_fd = -1;
5043 }
Haynes Mathew George16081042017-05-31 17:16:49 -07005044 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005045 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005046 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305047 out->send_next_track_params = false;
5048 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005049 out->gapless_mdata.encoder_delay = 0;
5050 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005051 if (out->compr != NULL) {
5052 compress_close(out->compr);
5053 out->compr = NULL;
5054 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08005055 }
Haynes Mathew George16081042017-05-31 17:16:49 -07005056 if (do_stop) {
5057 stop_output_stream(out);
5058 }
Lakshman Chaluvaraju06677b42019-06-24 10:04:52 +05305059 // if fm is active route on selected device in UI
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005060 audio_extn_fm_route_on_selected_device(adev, &out->device_list);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005061 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005062 }
5063 pthread_mutex_unlock(&out->lock);
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07005064 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005065 return 0;
5066}
5067
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305068static int out_on_error(struct audio_stream *stream)
5069{
5070 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07005071 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305072
5073 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08005074 // always send CMD_ERROR for offload streams, this
5075 // is needed e.g. when SSR happens within compress_open
5076 // since the stream is active, offload_callback_thread is also active.
5077 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
5078 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07005079 }
5080 pthread_mutex_unlock(&out->lock);
5081
5082 status = out_standby(&out->stream.common);
5083
5084 lock_output_stream(out);
5085 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08005086 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305087 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05305088
5089 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
5090 ALOGD("Setting previous card status if offline");
5091 out->prev_card_status_offline = true;
5092 }
5093
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305094 pthread_mutex_unlock(&out->lock);
5095
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07005096 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305097}
5098
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305099/*
Weiyin Jiang280ea742020-09-08 20:28:22 +08005100 * standby implementation without locks, assumes that the callee already
5101 * has taken adev and out lock.
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305102 */
5103int out_standby_l(struct audio_stream *stream)
5104{
5105 struct stream_out *out = (struct stream_out *)stream;
5106 struct audio_device *adev = out->dev;
5107
5108 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
5109 stream, out->usecase, use_case_table[out->usecase]);
5110
5111 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07005112 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305113 if (adev->adm_deregister_stream)
5114 adev->adm_deregister_stream(adev->adm_data, out->handle);
5115
Weiyin Jiang280ea742020-09-08 20:28:22 +08005116 if (is_offload_usecase(out->usecase)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305117 stop_compressed_output_l(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08005118 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305119
5120 out->standby = true;
5121 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
5122 voice_extn_compress_voip_close_output_stream(stream);
5123 out->started = 0;
5124 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07005125 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305126 return 0;
5127 } else if (!is_offload_usecase(out->usecase)) {
5128 if (out->pcm) {
5129 pcm_close(out->pcm);
5130 out->pcm = NULL;
5131 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005132 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
5133 if (adev->haptic_pcm) {
5134 pcm_close(adev->haptic_pcm);
5135 adev->haptic_pcm = NULL;
5136 }
5137
5138 if (adev->haptic_buffer != NULL) {
5139 free(adev->haptic_buffer);
5140 adev->haptic_buffer = NULL;
5141 adev->haptic_buffer_size = 0;
5142 }
5143 adev->haptic_pcm_device_id = 0;
5144 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305145 } else {
5146 ALOGD("copl(%p):standby", out);
5147 out->send_next_track_params = false;
5148 out->is_compr_metadata_avail = false;
5149 out->gapless_mdata.encoder_delay = 0;
5150 out->gapless_mdata.encoder_padding = 0;
5151 if (out->compr != NULL) {
5152 compress_close(out->compr);
5153 out->compr = NULL;
5154 }
5155 }
5156 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005157 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305158 }
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07005159 ALOGV("%s: exit", __func__);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305160 return 0;
5161}
5162
Aalique Grahame22e49102018-12-18 14:23:57 -08005163static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005164{
Aalique Grahame22e49102018-12-18 14:23:57 -08005165 struct stream_out *out = (struct stream_out *)stream;
5166
5167 // We try to get the lock for consistency,
5168 // but it isn't necessary for these variables.
5169 // If we're not in standby, we may be blocked on a write.
5170 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
5171 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
5172 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
Dechen Chai22768452021-07-30 09:29:16 +05305173#ifndef LINUX_ENABLED
Andy Hunga1f48fa2019-07-01 18:14:53 -07005174 char buffer[256]; // for statistics formatting
5175 if (!is_offload_usecase(out->usecase)) {
5176 simple_stats_to_string(&out->fifo_underruns, buffer, sizeof(buffer));
5177 dprintf(fd, " Fifo frame underruns: %s\n", buffer);
5178 }
5179
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005180 if (out->start_latency_ms.n > 0) {
5181 simple_stats_to_string(&out->start_latency_ms, buffer, sizeof(buffer));
5182 dprintf(fd, " Start latency ms: %s\n", buffer);
5183 }
Dechen Chai22768452021-07-30 09:29:16 +05305184#endif
Aalique Grahame22e49102018-12-18 14:23:57 -08005185 if (locked) {
5186 pthread_mutex_unlock(&out->lock);
5187 }
5188
Dechen Chai22768452021-07-30 09:29:16 +05305189#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -08005190 // dump error info
5191 (void)error_log_dump(
5192 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Dechen Chai22768452021-07-30 09:29:16 +05305193#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005194 return 0;
5195}
5196
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005197static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
5198{
5199 int ret = 0;
5200 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08005201
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005202 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08005203 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005204 return -EINVAL;
5205 }
5206
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05305207 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08005208
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005209 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
5210 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05305211 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005212 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005213 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
5214 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05305215 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005216 }
5217
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005218 ALOGV("%s new encoder delay %u and padding %u", __func__,
5219 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
5220
5221 return 0;
5222}
5223
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005224static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
5225{
5226 return out == adev->primary_output || out == adev->voice_tx_output;
5227}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005228
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305229// note: this call is safe only if the stream_cb is
5230// removed first in close_output_stream (as is done now).
5231static void out_snd_mon_cb(void * stream, struct str_parms * parms)
5232{
5233 if (!stream || !parms)
5234 return;
5235
5236 struct stream_out *out = (struct stream_out *)stream;
5237 struct audio_device *adev = out->dev;
5238
5239 card_status_t status;
5240 int card;
5241 if (parse_snd_card_status(parms, &card, &status) < 0)
5242 return;
5243
5244 pthread_mutex_lock(&adev->lock);
5245 bool valid_cb = (card == adev->snd_card);
5246 pthread_mutex_unlock(&adev->lock);
5247
5248 if (!valid_cb)
5249 return;
5250
5251 lock_output_stream(out);
5252 if (out->card_status != status)
5253 out->card_status = status;
5254 pthread_mutex_unlock(&out->lock);
5255
5256 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
5257 use_case_table[out->usecase],
5258 status == CARD_STATUS_OFFLINE ? "offline" : "online");
5259
Aditya Bavanari59ebed42019-02-05 17:44:57 +05305260 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305261 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05305262 if (voice_is_call_state_active(adev) &&
5263 out == adev->primary_output) {
5264 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
5265 pthread_mutex_lock(&adev->lock);
5266 voice_stop_call(adev);
5267 adev->mode = AUDIO_MODE_NORMAL;
5268 pthread_mutex_unlock(&adev->lock);
5269 }
5270 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305271 return;
5272}
5273
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005274int route_output_stream(struct stream_out *out,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005275 struct listnode *devices)
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005276{
5277 struct audio_device *adev = out->dev;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005278 int ret = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005279 struct listnode new_devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005280 bool bypass_a2dp = false;
5281 bool reconfig = false;
5282 unsigned long service_interval = 0;
5283
5284 ALOGD("%s: enter: usecase(%d: %s) devices %x",
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005285 __func__, out->usecase, use_case_table[out->usecase], get_device_types(devices));
5286
5287 list_init(&new_devices);
5288 assign_devices(&new_devices, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005289
5290 lock_output_stream(out);
5291 pthread_mutex_lock(&adev->lock);
5292
5293 /*
5294 * When HDMI cable is unplugged the music playback is paused and
5295 * the policy manager sends routing=0. But the audioflinger continues
5296 * to write data until standby time (3sec). As the HDMI core is
5297 * turned off, the write gets blocked.
5298 * Avoid this by routing audio to speaker until standby.
5299 */
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08005300 if (is_single_device_type_equal(&out->device_list,
5301 AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005302 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005303 !audio_extn_passthru_is_passthrough_stream(out) &&
5304 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005305 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005306 }
5307 /*
5308 * When A2DP is disconnected the
5309 * music playback is paused and the policy manager sends routing=0
5310 * But the audioflinger continues to write data until standby time
5311 * (3sec). As BT is turned off, the write gets blocked.
5312 * Avoid this by routing audio to speaker until standby.
5313 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005314 if (is_a2dp_out_device_type(&out->device_list) &&
5315 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005316 !audio_extn_a2dp_source_is_ready() &&
5317 !adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005318 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005319 }
5320 /*
Weiyin Jiangabedea32020-12-09 12:49:19 +08005321 * When USB headset is disconnected the music playback paused
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005322 * and the policy manager send routing=0. But if the USB is connected
5323 * back before the standby time, AFE is not closed and opened
5324 * when USB is connected back. So routing to speker will guarantee
5325 * AFE reconfiguration and AFE will be opend once USB is connected again
5326 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005327 if (is_usb_out_device_type(&out->device_list) &&
5328 list_empty(&new_devices) &&
5329 !audio_extn_usb_connected(NULL)) {
Sujin Panicker84d953a2020-11-16 17:39:54 +05305330 if (adev->mode == AUDIO_MODE_IN_CALL || adev->mode == AUDIO_MODE_IN_COMMUNICATION)
5331 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_EARPIECE, "");
5332 else
5333 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005334 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005335 /* To avoid a2dp to sco overlapping / BT device improper state
5336 * check with BT lib about a2dp streaming support before routing
5337 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005338 if (is_a2dp_out_device_type(&new_devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005339 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005340 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER) ||
5341 compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005342 //combo usecase just by pass a2dp
5343 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
5344 bypass_a2dp = true;
5345 } else {
5346 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
5347 /* update device to a2dp and don't route as BT returned error
5348 * However it is still possible a2dp routing called because
5349 * of current active device disconnection (like wired headset)
5350 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005351 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005352 pthread_mutex_unlock(&adev->lock);
5353 pthread_mutex_unlock(&out->lock);
5354 goto error;
5355 }
5356 }
5357 }
5358
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005359 // Workaround: If routing to an non existing usb device, fail gracefully
5360 // The routing request will otherwise block during 10 second
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005361 if (is_usb_out_device_type(&new_devices)) {
5362 struct str_parms *parms =
5363 str_parms_create_str(get_usb_device_address(&new_devices));
5364 if (!parms)
5365 goto error;
Weiyin Jiangabedea32020-12-09 12:49:19 +08005366 if (!audio_extn_usb_connected(NULL)) {
5367 ALOGW("%s: ignoring rerouting to non existing USB card", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005368 pthread_mutex_unlock(&adev->lock);
5369 pthread_mutex_unlock(&out->lock);
5370 str_parms_destroy(parms);
5371 ret = -ENOSYS;
5372 goto error;
5373 }
5374 str_parms_destroy(parms);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005375 }
5376
Weiyin Jiang80c8f9a2020-01-10 20:42:08 +08005377 // Workaround: If routing to an non existing hdmi device, fail gracefully
5378 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
5379 (platform_get_edid_info_v2(adev->platform,
5380 out->extconn.cs.controller,
5381 out->extconn.cs.stream) != 0)) {
5382 ALOGW("out_set_parameters() ignoring rerouting to non existing HDMI/DP");
5383 pthread_mutex_unlock(&adev->lock);
5384 pthread_mutex_unlock(&out->lock);
5385 ret = -ENOSYS;
5386 goto error;
5387 }
5388
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005389 /*
5390 * select_devices() call below switches all the usecases on the same
5391 * backend to the new device. Refer to check_usecases_codec_backend() in
5392 * the select_devices(). But how do we undo this?
5393 *
5394 * For example, music playback is active on headset (deep-buffer usecase)
5395 * and if we go to ringtones and select a ringtone, low-latency usecase
5396 * will be started on headset+speaker. As we can't enable headset+speaker
5397 * and headset devices at the same time, select_devices() switches the music
5398 * playback to headset+speaker while starting low-lateny usecase for ringtone.
5399 * So when the ringtone playback is completed, how do we undo the same?
5400 *
5401 * We are relying on the out_set_parameters() call on deep-buffer output,
5402 * once the ringtone playback is ended.
5403 * NOTE: We should not check if the current devices are same as new devices.
5404 * Because select_devices() must be called to switch back the music
5405 * playback to headset.
5406 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005407 if (!list_empty(&new_devices)) {
5408 bool same_dev = compare_devices(&out->device_list, &new_devices);
5409 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005410
5411 if (output_drives_call(adev, out)) {
5412 if (!voice_is_call_state_active(adev)) {
5413 if (adev->mode == AUDIO_MODE_IN_CALL) {
5414 adev->current_call_output = out;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005415 ret = voice_start_call(adev);
5416 }
5417 } else {
Kunlei Zhang253ad102020-10-14 16:21:28 +08005418 platform_is_volume_boost_supported_device(adev->platform, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005419 adev->current_call_output = out;
5420 voice_update_devices_for_all_voice_usecases(adev);
5421 }
5422 }
5423
Mingshu Pang971ff702020-09-09 15:28:22 +08005424 if (is_usb_out_device_type(&out->device_list)) {
5425 service_interval = audio_extn_usb_find_service_interval(false, true /*playback*/);
5426 audio_extn_usb_set_service_interval(true /*playback*/,
5427 service_interval,
5428 &reconfig);
5429 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
5430 }
5431
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005432 if (!out->standby) {
5433 if (!same_dev) {
5434 ALOGV("update routing change");
5435 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
5436 adev->perf_lock_opts,
5437 adev->perf_lock_opts_size);
5438 if (adev->adm_on_routing_change)
5439 adev->adm_on_routing_change(adev->adm_data,
5440 out->handle);
5441 }
5442 if (!bypass_a2dp) {
5443 select_devices(adev, out->usecase);
5444 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005445 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
5446 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005447 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005448 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005449 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005450 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005451 }
5452
5453 if (!same_dev) {
5454 // on device switch force swap, lower functions will make sure
5455 // to check if swap is allowed or not.
5456 platform_set_swap_channels(adev, true);
5457 audio_extn_perf_lock_release(&adev->perf_lock_handle);
5458 }
Zhou Songbaddf9f2020-11-20 13:57:39 +08005459 pthread_mutex_lock(&out->latch_lock);
5460 if (!is_a2dp_out_device_type(&out->device_list) || audio_extn_a2dp_source_is_ready()) {
5461 if (out->a2dp_muted) {
5462 out->a2dp_muted = false;
5463 if (is_offload_usecase(out->usecase))
5464 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5465 else if (out->usecase != USECASE_AUDIO_PLAYBACK_VOIP)
5466 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Weiyin Jiang280ea742020-09-08 20:28:22 +08005467 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005468 }
Zhou Songbaddf9f2020-11-20 13:57:39 +08005469 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP && !out->a2dp_muted)
5470 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
5471 pthread_mutex_unlock(&out->latch_lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005472 }
5473 }
5474
5475 pthread_mutex_unlock(&adev->lock);
5476 pthread_mutex_unlock(&out->lock);
5477
5478 /*handles device and call state changes*/
5479 audio_extn_extspk_update(adev->extspk);
5480
Revathi Uddaraju4255a632021-12-02 05:11:13 -08005481 clear_devices(&new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005482error:
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005483 ALOGV("%s: exit: code(%d)", __func__, ret);
5484 return ret;
5485}
5486
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005487static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
5488{
5489 struct stream_out *out = (struct stream_out *)stream;
5490 struct audio_device *adev = out->dev;
5491 struct str_parms *parms;
5492 char value[32];
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005493 int ret = 0, err;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005494 int ext_controller = -1;
5495 int ext_stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005496
sangwoobc677242013-08-08 16:53:43 +09005497 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005498 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005499 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305500 if (!parms)
5501 goto error;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005502
5503 err = platform_get_controller_stream_from_params(parms, &ext_controller,
5504 &ext_stream);
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08005505 if (err == 0) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005506 out->extconn.cs.controller = ext_controller;
5507 out->extconn.cs.stream = ext_stream;
5508 ALOGD("%s: usecase(%s) new controller/stream (%d/%d)", __func__,
5509 use_case_table[out->usecase], out->extconn.cs.controller,
5510 out->extconn.cs.stream);
5511 }
5512
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005513 if (out == adev->primary_output) {
5514 pthread_mutex_lock(&adev->lock);
5515 audio_extn_set_parameters(adev, parms);
5516 pthread_mutex_unlock(&adev->lock);
5517 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005518 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005519 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005520 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005521
5522 audio_extn_dts_create_state_notifier_node(out->usecase);
5523 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5524 popcount(out->channel_mask),
5525 out->playback_started);
5526
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08005527 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005528 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005529
Surendar Karkaf51b5842018-04-26 11:28:38 +05305530 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
5531 sizeof(value));
5532 if (err >= 0) {
5533 if (!strncmp("true", value, sizeof("true")) || atoi(value))
5534 audio_extn_send_dual_mono_mixing_coefficients(out);
5535 }
5536
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305537 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5538 if (err >= 0) {
5539 strlcpy(out->profile, value, sizeof(out->profile));
5540 ALOGV("updating stream profile with value '%s'", out->profile);
5541 lock_output_stream(out);
5542 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
5543 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005544 &out->device_list, out->flags,
5545 out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305546 out->sample_rate, out->bit_width,
5547 out->channel_mask, out->profile,
5548 &out->app_type_cfg);
5549 pthread_mutex_unlock(&out->lock);
5550 }
5551
Alexy Joseph98988832017-01-13 14:56:59 -08005552 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005553 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
5554 // and vendor.audio.hal.output.suspend.supported is set to true
5555 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08005556 //check suspend parameter only for low latency and if the property
5557 //is enabled
5558 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
5559 ALOGI("%s: got suspend_playback %s", __func__, value);
5560 lock_output_stream(out);
5561 if (!strncmp(value, "false", 5)) {
5562 //suspend_playback=false is supposed to set QOS value back to 75%
5563 //the mixer control sent with value Enable will achieve that
5564 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5565 } else if (!strncmp (value, "true", 4)) {
5566 //suspend_playback=true is supposed to remove QOS value
5567 //resetting the mixer control will set the default value
5568 //for the mixer control which is Disable and this removes the QOS vote
5569 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5570 } else {
5571 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
5572 " got %s", __func__, value);
5573 ret = -1;
5574 }
5575
5576 if (ret != 0) {
5577 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
5578 __func__, out->pm_qos_mixer_path, ret);
5579 }
5580
5581 pthread_mutex_unlock(&out->lock);
5582 }
5583 }
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005584
Alexy Joseph98988832017-01-13 14:56:59 -08005585 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005586 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305587error:
Eric Laurent994a6932013-07-17 11:51:42 -07005588 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005589 return ret;
5590}
5591
Paul McLeana50b7332018-12-17 08:24:21 -07005592static int in_set_microphone_direction(const struct audio_stream_in *stream,
5593 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07005594 struct stream_in *in = (struct stream_in *)stream;
5595
5596 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
5597
5598 in->direction = dir;
5599
5600 if (in->standby)
5601 return 0;
5602
5603 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07005604}
5605
5606static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07005607 struct stream_in *in = (struct stream_in *)stream;
5608
5609 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
5610
5611 if (zoom > 1.0 || zoom < -1.0)
5612 return -EINVAL;
5613
5614 in->zoom = zoom;
5615
5616 if (in->standby)
5617 return 0;
5618
5619 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07005620}
5621
5622
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005623static bool stream_get_parameter_channels(struct str_parms *query,
5624 struct str_parms *reply,
5625 audio_channel_mask_t *supported_channel_masks) {
5626 int ret = -1;
5627 char value[512];
5628 bool first = true;
5629 size_t i, j;
5630
5631 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
5632 ret = 0;
5633 value[0] = '\0';
5634 i = 0;
5635 while (supported_channel_masks[i] != 0) {
5636 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5637 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
5638 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305639 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005640
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305641 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005642 first = false;
5643 break;
5644 }
5645 }
5646 i++;
5647 }
5648 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5649 }
5650 return ret == 0;
5651}
5652
5653static bool stream_get_parameter_formats(struct str_parms *query,
5654 struct str_parms *reply,
5655 audio_format_t *supported_formats) {
5656 int ret = -1;
5657 char value[256];
5658 size_t i, j;
5659 bool first = true;
5660
5661 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
5662 ret = 0;
5663 value[0] = '\0';
5664 i = 0;
5665 while (supported_formats[i] != 0) {
5666 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5667 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
5668 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305669 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005670 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305671 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005672 first = false;
5673 break;
5674 }
5675 }
5676 i++;
5677 }
5678 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
5679 }
5680 return ret == 0;
5681}
5682
5683static bool stream_get_parameter_rates(struct str_parms *query,
5684 struct str_parms *reply,
5685 uint32_t *supported_sample_rates) {
5686
5687 int i;
5688 char value[256];
5689 int ret = -1;
5690 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
5691 ret = 0;
5692 value[0] = '\0';
5693 i=0;
5694 int cursor = 0;
5695 while (supported_sample_rates[i]) {
5696 int avail = sizeof(value) - cursor;
5697 ret = snprintf(value + cursor, avail, "%s%d",
5698 cursor > 0 ? "|" : "",
5699 supported_sample_rates[i]);
5700 if (ret < 0 || ret >= avail) {
5701 // if cursor is at the last element of the array
5702 // overwrite with \0 is duplicate work as
5703 // snprintf already put a \0 in place.
5704 // else
5705 // we had space to write the '|' at value[cursor]
5706 // (which will be overwritten) or no space to fill
5707 // the first element (=> cursor == 0)
5708 value[cursor] = '\0';
5709 break;
5710 }
5711 cursor += ret;
5712 ++i;
5713 }
5714 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
5715 value);
5716 }
5717 return ret >= 0;
5718}
5719
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005720static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
5721{
5722 struct stream_out *out = (struct stream_out *)stream;
5723 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005724 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005725 char value[256];
5726 struct str_parms *reply = str_parms_create();
5727 size_t i, j;
5728 int ret;
5729 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005730
5731 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005732 if (reply) {
5733 str_parms_destroy(reply);
5734 }
5735 if (query) {
5736 str_parms_destroy(query);
5737 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005738 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
5739 return NULL;
5740 }
5741
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005742 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005743 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
5744 if (ret >= 0) {
5745 value[0] = '\0';
5746 i = 0;
5747 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005748 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5749 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005750 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005751 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005752 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005753 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005754 first = false;
5755 break;
5756 }
5757 }
5758 i++;
5759 }
5760 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5761 str = str_parms_to_str(reply);
5762 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005763 voice_extn_out_get_parameters(out, query, reply);
5764 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005765 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005766
Alexy Joseph62142aa2015-11-16 15:10:34 -08005767
5768 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
5769 if (ret >= 0) {
5770 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05305771 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
5772 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08005773 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305774 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005775 } else {
5776 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05305777 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005778 }
5779 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005780 if (str)
5781 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08005782 str = str_parms_to_str(reply);
5783 }
5784
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005785 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
5786 if (ret >= 0) {
5787 value[0] = '\0';
5788 i = 0;
5789 first = true;
5790 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005791 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5792 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005793 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005794 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005795 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005796 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005797 first = false;
5798 break;
5799 }
5800 }
5801 i++;
5802 }
5803 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005804 if (str)
5805 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005806 str = str_parms_to_str(reply);
5807 }
Mingming Yin3a941d42016-02-17 18:08:05 -08005808
5809 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
5810 if (ret >= 0) {
5811 value[0] = '\0';
5812 i = 0;
5813 first = true;
5814 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005815 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
5816 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005817 if (!first) {
5818 strlcat(value, "|", sizeof(value));
5819 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005820 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08005821 first = false;
5822 break;
5823 }
5824 }
5825 i++;
5826 }
5827 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
5828 if (str)
5829 free(str);
5830 str = str_parms_to_str(reply);
5831 }
5832
Alexy Joseph98988832017-01-13 14:56:59 -08005833 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
5834 //only low latency track supports suspend_resume
5835 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005836 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08005837 if (str)
5838 free(str);
5839 str = str_parms_to_str(reply);
5840 }
5841
5842
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005843 str_parms_destroy(query);
5844 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07005845 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005846 return str;
5847}
5848
5849static uint32_t out_get_latency(const struct audio_stream_out *stream)
5850{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005851 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005852 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08005853 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005854
Alexy Josephaa54c872014-12-03 02:46:47 -08005855 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05305856 lock_output_stream(out);
5857 latency = audio_extn_utils_compress_get_dsp_latency(out);
5858 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005859 } else if ((out->realtime) ||
5860 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005861 // since the buffer won't be filled up faster than realtime,
5862 // return a smaller number
5863 if (out->config.rate)
5864 period_ms = (out->af_period_multiplier * out->config.period_size *
5865 1000) / (out->config.rate);
5866 else
5867 period_ms = 0;
George Gao9ba8a142020-07-23 14:30:03 -07005868 latency = period_ms + platform_render_latency(out) / 1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005869 } else {
5870 latency = (out->config.period_count * out->config.period_size * 1000) /
Mingshu Pangf69a88d2021-04-30 16:14:39 +08005871 (out->config.rate);
pavanisra2d95d82022-02-09 18:55:58 +05305872 if (out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5873 out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY)
Mingshu Pangf69a88d2021-04-30 16:14:39 +08005874 latency += platform_render_latency(out)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005875 }
5876
Zhou Songd2537a02020-06-11 22:04:46 +08005877 if (!out->standby && is_a2dp_out_device_type(&out->device_list))
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08005878 latency += audio_extn_a2dp_get_encoder_latency();
5879
Anish Kumar50ebcbf2014-12-09 04:01:39 +05305880 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08005881 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005882}
5883
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305884static float AmpToDb(float amplification)
5885{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305886 float db = DSD_VOLUME_MIN_DB;
5887 if (amplification > 0) {
5888 db = 20 * log10(amplification);
5889 if(db < DSD_VOLUME_MIN_DB)
5890 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305891 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305892 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305893}
5894
Krishna Kishor Jha10ad39f2022-02-21 17:02:47 +05305895#ifdef SOFT_VOLUME
5896static int out_set_soft_volume_params(struct audio_stream_out *stream)
5897{
5898 struct stream_out *out = (struct stream_out *)stream;
5899 int ret = 0;
5900 char mixer_ctl_name[128];
5901 struct audio_device *adev = out->dev;
5902 struct mixer_ctl *ctl = NULL;
5903 struct soft_step_volume_params *volume_params = NULL;
5904
5905 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5906 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Soft Vol Params", pcm_device_id);
5907 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5908 if (!ctl) {
5909 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5910 return -EINVAL;
5911 }
5912
5913 volume_params =(struct soft_step_volume_params * ) malloc(sizeof(struct soft_step_volume_params));
5914 if (volume_params == NULL){
5915 ALOGE("%s : malloc is failed for volume params", __func__);
5916 return -EINVAL;
5917 } else {
5918 ret = platform_get_soft_step_volume_params(volume_params,out->usecase);
5919 if (ret < 0) {
5920 ALOGE("%s : platform_get_soft_step_volume_params is fialed", __func__);
Karan Naidu28b335a2022-05-18 23:00:08 +05305921 ret = -EINVAL;
5922 goto ERR_EXIT;
Krishna Kishor Jha10ad39f2022-02-21 17:02:47 +05305923 }
5924
5925 }
5926 ret = mixer_ctl_set_array(ctl, volume_params, sizeof(struct soft_step_volume_params)/sizeof(int));
5927 if (ret < 0) {
5928 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
Karan Naidu28b335a2022-05-18 23:00:08 +05305929 ret = -EINVAL;
5930 goto ERR_EXIT;
5931 }
5932
5933 if (volume_params) {
5934 free(volume_params);
Krishna Kishor Jha10ad39f2022-02-21 17:02:47 +05305935 }
5936 return 0;
Karan Naidu28b335a2022-05-18 23:00:08 +05305937
5938ERR_EXIT:
5939 if (volume_params) {
5940 free(volume_params);
5941 }
5942 return ret;
Krishna Kishor Jha10ad39f2022-02-21 17:02:47 +05305943}
5944#endif
5945
Arun Mirpuri5d170872019-03-26 13:21:31 -07005946static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
5947 float right)
5948{
5949 struct stream_out *out = (struct stream_out *)stream;
5950 long volume = 0;
5951 char mixer_ctl_name[128] = "";
5952 struct audio_device *adev = out->dev;
5953 struct mixer_ctl *ctl = NULL;
5954 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5955 PCM_PLAYBACK);
5956
5957 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5958 "Playback %d Volume", pcm_device_id);
5959 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5960 if (!ctl) {
5961 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5962 __func__, mixer_ctl_name);
5963 return -EINVAL;
5964 }
5965 if (left != right)
5966 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
5967 __func__, left, right);
5968 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
5969 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
5970 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
5971 __func__, mixer_ctl_name, volume);
5972 return -EINVAL;
5973 }
5974 return 0;
5975}
5976
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305977static int out_set_compr_volume(struct audio_stream_out *stream, float left,
5978 float right)
5979{
5980 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305981 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305982 char mixer_ctl_name[128];
5983 struct audio_device *adev = out->dev;
5984 struct mixer_ctl *ctl;
5985 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5986 PCM_PLAYBACK);
5987
5988 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5989 "Compress Playback %d Volume", pcm_device_id);
5990 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5991 if (!ctl) {
5992 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5993 __func__, mixer_ctl_name);
5994 return -EINVAL;
5995 }
5996 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
5997 __func__, mixer_ctl_name, left, right);
5998 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
5999 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
6000 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
6001
6002 return 0;
6003}
6004
Zhou Song2b8f28f2017-09-11 10:51:38 +08006005static int out_set_voip_volume(struct audio_stream_out *stream, float left,
6006 float right)
6007{
6008 struct stream_out *out = (struct stream_out *)stream;
6009 char mixer_ctl_name[] = "App Type Gain";
6010 struct audio_device *adev = out->dev;
6011 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05306012 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08006013
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07006014 if (!is_valid_volume(left, right)) {
6015 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
6016 __func__, left, right);
6017 return -EINVAL;
6018 }
6019
Zhou Song2b8f28f2017-09-11 10:51:38 +08006020 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
6021 if (!ctl) {
6022 ALOGE("%s: Could not get ctl for mixer cmd - %s",
6023 __func__, mixer_ctl_name);
6024 return -EINVAL;
6025 }
6026
6027 set_values[0] = 0; //0: Rx Session 1:Tx Session
6028 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05306029 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
6030 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08006031
6032 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
6033 return 0;
6034}
6035
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05306036static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
6037 float right)
6038{
6039 struct stream_out *out = (struct stream_out *)stream;
6040 /* Volume control for pcm playback */
6041 if (left != right) {
6042 return -EINVAL;
6043 } else {
6044 char mixer_ctl_name[128];
6045 struct audio_device *adev = out->dev;
6046 struct mixer_ctl *ctl;
6047 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
6048 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
6049 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
6050 if (!ctl) {
6051 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
6052 return -EINVAL;
6053 }
6054
6055 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
6056 int ret = mixer_ctl_set_value(ctl, 0, volume);
6057 if (ret < 0) {
6058 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
6059 return -EINVAL;
6060 }
6061
6062 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
6063
6064 return 0;
6065 }
6066}
6067
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006068static int out_set_volume(struct audio_stream_out *stream, float left,
6069 float right)
6070{
Eric Laurenta9024de2013-04-04 09:19:12 -07006071 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006072 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306073 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006074
Arun Mirpuri5d170872019-03-26 13:21:31 -07006075 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07006076 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
6077 /* only take left channel into account: the API is for stereo anyway */
6078 out->muted = (left == 0.0f);
6079 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006080 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306081 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006082 /*
6083 * Set mute or umute on HDMI passthrough stream.
6084 * Only take left channel into account.
6085 * Mute is 0 and unmute 1
6086 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306087 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306088 } else if (out->format == AUDIO_FORMAT_DSD){
6089 char mixer_ctl_name[128] = "DSD Volume";
6090 struct audio_device *adev = out->dev;
6091 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
6092
6093 if (!ctl) {
6094 ALOGE("%s: Could not get ctl for mixer cmd - %s",
6095 __func__, mixer_ctl_name);
6096 return -EINVAL;
6097 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05306098 volume[0] = (long)(AmpToDb(left));
6099 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306100 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
6101 return 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006102 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS) &&
Derek Chendf05eea2019-08-01 13:57:49 -07006103 (out->car_audio_stream == CAR_AUDIO_STREAM_MEDIA)) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07006104 ALOGD("%s: Overriding offload set volume for media bus stream", __func__);
6105 struct listnode *node = NULL;
6106 list_for_each(node, &adev->active_outputs_list) {
6107 streams_output_ctxt_t *out_ctxt = node_to_item(node,
6108 streams_output_ctxt_t,
6109 list);
6110 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
6111 out->volume_l = out_ctxt->output->volume_l;
6112 out->volume_r = out_ctxt->output->volume_r;
6113 }
6114 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08006115 pthread_mutex_lock(&out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +08006116 if (!out->a2dp_muted) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07006117 ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
6118 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08006119 pthread_mutex_unlock(&out->latch_lock);
Philippe Gravel1c9ac352019-05-28 16:08:37 -07006120 return ret;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006121 } else {
Weiyin Jiang280ea742020-09-08 20:28:22 +08006122 pthread_mutex_lock(&out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +08006123 ALOGV("%s: compress mute %d", __func__, out->a2dp_muted);
6124 if (!out->a2dp_muted)
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306125 ret = out_set_compr_volume(stream, left, right);
6126 out->volume_l = left;
6127 out->volume_r = right;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006128 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306129 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006130 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07006131 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08006132 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
6133 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Songbaddf9f2020-11-20 13:57:39 +08006134 pthread_mutex_lock(&out->latch_lock);
Aalique Grahame22e49102018-12-18 14:23:57 -08006135 if (!out->standby) {
6136 audio_extn_utils_send_app_type_gain(out->dev,
6137 out->app_type_cfg.app_type,
6138 &out->app_type_cfg.gain[0]);
Zhou Songbaddf9f2020-11-20 13:57:39 +08006139 if (!out->a2dp_muted)
6140 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08006141 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08006142 out->volume_l = left;
6143 out->volume_r = right;
Zhou Songbaddf9f2020-11-20 13:57:39 +08006144 pthread_mutex_unlock(&out->latch_lock);
Zhou Song2b8f28f2017-09-11 10:51:38 +08006145 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006146 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
6147 ALOGV("%s: MMAP set volume called", __func__);
6148 if (!out->standby)
6149 ret = out_set_mmap_volume(stream, left, right);
6150 out->volume_l = left;
6151 out->volume_r = right;
6152 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05306153 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05306154 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
6155 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Zhou Songbaddf9f2020-11-20 13:57:39 +08006156 pthread_mutex_lock(&out->latch_lock);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05306157 /* Volume control for pcm playback */
Zhou Songbaddf9f2020-11-20 13:57:39 +08006158 if (!out->standby && !out->a2dp_muted)
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05306159 ret = out_set_pcm_volume(stream, left, right);
6160 else
6161 out->apply_volume = true;
6162
6163 out->volume_l = left;
6164 out->volume_r = right;
Zhou Songbaddf9f2020-11-20 13:57:39 +08006165 pthread_mutex_unlock(&out->latch_lock);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05306166 return ret;
Derek Chenf13dd492018-11-13 14:53:51 -08006167 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
6168 ALOGV("%s: bus device set volume called", __func__);
Zhou Songbaddf9f2020-11-20 13:57:39 +08006169 pthread_mutex_lock(&out->latch_lock);
6170 if (!out->standby && !out->a2dp_muted)
Derek Chenf13dd492018-11-13 14:53:51 -08006171 ret = out_set_pcm_volume(stream, left, right);
6172 out->volume_l = left;
6173 out->volume_r = right;
Zhou Songbaddf9f2020-11-20 13:57:39 +08006174 pthread_mutex_unlock(&out->latch_lock);
Derek Chenf13dd492018-11-13 14:53:51 -08006175 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07006176 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006177
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006178 return -ENOSYS;
6179}
6180
Zhou Songc9672822017-08-16 16:01:39 +08006181static void update_frames_written(struct stream_out *out, size_t bytes)
6182{
6183 size_t bpf = 0;
6184
6185 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
6186 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
6187 bpf = 1;
6188 else if (!is_offload_usecase(out->usecase))
6189 bpf = audio_bytes_per_sample(out->format) *
6190 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08006191
6192 pthread_mutex_lock(&out->position_query_lock);
6193 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08006194 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08006195 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
6196 }
6197 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08006198}
6199
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006200int split_and_write_audio_haptic_data(struct stream_out *out,
6201 const void *buffer, size_t bytes_to_write)
6202{
6203 struct audio_device *adev = out->dev;
6204
6205 int ret = 0;
6206 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
6207 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
6208 size_t frame_size = channel_count * bytes_per_sample;
6209 size_t frame_count = bytes_to_write / frame_size;
6210
6211 bool force_haptic_path =
6212 property_get_bool("vendor.audio.test_haptic", false);
6213
6214 // extract Haptics data from Audio buffer
6215 bool alloc_haptic_buffer = false;
6216 int haptic_channel_count = adev->haptics_config.channels;
6217 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
6218 size_t audio_frame_size = frame_size - haptic_frame_size;
6219 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
6220
6221 if (adev->haptic_buffer == NULL) {
6222 alloc_haptic_buffer = true;
6223 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
6224 free(adev->haptic_buffer);
6225 adev->haptic_buffer_size = 0;
6226 alloc_haptic_buffer = true;
6227 }
6228
6229 if (alloc_haptic_buffer) {
6230 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08006231 if(adev->haptic_buffer == NULL) {
6232 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
6233 return -ENOMEM;
6234 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006235 adev->haptic_buffer_size = total_haptic_buffer_size;
6236 }
6237
6238 size_t src_index = 0, aud_index = 0, hap_index = 0;
6239 uint8_t *audio_buffer = (uint8_t *)buffer;
6240 uint8_t *haptic_buffer = adev->haptic_buffer;
6241
6242 // This is required for testing only. This works for stereo data only.
6243 // One channel is fed to audio stream and other to haptic stream for testing.
6244 if (force_haptic_path)
6245 audio_frame_size = haptic_frame_size = bytes_per_sample;
6246
6247 for (size_t i = 0; i < frame_count; i++) {
6248 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
6249 audio_frame_size);
6250 aud_index += audio_frame_size;
6251 src_index += audio_frame_size;
6252
6253 if (adev->haptic_pcm)
6254 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
6255 haptic_frame_size);
6256 hap_index += haptic_frame_size;
6257 src_index += haptic_frame_size;
6258
6259 // This is required for testing only.
6260 // Discard haptic channel data.
6261 if (force_haptic_path)
6262 src_index += haptic_frame_size;
6263 }
6264
6265 // write to audio pipeline
6266 ret = pcm_write(out->pcm, (void *)audio_buffer,
6267 frame_count * audio_frame_size);
6268
6269 // write to haptics pipeline
6270 if (adev->haptic_pcm)
6271 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
6272 frame_count * haptic_frame_size);
6273
6274 return ret;
6275}
6276
Aalique Grahame22e49102018-12-18 14:23:57 -08006277#ifdef NO_AUDIO_OUT
6278static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
6279 const void *buffer __unused, size_t bytes)
6280{
6281 struct stream_out *out = (struct stream_out *)stream;
6282
6283 /* No Output device supported other than BT for playback.
6284 * Sleep for the amount of buffer duration
6285 */
6286 lock_output_stream(out);
6287 usleep(bytes * 1000000 / audio_stream_out_frame_size(
6288 (const struct audio_stream_out *)&out->stream) /
6289 out_get_sample_rate(&out->stream.common));
6290 pthread_mutex_unlock(&out->lock);
6291 return bytes;
6292}
6293#endif
6294
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006295static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
6296 size_t bytes)
6297{
6298 struct stream_out *out = (struct stream_out *)stream;
6299 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07006300 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05306301 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006302 const size_t frame_size = audio_stream_out_frame_size(stream);
6303 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05306304 struct audio_usecase *usecase = NULL;
Meng Wang4c32fb42020-01-16 17:57:11 +08006305 uint32_t compr_passthr = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006306
Haynes Mathew George380745d2017-10-04 15:27:45 -07006307 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006308 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306309
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05006310 if (CARD_STATUS_OFFLINE == out->card_status ||
6311 POWER_POLICY_STATUS_OFFLINE == adev->out_power_policy) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08006312
Dhananjay Kumarac341582017-02-23 23:42:25 +05306313 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306314 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05306315 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
6316 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006317 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05306318 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05306319 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05306320 ALOGD(" %s: sound card is not active/SSR state", __func__);
6321 ret= -EIO;
6322 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306323 }
6324 }
6325
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306326 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05306327 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05306328 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306329 goto exit;
6330 }
6331
Haynes Mathew George16081042017-05-31 17:16:49 -07006332 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
6333 ret = -EINVAL;
6334 goto exit;
6335 }
6336
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006337 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306338 !out->is_iec61937_info_available) {
6339
6340 if (!audio_extn_passthru_is_passthrough_stream(out)) {
6341 out->is_iec61937_info_available = true;
6342 } else if (audio_extn_passthru_is_enabled()) {
6343 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05306344 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05306345
6346 if((out->format == AUDIO_FORMAT_DTS) ||
6347 (out->format == AUDIO_FORMAT_DTS_HD)) {
6348 ret = audio_extn_passthru_update_dts_stream_configuration(out,
6349 buffer, bytes);
6350 if (ret) {
6351 if (ret != -ENOSYS) {
6352 out->is_iec61937_info_available = false;
6353 ALOGD("iec61937 transmission info not yet updated retry");
6354 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306355 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05306356 /* if stream has started and after that there is
6357 * stream config change (iec transmission config)
6358 * then trigger select_device to update backend configuration.
6359 */
6360 out->stream_config_changed = true;
6361 pthread_mutex_lock(&adev->lock);
6362 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306363 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08006364 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306365 ret = -EINVAL;
6366 goto exit;
6367 }
Manish Dewangan671a4202017-08-18 17:30:46 +05306368 pthread_mutex_unlock(&adev->lock);
6369 out->stream_config_changed = false;
6370 out->is_iec61937_info_available = true;
6371 }
6372 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05306373
Meng Wang4c32fb42020-01-16 17:57:11 +08006374#ifdef AUDIO_GKI_ENABLED
6375 /* out->compr_config.codec->reserved[0] is for compr_passthr */
6376 compr_passthr = out->compr_config.codec->reserved[0];
6377#else
6378 compr_passthr = out->compr_config.codec->compr_passthr;
6379#endif
6380
Garmond Leung317cbf12017-09-13 16:20:50 -07006381 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Meng Wang4c32fb42020-01-16 17:57:11 +08006382 (compr_passthr == PASSTHROUGH) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05306383 (out->is_iec61937_info_available == true)) {
6384 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
6385 ret = -EINVAL;
6386 goto exit;
6387 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05306388 }
6389 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306390
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006391 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02006392 (audio_extn_a2dp_source_is_suspended())) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006393 if (!(compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER) ||
6394 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Zhou Songd01e7a22020-09-23 22:49:01 +08006395 if (!is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306396 ret = -EIO;
6397 goto exit;
6398 }
6399 }
6400 }
6401
Weiyin Jiangabedea32020-12-09 12:49:19 +08006402 if (is_usb_out_device_type(&out->device_list) &&
6403 !audio_extn_usb_connected(NULL)) {
6404 ret = -EIO;
6405 goto exit;
6406 }
6407
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006408 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07006409 out->standby = false;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006410 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
6411
Eric Laurent150dbfe2013-02-27 14:31:02 -08006412 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006413 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
6414 ret = voice_extn_compress_voip_start_output_stream(out);
6415 else
6416 ret = start_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006417 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006418 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07006419 out->standby = true;
Weiyin Jiangac2bae82020-07-29 17:23:53 +08006420 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006421 goto exit;
6422 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306423 out->started = 1;
Andy Hunga1f48fa2019-07-01 18:14:53 -07006424 out->last_fifo_valid = false; // we're coming out of standby, last_fifo isn't valid.
Weiyin Jiangac2bae82020-07-29 17:23:53 +08006425
6426 if ((last_known_cal_step != -1) && (adev->platform != NULL)) {
vivek mehtab72d08d2016-04-29 03:16:47 -07006427 ALOGD("%s: retry previous failed cal level set", __func__);
Weiyin Jiangac2bae82020-07-29 17:23:53 +08006428 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05306429 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07006430 }
Weiyin Jiangac2bae82020-07-29 17:23:53 +08006431 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306432
6433 if ((out->is_iec61937_info_available == true) &&
6434 (audio_extn_passthru_is_passthrough_stream(out))&&
6435 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
6436 ret = -EINVAL;
6437 goto exit;
6438 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05306439 if (out->set_dual_mono)
6440 audio_extn_send_dual_mono_mixing_coefficients(out);
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006441
Dechen Chai22768452021-07-30 09:29:16 +05306442#ifndef LINUX_ENABLED
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006443 // log startup time in ms.
6444 simple_stats_log(
6445 &out->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Dechen Chai22768452021-07-30 09:29:16 +05306446#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006447 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006448
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006449 if (adev->is_channel_status_set == false &&
6450 compare_device_type(&out->device_list,
6451 AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Alexy Josephb1379942016-01-29 15:49:38 -08006452 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05306453 adev->is_channel_status_set = true;
6454 }
6455
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05306456 if ((adev->use_old_pspd_mix_ctrl == true) &&
6457 (out->pspd_coeff_sent == false)) {
6458 /*
6459 * Need to resend pspd coefficients after stream started for
6460 * older kernel version as it does not save the coefficients
6461 * and also stream has to be started for coeff to apply.
6462 */
6463 usecase = get_usecase_from_list(adev, out->usecase);
6464 if (usecase != NULL) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05306465 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05306466 out->pspd_coeff_sent = true;
6467 }
6468 }
6469
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006470 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08006471 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006472 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006473 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006474 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
6475 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05306476 if (out->send_next_track_params && out->is_compr_metadata_avail) {
6477 ALOGD("copl(%p):send next track params in gapless", out);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08006478 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05306479 out->send_next_track_params = false;
6480 out->is_compr_metadata_avail = false;
6481 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006482 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05306483 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306484 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006485
Ashish Jain83a6cc22016-06-28 14:34:17 +05306486 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05306487 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05306488 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05306489 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006490 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05306491 return -EINVAL;
6492 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05306493 audio_format_t dst_format = out->hal_op_format;
6494 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306495
Dieter Luecking5d57def2018-09-07 14:23:37 +02006496 /* prevent division-by-zero */
6497 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
6498 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
6499 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
6500 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05306501 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006502 ATRACE_END();
6503 return -EINVAL;
6504 }
6505
Ashish Jainf1eaa582016-05-23 20:54:24 +05306506 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
6507 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
6508
Ashish Jain83a6cc22016-06-28 14:34:17 +05306509 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05306510 dst_format,
6511 buffer,
6512 src_format,
6513 frames);
6514
Ashish Jain83a6cc22016-06-28 14:34:17 +05306515 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05306516 bytes_to_write);
6517
6518 /*Convert written bytes in audio flinger format*/
6519 if (ret > 0)
6520 ret = ((ret * format_to_bitwidth_table[out->format]) /
6521 format_to_bitwidth_table[dst_format]);
6522 }
6523 } else
6524 ret = compress_write(out->compr, buffer, bytes);
6525
Zhou Songc9672822017-08-16 16:01:39 +08006526 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
6527 update_frames_written(out, bytes);
6528
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306529 if (ret < 0)
6530 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08006531 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05306532 /*msg to cb thread only if non blocking write is enabled*/
6533 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05306534 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006535 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05306536 } else if (-ENETRESET == ret) {
6537 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306538 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05306539 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05306540 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006541 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05306542 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006543 }
Ashish Jain5106d362016-05-11 19:23:33 +05306544
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05306545 /* Call compr start only when non-zero bytes of data is there to be rendered */
6546 if (!out->playback_started && ret > 0) {
6547 int status = compress_start(out->compr);
6548 if (status < 0) {
6549 ret = status;
6550 ALOGE("%s: compr start failed with err %d", __func__, errno);
6551 goto exit;
6552 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07006553 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006554 out->playback_started = 1;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006555 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006556 out->offload_state = OFFLOAD_STATE_PLAYING;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006557 pthread_mutex_unlock(&out->latch_lock);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006558
6559 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6560 popcount(out->channel_mask),
6561 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006562 }
6563 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006564 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006565 return ret;
6566 } else {
6567 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006568 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006569 if (out->muted)
6570 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006571 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
6572 __func__, frames, frame_size, bytes_to_write);
6573
Aalique Grahame22e49102018-12-18 14:23:57 -08006574 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07006575 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
6576 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
6577 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006578 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
6579 int16_t *src = (int16_t *)buffer;
6580 int16_t *dst = (int16_t *)buffer;
6581
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006582 LOG_ALWAYS_FATAL_IF(channel_count > 2 ||
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006583 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08006584 "out_write called for %s use case with wrong properties",
6585 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006586
6587 /*
6588 * FIXME: this can be removed once audio flinger mixer supports
6589 * mono output
6590 */
6591
6592 /*
6593 * Code below goes over each frame in the buffer and adds both
6594 * L and R samples and then divides by 2 to convert to mono
6595 */
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006596 if (channel_count == 2) {
6597 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
6598 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
6599 }
6600 bytes_to_write /= 2;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006601 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006602 }
Andy Hunga1f48fa2019-07-01 18:14:53 -07006603
6604 // Note: since out_get_presentation_position() is called alternating with out_write()
6605 // by AudioFlinger, we can check underruns using the prior timestamp read.
6606 // (Alternately we could check if the buffer is empty using pcm_get_htimestamp().
6607 if (out->last_fifo_valid) {
6608 // compute drain to see if there is an underrun.
6609 const int64_t current_ns = systemTime(SYSTEM_TIME_MONOTONIC); // sys call
Dhananjay Kumara4429632020-07-11 02:53:37 +05306610 int64_t time_diff_ns = current_ns - out->last_fifo_time_ns;
6611 int64_t frames_by_time =
6612 ((time_diff_ns > 0) && (time_diff_ns < (INT64_MAX / out->config.rate))) ?
6613 (time_diff_ns * out->config.rate / NANOS_PER_SECOND) : 0;
Andy Hunga1f48fa2019-07-01 18:14:53 -07006614 const int64_t underrun = frames_by_time - out->last_fifo_frames_remaining;
6615
6616 if (underrun > 0) {
Dechen Chai22768452021-07-30 09:29:16 +05306617#ifndef LINUX_ENABLED
Andy Hunga1f48fa2019-07-01 18:14:53 -07006618 simple_stats_log(&out->fifo_underruns, underrun);
Dechen Chai22768452021-07-30 09:29:16 +05306619#endif
Andy Hunga1f48fa2019-07-01 18:14:53 -07006620
6621 ALOGW("%s: underrun(%lld) "
6622 "frames_by_time(%lld) > out->last_fifo_frames_remaining(%lld)",
6623 __func__,
6624 (long long)out->fifo_underruns.n,
6625 (long long)frames_by_time,
6626 (long long)out->last_fifo_frames_remaining);
6627 }
6628 out->last_fifo_valid = false; // we're writing below, mark fifo info as stale.
6629 }
6630
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306631 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006632
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006633 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006634
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006635 if (out->config.rate)
6636 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
6637 out->config.rate;
6638
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006639 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006640 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
6641
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006642 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006643 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006644 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306645 out->convert_buffer != NULL) {
6646
6647 memcpy_by_audio_format(out->convert_buffer,
6648 out->hal_op_format,
6649 buffer,
6650 out->hal_ip_format,
6651 out->config.period_size * out->config.channels);
6652
6653 ret = pcm_write(out->pcm, out->convert_buffer,
6654 (out->config.period_size *
6655 out->config.channels *
6656 format_to_bitwidth_table[out->hal_op_format]));
6657 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05306658 /*
6659 * To avoid underrun in DSP when the application is not pumping
6660 * data at required rate, check for the no. of bytes and ignore
6661 * pcm_write if it is less than actual buffer size.
6662 * It is a work around to a change in compress VOIP driver.
6663 */
6664 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
6665 bytes < (out->config.period_size * out->config.channels *
6666 audio_bytes_per_sample(out->format))) {
6667 size_t voip_buf_size =
6668 out->config.period_size * out->config.channels *
6669 audio_bytes_per_sample(out->format);
6670 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
6671 __func__, bytes, voip_buf_size);
6672 usleep(((uint64_t)voip_buf_size - bytes) *
6673 1000000 / audio_stream_out_frame_size(stream) /
6674 out_get_sample_rate(&out->stream.common));
6675 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006676 } else {
6677 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
6678 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
6679 else
6680 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
6681 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306682 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006683
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006684 release_out_focus(out);
6685
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306686 if (ret < 0)
6687 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08006688 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05306689 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006690 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006691 }
6692
6693exit:
Zhou Songc9672822017-08-16 16:01:39 +08006694 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306695 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306696 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306697 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006698 pthread_mutex_unlock(&out->lock);
6699
6700 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006701 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08006702 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306703 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306704 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306705 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306706 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306707 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306708 out->standby = true;
6709 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306710 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006711 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
6712 /* prevent division-by-zero */
6713 uint32_t stream_size = audio_stream_out_frame_size(stream);
6714 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006715
Dieter Luecking5d57def2018-09-07 14:23:37 +02006716 if ((stream_size == 0) || (srate == 0)) {
6717 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
6718 ATRACE_END();
6719 return -EINVAL;
6720 }
6721 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
6722 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006723 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05306724 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006725 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006726 return ret;
6727 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006728 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07006729 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006730 return bytes;
6731}
6732
6733static int out_get_render_position(const struct audio_stream_out *stream,
6734 uint32_t *dsp_frames)
6735{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006736 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08006737
6738 if (dsp_frames == NULL)
6739 return -EINVAL;
6740
6741 *dsp_frames = 0;
6742 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08006743 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05306744
6745 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
6746 * this operation and adev_close_output_stream(where out gets reset).
6747 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05306748 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006749 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05306750 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006751 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05306752 return 0;
6753 }
6754
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006755 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05306756 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306757 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006758 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306759 if (ret < 0)
6760 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006761 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05306762 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006763 }
Naresh Tanniru80659832014-06-04 18:17:56 +05306764 if (-ENETRESET == ret) {
6765 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306766 out->card_status = CARD_STATUS_OFFLINE;
6767 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306768 } else if(ret < 0) {
6769 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306770 ret = -EINVAL;
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05006771 } else if (out->card_status == CARD_STATUS_OFFLINE ||
6772 adev->out_power_policy == POWER_POLICY_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05306773 /*
6774 * Handle corner case where compress session is closed during SSR
6775 * and timestamp is queried
6776 */
6777 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306778 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306779 } else if (out->prev_card_status_offline) {
6780 ALOGE("ERROR: previously sound card was offline,return error");
6781 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306782 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306783 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006784 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05306785 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306786 pthread_mutex_unlock(&out->lock);
6787 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08006788 } else if (audio_is_linear_pcm(out->format)) {
6789 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006790 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08006791 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006792 } else
6793 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006794}
6795
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006796static int out_add_audio_effect(const struct audio_stream *stream __unused,
6797 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006798{
6799 return 0;
6800}
6801
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006802static int out_remove_audio_effect(const struct audio_stream *stream __unused,
6803 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006804{
6805 return 0;
6806}
6807
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006808static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
6809 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006810{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05306811 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006812}
6813
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006814static int out_get_presentation_position(const struct audio_stream_out *stream,
6815 uint64_t *frames, struct timespec *timestamp)
6816{
6817 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05306818 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07006819 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006820
Ashish Jain5106d362016-05-11 19:23:33 +05306821 /* below piece of code is not guarded against any lock because audioFliner serializes
6822 * this operation and adev_close_output_stream( where out gets reset).
6823 */
6824 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05306825 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006826 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05306827 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
6828 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
6829 return 0;
6830 }
6831
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006832 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006833
Ashish Jain5106d362016-05-11 19:23:33 +05306834 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
6835 ret = compress_get_tstamp(out->compr, &dsp_frames,
6836 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08006837 // Adjustment accounts for A2dp encoder latency with offload usecases
6838 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006839 if (is_a2dp_out_device_type(&out->device_list)) {
yidongh0515e042017-07-06 15:00:34 +08006840 unsigned long offset =
6841 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
6842 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
6843 }
Ashish Jain5106d362016-05-11 19:23:33 +05306844 ALOGVV("%s rendered frames %ld sample_rate %d",
6845 __func__, dsp_frames, out->sample_rate);
6846 *frames = dsp_frames;
6847 if (ret < 0)
6848 ret = -errno;
6849 if (-ENETRESET == ret) {
6850 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306851 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05306852 ret = -EINVAL;
6853 } else
6854 ret = 0;
6855 /* this is the best we can do */
6856 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07006857 } else {
6858 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08006859 unsigned int avail;
6860 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
George Gao62ebc722019-07-29 16:29:44 -07006861 uint64_t signed_frames = 0;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006862 uint64_t frames_temp = 0;
George Gao62ebc722019-07-29 16:29:44 -07006863
Andy Hunga1f48fa2019-07-01 18:14:53 -07006864 if (out->kernel_buffer_size > avail) {
6865 frames_temp = out->last_fifo_frames_remaining = out->kernel_buffer_size - avail;
6866 } else {
6867 ALOGW("%s: avail:%u > kernel_buffer_size:%zu clamping!",
6868 __func__, avail, out->kernel_buffer_size);
6869 avail = out->kernel_buffer_size;
6870 frames_temp = out->last_fifo_frames_remaining = 0;
6871 }
6872 out->last_fifo_valid = true;
6873 out->last_fifo_time_ns = audio_utils_ns_from_timespec(timestamp);
6874
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006875 if (out->written >= frames_temp)
6876 signed_frames = out->written - frames_temp;
George Gao62ebc722019-07-29 16:29:44 -07006877
Andy Hunga1f48fa2019-07-01 18:14:53 -07006878 ALOGVV("%s: frames:%lld avail:%u kernel_buffer_size:%zu",
6879 __func__, (long long)signed_frames, avail, out->kernel_buffer_size);
6880
Weiyin Jiangd4633762018-03-16 12:05:03 +08006881 // This adjustment accounts for buffering after app processor.
6882 // It is based on estimated DSP latency per use case, rather than exact.
George Gao9ba8a142020-07-23 14:30:03 -07006883 frames_temp = platform_render_latency(out) *
Robert Lee58215542019-07-15 20:55:12 +08006884 out->sample_rate / 1000000LL;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006885 if (signed_frames >= frames_temp)
6886 signed_frames -= frames_temp;
Aniket Kumar Lataff613152017-07-18 18:19:21 -07006887
Weiyin Jiangd4633762018-03-16 12:05:03 +08006888 // Adjustment accounts for A2dp encoder latency with non offload usecases
6889 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006890 if (is_a2dp_out_device_type(&out->device_list)) {
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006891 frames_temp = audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000;
6892 if (signed_frames >= frames_temp)
6893 signed_frames -= frames_temp;
Weiyin Jiangd4633762018-03-16 12:05:03 +08006894 }
6895
6896 // It would be unusual for this value to be negative, but check just in case ...
George Gao62ebc722019-07-29 16:29:44 -07006897 *frames = signed_frames;
6898 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006899 }
Eric Laurenta7a33042019-07-10 16:20:22 -07006900 } else if (out->card_status == CARD_STATUS_OFFLINE ||
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05006901 adev->out_power_policy == POWER_POLICY_STATUS_OFFLINE ||
Eric Laurenta7a33042019-07-10 16:20:22 -07006902 // audioflinger still needs position updates when A2DP is suspended
Jasmine Cha5c2517f2019-09-09 11:07:28 +08006903 (is_a2dp_out_device_type(&out->device_list) && audio_extn_a2dp_source_is_suspended())) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306904 *frames = out->written;
6905 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306906 if (is_offload_usecase(out->usecase))
6907 ret = -EINVAL;
6908 else
6909 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006910 }
6911 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006912 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006913 return ret;
6914}
6915
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006916static int out_set_callback(struct audio_stream_out *stream,
6917 stream_callback_t callback, void *cookie)
6918{
6919 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006920 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006921
6922 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006923 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006924 out->client_callback = callback;
6925 out->client_cookie = cookie;
6926 if (out->adsp_hdlr_stream_handle) {
6927 ret = audio_extn_adsp_hdlr_stream_set_callback(
6928 out->adsp_hdlr_stream_handle,
6929 callback,
6930 cookie);
6931 if (ret)
6932 ALOGW("%s:adsp hdlr callback registration failed %d",
6933 __func__, ret);
6934 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006935 pthread_mutex_unlock(&out->lock);
6936 return 0;
6937}
6938
6939static int out_pause(struct audio_stream_out* stream)
6940{
6941 struct stream_out *out = (struct stream_out *)stream;
6942 int status = -ENOSYS;
6943 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006944 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006945 ALOGD("copl(%p):pause compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306946 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006947 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006948 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006949 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306950 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05306951 status = compress_pause(out->compr);
6952
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006953 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006954
Mingming Yin21854652016-04-13 11:54:02 -07006955 if (audio_extn_passthru_is_active()) {
6956 ALOGV("offload use case, pause passthru");
6957 audio_extn_passthru_on_pause(out);
6958 }
6959
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306960 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006961 audio_extn_dts_notify_playback_state(out->usecase, 0,
6962 out->sample_rate, popcount(out->channel_mask),
6963 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006964 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08006965 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006966 pthread_mutex_unlock(&out->lock);
6967 }
6968 return status;
6969}
6970
6971static int out_resume(struct audio_stream_out* stream)
6972{
6973 struct stream_out *out = (struct stream_out *)stream;
6974 int status = -ENOSYS;
6975 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006976 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006977 ALOGD("copl(%p):resume compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306978 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006979 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006980 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006981 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306982 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306983 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07006984 }
6985 if (!status) {
6986 out->offload_state = OFFLOAD_STATE_PLAYING;
6987 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306988 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006989 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6990 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006991 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08006992 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006993 pthread_mutex_unlock(&out->lock);
6994 }
6995 return status;
6996}
6997
6998static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
6999{
7000 struct stream_out *out = (struct stream_out *)stream;
7001 int status = -ENOSYS;
7002 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07007003 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007004 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007005 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
7006 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
7007 else
7008 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
7009 pthread_mutex_unlock(&out->lock);
7010 }
7011 return status;
7012}
7013
7014static int out_flush(struct audio_stream_out* stream)
7015{
7016 struct stream_out *out = (struct stream_out *)stream;
7017 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07007018 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07007019 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007020 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08007021 pthread_mutex_lock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07007022 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
Gautam Manam14c198b2020-12-24 14:08:04 +05307023 pthread_mutex_unlock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07007024 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07007025 } else {
7026 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
Gautam Manam14c198b2020-12-24 14:08:04 +05307027 pthread_mutex_unlock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07007028 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08007029 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007030 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07007031 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007032 return 0;
7033 }
7034 return -ENOSYS;
7035}
7036
Haynes Mathew George16081042017-05-31 17:16:49 -07007037static int out_stop(const struct audio_stream_out* stream)
7038{
7039 struct stream_out *out = (struct stream_out *)stream;
7040 struct audio_device *adev = out->dev;
7041 int ret = -ENOSYS;
7042
7043 ALOGV("%s", __func__);
7044 pthread_mutex_lock(&adev->lock);
7045 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
7046 out->playback_started && out->pcm != NULL) {
7047 pcm_stop(out->pcm);
7048 ret = stop_output_stream(out);
7049 out->playback_started = false;
7050 }
7051 pthread_mutex_unlock(&adev->lock);
7052 return ret;
7053}
7054
7055static int out_start(const struct audio_stream_out* stream)
7056{
7057 struct stream_out *out = (struct stream_out *)stream;
7058 struct audio_device *adev = out->dev;
7059 int ret = -ENOSYS;
7060
7061 ALOGV("%s", __func__);
7062 pthread_mutex_lock(&adev->lock);
7063 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
7064 !out->playback_started && out->pcm != NULL) {
7065 ret = start_output_stream(out);
7066 if (ret == 0) {
7067 out->playback_started = true;
7068 }
7069 }
7070 pthread_mutex_unlock(&adev->lock);
7071 return ret;
7072}
7073
7074/*
7075 * Modify config->period_count based on min_size_frames
7076 */
7077static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
7078{
7079 int periodCountRequested = (min_size_frames + config->period_size - 1)
7080 / config->period_size;
7081 int periodCount = MMAP_PERIOD_COUNT_MIN;
7082
7083 ALOGV("%s original config.period_size = %d config.period_count = %d",
7084 __func__, config->period_size, config->period_count);
7085
7086 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
7087 periodCount *= 2;
7088 }
7089 config->period_count = periodCount;
7090
7091 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
7092}
7093
Phil Burkfe17efd2019-03-25 10:23:35 -07007094// Read offset for the positional timestamp from a persistent vendor property.
7095// This is to workaround apparent inaccuracies in the timing information that
7096// is used by the AAudio timing model. The inaccuracies can cause glitches.
7097static int64_t get_mmap_out_time_offset() {
7098 const int32_t kDefaultOffsetMicros = 0;
7099 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08007100 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07007101 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
7102 return mmap_time_offset_micros * (int64_t)1000;
7103}
7104
Haynes Mathew George16081042017-05-31 17:16:49 -07007105static int out_create_mmap_buffer(const struct audio_stream_out *stream,
7106 int32_t min_size_frames,
7107 struct audio_mmap_buffer_info *info)
7108{
7109 struct stream_out *out = (struct stream_out *)stream;
7110 struct audio_device *adev = out->dev;
7111 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07007112 unsigned int offset1 = 0;
7113 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007114 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07007115 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007116 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07007117
Arun Mirpuri5d170872019-03-26 13:21:31 -07007118 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05307119 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07007120 pthread_mutex_lock(&adev->lock);
7121
Sharad Sanglec6f32552018-05-04 16:15:38 +05307122 if (CARD_STATUS_OFFLINE == out->card_status ||
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05007123 CARD_STATUS_OFFLINE == adev->card_status ||
7124 POWER_POLICY_STATUS_OFFLINE == adev->out_power_policy) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307125 ALOGW("out->card_status or adev->card_status offline, try again");
7126 ret = -EIO;
7127 goto exit;
7128 }
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307129 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07007130 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
7131 ret = -EINVAL;
7132 goto exit;
7133 }
7134 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
7135 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
7136 ret = -ENOSYS;
7137 goto exit;
7138 }
7139 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
7140 if (out->pcm_device_id < 0) {
7141 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
7142 __func__, out->pcm_device_id, out->usecase);
7143 ret = -EINVAL;
7144 goto exit;
7145 }
7146
7147 adjust_mmap_period_count(&out->config, min_size_frames);
7148
Arun Mirpuri5d170872019-03-26 13:21:31 -07007149 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07007150 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
7151 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
7152 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307153 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307154 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7155 out->card_status = CARD_STATUS_OFFLINE;
7156 adev->card_status = CARD_STATUS_OFFLINE;
7157 ret = -EIO;
7158 goto exit;
7159 }
7160
Haynes Mathew George16081042017-05-31 17:16:49 -07007161 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
7162 step = "open";
7163 ret = -ENODEV;
7164 goto exit;
7165 }
7166 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
7167 if (ret < 0) {
7168 step = "begin";
7169 goto exit;
7170 }
juyuchen626833d2019-06-04 16:48:02 +08007171
7172 info->flags = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007173 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07007174 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07007175 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07007176 ret = platform_get_mmap_data_fd(adev->platform,
7177 out->pcm_device_id, 0 /*playback*/,
7178 &info->shared_memory_fd,
7179 &mmap_size);
7180 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07007181 // Fall back to non exclusive mode
7182 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
7183 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07007184 out->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
7185 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, out->mmap_shared_memory_fd);
7186
Arun Mirpuri5d170872019-03-26 13:21:31 -07007187 if (mmap_size < buffer_size) {
7188 step = "mmap";
7189 goto exit;
7190 }
juyuchen626833d2019-06-04 16:48:02 +08007191 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07007192 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007193 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07007194 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07007195
7196 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
7197 if (ret < 0) {
7198 step = "commit";
7199 goto exit;
7200 }
7201
Phil Burkfe17efd2019-03-25 10:23:35 -07007202 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
7203
Haynes Mathew George16081042017-05-31 17:16:49 -07007204 out->standby = false;
7205 ret = 0;
7206
Arun Mirpuri5d170872019-03-26 13:21:31 -07007207 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07007208 __func__, info->shared_memory_address, info->buffer_size_frames);
7209
7210exit:
7211 if (ret != 0) {
7212 if (out->pcm == NULL) {
7213 ALOGE("%s: %s - %d", __func__, step, ret);
7214 } else {
7215 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
7216 pcm_close(out->pcm);
7217 out->pcm = NULL;
7218 }
7219 }
7220 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05307221 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07007222 return ret;
7223}
7224
7225static int out_get_mmap_position(const struct audio_stream_out *stream,
7226 struct audio_mmap_position *position)
7227{
7228 struct stream_out *out = (struct stream_out *)stream;
7229 ALOGVV("%s", __func__);
7230 if (position == NULL) {
7231 return -EINVAL;
7232 }
7233 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08007234 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07007235 return -ENOSYS;
7236 }
7237 if (out->pcm == NULL) {
7238 return -ENOSYS;
7239 }
7240
7241 struct timespec ts = { 0, 0 };
7242 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
7243 if (ret < 0) {
7244 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
7245 return ret;
7246 }
Phil Burkfe17efd2019-03-25 10:23:35 -07007247 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7248 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07007249 return 0;
7250}
7251
7252
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007253/** audio_stream_in implementation **/
7254static uint32_t in_get_sample_rate(const struct audio_stream *stream)
7255{
7256 struct stream_in *in = (struct stream_in *)stream;
7257
7258 return in->config.rate;
7259}
7260
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007261static int in_set_sample_rate(struct audio_stream *stream __unused,
7262 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007263{
7264 return -ENOSYS;
7265}
7266
7267static size_t in_get_buffer_size(const struct audio_stream *stream)
7268{
7269 struct stream_in *in = (struct stream_in *)stream;
7270
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007271 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
7272 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07007273 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
Raghu Bankapur37cbf382022-12-01 09:30:00 +05307274 return audio_extn_compr_cap_get_buffer_size(pcm_format_to_audio_format(in->config.format));
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307275 else if(audio_extn_cin_attached_usecase(in))
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307276 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007277
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007278 return in->config.period_size * in->af_period_multiplier *
7279 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007280}
7281
7282static uint32_t in_get_channels(const struct audio_stream *stream)
7283{
7284 struct stream_in *in = (struct stream_in *)stream;
7285
7286 return in->channel_mask;
7287}
7288
7289static audio_format_t in_get_format(const struct audio_stream *stream)
7290{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007291 struct stream_in *in = (struct stream_in *)stream;
7292
7293 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007294}
7295
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007296static int in_set_format(struct audio_stream *stream __unused,
7297 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007298{
7299 return -ENOSYS;
7300}
7301
7302static int in_standby(struct audio_stream *stream)
7303{
7304 struct stream_in *in = (struct stream_in *)stream;
7305 struct audio_device *adev = in->dev;
7306 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307307 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
7308 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07007309 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307310
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007311 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007312 if (!in->standby && in->is_st_session) {
7313 ALOGD("%s: sound trigger pcm stop lab", __func__);
7314 audio_extn_sound_trigger_stop_lab(in);
George Gao3018ede2019-10-23 13:23:00 -07007315 if (adev->num_va_sessions > 0)
7316 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007317 in->standby = 1;
7318 }
7319
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007320 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007321 if (adev->adm_deregister_stream)
7322 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
7323
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08007324 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007325 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08007326 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08007327 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08007328 voice_extn_compress_voip_close_input_stream(stream);
7329 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07007330 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
7331 do_stop = in->capture_started;
7332 in->capture_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07007333 if (in->mmap_shared_memory_fd >= 0) {
7334 ALOGV("%s: closing mmap_shared_memory_fd = %d",
7335 __func__, in->mmap_shared_memory_fd);
7336 close(in->mmap_shared_memory_fd);
7337 in->mmap_shared_memory_fd = -1;
7338 }
Zhou Songa8895042016-07-05 17:54:22 +08007339 } else {
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307340 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05307341 audio_extn_cin_close_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08007342 }
7343
Arun Mirpuri5d170872019-03-26 13:21:31 -07007344 if (in->pcm) {
7345 ATRACE_BEGIN("pcm_in_close");
7346 pcm_close(in->pcm);
7347 ATRACE_END();
7348 in->pcm = NULL;
7349 }
7350
Carter Hsu2e429db2019-05-14 18:50:52 +08007351 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08007352 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08007353
George Gao3018ede2019-10-23 13:23:00 -07007354 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
7355 if (adev->num_va_sessions > 0)
7356 adev->num_va_sessions--;
7357 }
Quinn Malef6050362019-01-30 15:55:40 -08007358
Eric Laurent150dbfe2013-02-27 14:31:02 -08007359 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007360 }
7361 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07007362 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007363 return status;
7364}
7365
Aalique Grahame22e49102018-12-18 14:23:57 -08007366static int in_dump(const struct audio_stream *stream,
7367 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007368{
Aalique Grahame22e49102018-12-18 14:23:57 -08007369 struct stream_in *in = (struct stream_in *)stream;
7370
7371 // We try to get the lock for consistency,
7372 // but it isn't necessary for these variables.
7373 // If we're not in standby, we may be blocked on a read.
7374 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
7375 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
7376 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
7377 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
Dechen Chai22768452021-07-30 09:29:16 +05307378#ifndef LINUX_ENABLED
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007379 char buffer[256]; // for statistics formatting
7380 if (in->start_latency_ms.n > 0) {
7381 simple_stats_to_string(&in->start_latency_ms, buffer, sizeof(buffer));
7382 dprintf(fd, " Start latency ms: %s\n", buffer);
7383 }
Dechen Chai22768452021-07-30 09:29:16 +05307384#endif
Aalique Grahame22e49102018-12-18 14:23:57 -08007385 if (locked) {
7386 pthread_mutex_unlock(&in->lock);
7387 }
Dechen Chai22768452021-07-30 09:29:16 +05307388#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -08007389 // dump error info
7390 (void)error_log_dump(
7391 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Dechen Chai22768452021-07-30 09:29:16 +05307392#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007393 return 0;
7394}
7395
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307396static void in_snd_mon_cb(void * stream, struct str_parms * parms)
7397{
7398 if (!stream || !parms)
7399 return;
7400
7401 struct stream_in *in = (struct stream_in *)stream;
7402 struct audio_device *adev = in->dev;
7403
7404 card_status_t status;
7405 int card;
7406 if (parse_snd_card_status(parms, &card, &status) < 0)
7407 return;
7408
7409 pthread_mutex_lock(&adev->lock);
7410 bool valid_cb = (card == adev->snd_card);
7411 pthread_mutex_unlock(&adev->lock);
7412
7413 if (!valid_cb)
7414 return;
7415
7416 lock_input_stream(in);
7417 if (in->card_status != status)
7418 in->card_status = status;
7419 pthread_mutex_unlock(&in->lock);
7420
7421 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
7422 use_case_table[in->usecase],
7423 status == CARD_STATUS_OFFLINE ? "offline" : "online");
7424
7425 // a better solution would be to report error back to AF and let
7426 // it put the stream to standby
7427 if (status == CARD_STATUS_OFFLINE)
7428 in_standby(&in->stream.common);
7429
7430 return;
7431}
7432
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007433int route_input_stream(struct stream_in *in,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007434 struct listnode *devices,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007435 audio_source_t source)
7436{
7437 struct audio_device *adev = in->dev;
7438 int ret = 0;
7439
7440 lock_input_stream(in);
7441 pthread_mutex_lock(&adev->lock);
7442
7443 /* no audio source uses val == 0 */
7444 if ((in->source != source) && (source != AUDIO_SOURCE_DEFAULT)) {
7445 in->source = source;
7446 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
7447 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
7448 (voice_extn_compress_voip_is_format_supported(in->format)) &&
7449 (in->config.rate == 8000 || in->config.rate == 16000 ||
7450 in->config.rate == 32000 || in->config.rate == 48000 ) &&
7451 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
7452 ret = voice_extn_compress_voip_open_input_stream(in);
7453 if (ret != 0) {
7454 ALOGE("%s: Compress voip input cannot be opened, error:%d",
7455 __func__, ret);
7456 }
7457 }
7458 }
7459
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007460 if (!compare_devices(&in->device_list, devices) && !list_empty(devices) &&
7461 is_audio_in_device_type(devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007462 // Workaround: If routing to an non existing usb device, fail gracefully
7463 // The routing request will otherwise block during 10 second
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007464 struct str_parms *usb_addr =
7465 str_parms_create_str(get_usb_device_address(devices));
7466 if (is_usb_in_device_type(devices) && usb_addr &&
Weiyin Jiangabedea32020-12-09 12:49:19 +08007467 !audio_extn_usb_connected(NULL)) {
7468 ALOGW("%s: ignoring rerouting to non existing USB", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007469 ret = -ENOSYS;
7470 } else {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007471 /* If recording is in progress, change the tx device to new device */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007472 assign_devices(&in->device_list, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007473 if (!in->standby && !in->is_st_session) {
7474 ALOGV("update input routing change");
7475 // inform adm before actual routing to prevent glitches.
7476 if (adev->adm_on_routing_change) {
7477 adev->adm_on_routing_change(adev->adm_data,
7478 in->capture_handle);
7479 ret = select_devices(adev, in->usecase);
7480 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7481 adev->adm_routing_changed = true;
7482 }
7483 }
7484 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007485 if (usb_addr)
7486 str_parms_destroy(usb_addr);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007487 }
7488 pthread_mutex_unlock(&adev->lock);
7489 pthread_mutex_unlock(&in->lock);
7490
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07007491 ALOGV("%s: exit: status(%d)", __func__, ret);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007492 return ret;
7493}
7494
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007495static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
7496{
7497 struct stream_in *in = (struct stream_in *)stream;
7498 struct audio_device *adev = in->dev;
7499 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007500 char value[32];
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307501 int err = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007502
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307503 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007504 parms = str_parms_create_str(kvpairs);
7505
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307506 if (!parms)
7507 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007508 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08007509 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007510
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307511 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
7512 if (err >= 0) {
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307513 strlcpy(in->profile, value, sizeof(in->profile));
7514 ALOGV("updating stream profile with value '%s'", in->profile);
7515 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
7516 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007517 &in->device_list, in->flags, in->format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307518 in->sample_rate, in->bit_width,
7519 in->profile, &in->app_type_cfg);
7520 }
7521
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007522 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08007523 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007524
7525 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307526error:
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307527 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007528}
7529
7530static char* in_get_parameters(const struct audio_stream *stream,
7531 const char *keys)
7532{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007533 struct stream_in *in = (struct stream_in *)stream;
7534 struct str_parms *query = str_parms_create_str(keys);
7535 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007536 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007537
7538 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08007539 if (reply) {
7540 str_parms_destroy(reply);
7541 }
7542 if (query) {
7543 str_parms_destroy(query);
7544 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007545 ALOGE("in_get_parameters: failed to create query or reply");
7546 return NULL;
7547 }
7548
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007549 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007550
7551 voice_extn_in_get_parameters(in, query, reply);
7552
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007553 stream_get_parameter_channels(query, reply,
7554 &in->supported_channel_masks[0]);
7555 stream_get_parameter_formats(query, reply,
7556 &in->supported_formats[0]);
7557 stream_get_parameter_rates(query, reply,
7558 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007559 str = str_parms_to_str(reply);
7560 str_parms_destroy(query);
7561 str_parms_destroy(reply);
7562
7563 ALOGV("%s: exit: returns - %s", __func__, str);
7564 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007565}
7566
Aalique Grahame22e49102018-12-18 14:23:57 -08007567static int in_set_gain(struct audio_stream_in *stream,
7568 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007569{
Aalique Grahame22e49102018-12-18 14:23:57 -08007570 struct stream_in *in = (struct stream_in *)stream;
7571 char mixer_ctl_name[128];
7572 struct mixer_ctl *ctl;
7573 int ctl_value;
7574
7575 ALOGV("%s: gain %f", __func__, gain);
7576
7577 if (stream == NULL)
7578 return -EINVAL;
7579
7580 /* in_set_gain() only used to silence MMAP capture for now */
7581 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
7582 return -ENOSYS;
7583
7584 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
7585
7586 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
7587 if (!ctl) {
7588 ALOGW("%s: Could not get ctl for mixer cmd - %s",
7589 __func__, mixer_ctl_name);
7590 return -ENOSYS;
7591 }
7592
7593 if (gain < RECORD_GAIN_MIN)
7594 gain = RECORD_GAIN_MIN;
7595 else if (gain > RECORD_GAIN_MAX)
7596 gain = RECORD_GAIN_MAX;
7597 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
7598
7599 mixer_ctl_set_value(ctl, 0, ctl_value);
7600
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007601 return 0;
7602}
7603
7604static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
7605 size_t bytes)
7606{
7607 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05307608
7609 if (in == NULL) {
7610 ALOGE("%s: stream_in ptr is NULL", __func__);
7611 return -EINVAL;
7612 }
7613
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007614 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05307615 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307616 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007617
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007618 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05307619
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007620 if (in->is_st_session) {
7621 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
7622 /* Read from sound trigger HAL */
7623 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08007624 if (in->standby) {
George Gao3018ede2019-10-23 13:23:00 -07007625 if (adev->num_va_sessions < UINT_MAX)
7626 adev->num_va_sessions++;
Quinn Malef6050362019-01-30 15:55:40 -08007627 in->standby = 0;
7628 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007629 pthread_mutex_unlock(&in->lock);
7630 return bytes;
7631 }
7632
Haynes Mathew George16081042017-05-31 17:16:49 -07007633 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
7634 ret = -ENOSYS;
7635 goto exit;
7636 }
7637
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007638 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
7639 !in->standby && adev->adm_routing_changed) {
7640 ret = -ENOSYS;
7641 goto exit;
7642 }
7643
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007644 if (in->standby) {
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007645 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
7646
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007647 pthread_mutex_lock(&adev->lock);
7648 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
7649 ret = voice_extn_compress_voip_start_input_stream(in);
7650 else
7651 ret = start_input_stream(in);
George Gao3018ede2019-10-23 13:23:00 -07007652 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
7653 if (adev->num_va_sessions < UINT_MAX)
7654 adev->num_va_sessions++;
7655 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007656 pthread_mutex_unlock(&adev->lock);
7657 if (ret != 0) {
7658 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007659 }
7660 in->standby = 0;
Dechen Chai22768452021-07-30 09:29:16 +05307661#ifndef LINUX_ENABLED
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007662 // log startup time in ms.
7663 simple_stats_log(
7664 &in->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Dechen Chai22768452021-07-30 09:29:16 +05307665#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007666 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007667
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05307668 /* Avoid read if capture_stopped is set */
7669 if (android_atomic_acquire_load(&(in->capture_stopped)) > 0) {
7670 ALOGD("%s: force stopped catpure session, ignoring read request", __func__);
7671 ret = -EINVAL;
7672 goto exit;
7673 }
7674
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007675 // what's the duration requested by the client?
7676 long ns = 0;
7677
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307678 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007679 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
7680 in->config.rate;
7681
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007682 ret = request_in_focus(in, ns);
7683 if (ret != 0)
7684 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007685 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007686
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307687 if (audio_extn_cin_attached_usecase(in)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307688 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
7689 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307690 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007691 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307692 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07007693 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007694 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007695 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07007696 } else if (audio_extn_ffv_get_stream() == in) {
7697 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307698 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007699 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307700 /* data from DSP comes in 24_8 format, convert it to 8_24 */
7701 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
7702 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
7703 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307704 ret = -EINVAL;
7705 goto exit;
7706 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307707 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307708 ret = -errno;
7709 }
7710 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307711 /* bytes read is always set to bytes for non compress usecases */
7712 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007713 }
7714
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007715 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007716
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007717 /*
Quinn Malef6050362019-01-30 15:55:40 -08007718 * Instead of writing zeroes here, we could trust the hardware to always
7719 * provide zeroes when muted. This is also muted with voice recognition
7720 * usecases so that other clients do not have access to voice recognition
7721 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007722 */
Quinn Malef6050362019-01-30 15:55:40 -08007723 if ((ret == 0 && voice_get_mic_mute(adev) &&
7724 !voice_is_in_call_rec_stream(in) &&
Zhou Song62ea0282020-03-22 19:53:01 +08007725 (in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY &&
Manoj Kumar N D54cab152023-01-27 16:41:55 +05307726 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY2 &&
7727 in->source != AUDIO_SOURCE_FM_TUNER &&
7728 !is_single_device_type_equal(&in->device_list, AUDIO_DEVICE_IN_FM_TUNER))) ||
Quinn Malef6050362019-01-30 15:55:40 -08007729 (adev->num_va_sessions &&
7730 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
7731 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
7732 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007733 memset(buffer, 0, bytes);
7734
7735exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307736 frame_size = audio_stream_in_frame_size(stream);
7737 if (frame_size > 0)
7738 in->frames_read += bytes_read/frame_size;
7739
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007740 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307741 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007742 pthread_mutex_unlock(&in->lock);
7743
7744 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307745 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307746 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307747 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307748 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307749 in->standby = true;
7750 }
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307751 if (!audio_extn_cin_attached_usecase(in)) {
Sharad Sangled17c9122017-03-20 15:58:52 +05307752 bytes_read = bytes;
7753 memset(buffer, 0, bytes);
7754 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007755 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007756 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7757 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007758 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05307759 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05307760 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007761 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307762 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007763}
7764
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007765static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007766{
7767 return 0;
7768}
7769
Aalique Grahame22e49102018-12-18 14:23:57 -08007770static int in_get_capture_position(const struct audio_stream_in *stream,
7771 int64_t *frames, int64_t *time)
7772{
7773 if (stream == NULL || frames == NULL || time == NULL) {
7774 return -EINVAL;
7775 }
7776 struct stream_in *in = (struct stream_in *)stream;
7777 int ret = -ENOSYS;
7778
7779 lock_input_stream(in);
7780 // note: ST sessions do not close the alsa pcm driver synchronously
7781 // on standby. Therefore, we may return an error even though the
7782 // pcm stream is still opened.
7783 if (in->standby) {
7784 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
7785 "%s stream in standby but pcm not NULL for non ST session", __func__);
7786 goto exit;
7787 }
7788 if (in->pcm) {
7789 struct timespec timestamp;
7790 unsigned int avail;
7791 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
7792 *frames = in->frames_read + avail;
Robert Lee58215542019-07-15 20:55:12 +08007793 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec
George Gao9ba8a142020-07-23 14:30:03 -07007794 - platform_capture_latency(in) * 1000LL;
Kakanaboina Ramanjaneyulu8cedb092021-03-15 15:55:29 +05307795 //Adjustment accounts for A2dp decoder latency for recording usecase
7796 // Note: decoder latency is returned in ms, while platform_capture_latency in ns.
7797 if (is_a2dp_in_device_type(&in->device_list))
7798 *time -= audio_extn_a2dp_get_decoder_latency() * 1000000LL;
Aalique Grahame22e49102018-12-18 14:23:57 -08007799 ret = 0;
7800 }
7801 }
7802exit:
7803 pthread_mutex_unlock(&in->lock);
7804 return ret;
7805}
7806
Carter Hsu2e429db2019-05-14 18:50:52 +08007807static int in_update_effect_list(bool add, effect_handle_t effect,
7808 struct listnode *head)
7809{
7810 struct listnode *node;
7811 struct in_effect_list *elist = NULL;
7812 struct in_effect_list *target = NULL;
7813 int ret = 0;
7814
7815 if (!head)
7816 return ret;
7817
7818 list_for_each(node, head) {
7819 elist = node_to_item(node, struct in_effect_list, list);
7820 if (elist->handle == effect) {
7821 target = elist;
7822 break;
7823 }
7824 }
7825
7826 if (add) {
7827 if (target) {
7828 ALOGD("effect %p already exist", effect);
7829 return ret;
7830 }
7831
7832 target = (struct in_effect_list *)
7833 calloc(1, sizeof(struct in_effect_list));
7834
7835 if (!target) {
7836 ALOGE("%s:fail to allocate memory", __func__);
7837 return -ENOMEM;
7838 }
7839
7840 target->handle = effect;
7841 list_add_tail(head, &target->list);
7842 } else {
7843 if (target) {
7844 list_remove(&target->list);
7845 free(target);
7846 }
7847 }
7848
7849 return ret;
7850}
7851
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007852static int add_remove_audio_effect(const struct audio_stream *stream,
7853 effect_handle_t effect,
7854 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007855{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007856 struct stream_in *in = (struct stream_in *)stream;
7857 int status = 0;
7858 effect_descriptor_t desc;
7859
7860 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007861 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
7862
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007863 if (status != 0)
7864 return status;
7865
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007866 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007867 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08007868 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08007869 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
7870 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007871 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08007872
7873 in_update_effect_list(enable, effect, &in->aec_list);
7874 enable = !list_empty(&in->aec_list);
7875 if (enable == in->enable_aec)
7876 goto exit;
7877
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007878 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007879 ALOGD("AEC enable %d", enable);
7880
Aalique Grahame22e49102018-12-18 14:23:57 -08007881 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7882 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
7883 in->dev->enable_voicerx = enable;
7884 struct audio_usecase *usecase;
7885 struct listnode *node;
7886 list_for_each(node, &in->dev->usecase_list) {
7887 usecase = node_to_item(node, struct audio_usecase, list);
7888 if (usecase->type == PCM_PLAYBACK)
7889 select_devices(in->dev, usecase->id);
7890 }
7891 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007892 if (!in->standby) {
7893 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
7894 select_devices(in->dev, in->usecase);
7895 }
7896
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007897 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007898 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
7899
7900 in_update_effect_list(enable, effect, &in->ns_list);
7901 enable = !list_empty(&in->ns_list);
7902 if (enable == in->enable_ns)
7903 goto exit;
7904
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007905 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007906 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007907 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08007908 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Ramu Gottipatifa5be522021-12-28 19:18:21 +05307909 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
kunleizd96526c2018-04-09 11:12:32 +08007910 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007911 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
7912 select_devices(in->dev, in->usecase);
7913 } else
7914 select_devices(in->dev, in->usecase);
7915 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007916 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007917exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007918 pthread_mutex_unlock(&in->dev->lock);
7919 pthread_mutex_unlock(&in->lock);
7920
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007921 return 0;
7922}
7923
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007924static int in_add_audio_effect(const struct audio_stream *stream,
7925 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007926{
Eric Laurent994a6932013-07-17 11:51:42 -07007927 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007928 return add_remove_audio_effect(stream, effect, true);
7929}
7930
7931static int in_remove_audio_effect(const struct audio_stream *stream,
7932 effect_handle_t effect)
7933{
Eric Laurent994a6932013-07-17 11:51:42 -07007934 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007935 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007936}
7937
Haynes Mathew George16081042017-05-31 17:16:49 -07007938static int in_stop(const struct audio_stream_in* stream)
7939{
7940 struct stream_in *in = (struct stream_in *)stream;
7941 struct audio_device *adev = in->dev;
7942
7943 int ret = -ENOSYS;
7944 ALOGV("%s", __func__);
7945 pthread_mutex_lock(&adev->lock);
7946 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7947 in->capture_started && in->pcm != NULL) {
7948 pcm_stop(in->pcm);
7949 ret = stop_input_stream(in);
7950 in->capture_started = false;
7951 }
7952 pthread_mutex_unlock(&adev->lock);
7953 return ret;
7954}
7955
7956static int in_start(const struct audio_stream_in* stream)
7957{
7958 struct stream_in *in = (struct stream_in *)stream;
7959 struct audio_device *adev = in->dev;
7960 int ret = -ENOSYS;
7961
7962 ALOGV("%s in %p", __func__, in);
7963 pthread_mutex_lock(&adev->lock);
7964 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7965 !in->capture_started && in->pcm != NULL) {
7966 if (!in->capture_started) {
7967 ret = start_input_stream(in);
7968 if (ret == 0) {
7969 in->capture_started = true;
7970 }
7971 }
7972 }
7973 pthread_mutex_unlock(&adev->lock);
7974 return ret;
7975}
7976
Phil Burke0a86d12019-02-16 22:28:11 -08007977// Read offset for the positional timestamp from a persistent vendor property.
7978// This is to workaround apparent inaccuracies in the timing information that
7979// is used by the AAudio timing model. The inaccuracies can cause glitches.
7980static int64_t in_get_mmap_time_offset() {
7981 const int32_t kDefaultOffsetMicros = 0;
7982 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08007983 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08007984 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
7985 return mmap_time_offset_micros * (int64_t)1000;
7986}
7987
Haynes Mathew George16081042017-05-31 17:16:49 -07007988static int in_create_mmap_buffer(const struct audio_stream_in *stream,
7989 int32_t min_size_frames,
7990 struct audio_mmap_buffer_info *info)
7991{
7992 struct stream_in *in = (struct stream_in *)stream;
7993 struct audio_device *adev = in->dev;
7994 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07007995 unsigned int offset1 = 0;
7996 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007997 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07007998 uint32_t mmap_size = 0;
7999 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07008000
8001 pthread_mutex_lock(&adev->lock);
8002 ALOGV("%s in %p", __func__, in);
8003
Sharad Sanglec6f32552018-05-04 16:15:38 +05308004 if (CARD_STATUS_OFFLINE == in->card_status||
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05008005 CARD_STATUS_OFFLINE == adev->card_status ||
8006 POWER_POLICY_STATUS_OFFLINE == adev->in_power_policy) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05308007 ALOGW("in->card_status or adev->card_status offline, try again");
8008 ret = -EIO;
8009 goto exit;
8010 }
8011
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05308012 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07008013 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
8014 ret = -EINVAL;
8015 goto exit;
8016 }
8017 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
8018 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
8019 ALOGV("%s in %p", __func__, in);
8020 ret = -ENOSYS;
8021 goto exit;
8022 }
8023 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
8024 if (in->pcm_device_id < 0) {
8025 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
8026 __func__, in->pcm_device_id, in->usecase);
8027 ret = -EINVAL;
8028 goto exit;
8029 }
8030
8031 adjust_mmap_period_count(&in->config, min_size_frames);
8032
8033 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
8034 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
8035 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
8036 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05308037 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05308038 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
8039 in->card_status = CARD_STATUS_OFFLINE;
8040 adev->card_status = CARD_STATUS_OFFLINE;
8041 ret = -EIO;
8042 goto exit;
8043 }
8044
Haynes Mathew George16081042017-05-31 17:16:49 -07008045 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
8046 step = "open";
8047 ret = -ENODEV;
8048 goto exit;
8049 }
8050
8051 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
8052 if (ret < 0) {
8053 step = "begin";
8054 goto exit;
8055 }
Haynes Mathew George16081042017-05-31 17:16:49 -07008056
juyuchen626833d2019-06-04 16:48:02 +08008057 info->flags = 0;
Arun Mirpuri5d170872019-03-26 13:21:31 -07008058 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
8059 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
8060 info->burst_size_frames = in->config.period_size;
8061 ret = platform_get_mmap_data_fd(adev->platform,
8062 in->pcm_device_id, 1 /*capture*/,
8063 &info->shared_memory_fd,
8064 &mmap_size);
8065 if (ret < 0) {
8066 // Fall back to non exclusive mode
8067 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
8068 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07008069 in->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
8070 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, in->mmap_shared_memory_fd);
8071
Arun Mirpuri5d170872019-03-26 13:21:31 -07008072 if (mmap_size < buffer_size) {
8073 step = "mmap";
8074 goto exit;
8075 }
juyuchen626833d2019-06-04 16:48:02 +08008076 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Arun Mirpuri5d170872019-03-26 13:21:31 -07008077 }
8078
8079 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07008080
8081 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
8082 if (ret < 0) {
8083 step = "commit";
8084 goto exit;
8085 }
8086
Phil Burke0a86d12019-02-16 22:28:11 -08008087 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
8088
Haynes Mathew George16081042017-05-31 17:16:49 -07008089 in->standby = false;
8090 ret = 0;
8091
8092 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
8093 __func__, info->shared_memory_address, info->buffer_size_frames);
8094
8095exit:
8096 if (ret != 0) {
8097 if (in->pcm == NULL) {
8098 ALOGE("%s: %s - %d", __func__, step, ret);
8099 } else {
8100 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
8101 pcm_close(in->pcm);
8102 in->pcm = NULL;
8103 }
8104 }
8105 pthread_mutex_unlock(&adev->lock);
8106 return ret;
8107}
8108
8109static int in_get_mmap_position(const struct audio_stream_in *stream,
8110 struct audio_mmap_position *position)
8111{
8112 struct stream_in *in = (struct stream_in *)stream;
8113 ALOGVV("%s", __func__);
8114 if (position == NULL) {
8115 return -EINVAL;
8116 }
Gautam Manam34d1f542021-01-05 20:24:37 +05308117 lock_input_stream(in);
Haynes Mathew George16081042017-05-31 17:16:49 -07008118 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
Gautam Manam34d1f542021-01-05 20:24:37 +05308119 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07008120 return -ENOSYS;
8121 }
8122 if (in->pcm == NULL) {
Gautam Manam34d1f542021-01-05 20:24:37 +05308123 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07008124 return -ENOSYS;
8125 }
8126 struct timespec ts = { 0, 0 };
8127 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
8128 if (ret < 0) {
8129 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
Gautam Manam34d1f542021-01-05 20:24:37 +05308130 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07008131 return ret;
8132 }
Phil Burke0a86d12019-02-16 22:28:11 -08008133 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
8134 + in->mmap_time_offset_nanos;
Gautam Manam34d1f542021-01-05 20:24:37 +05308135 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07008136 return 0;
8137}
8138
Naresh Tannirudcb47c52018-06-25 16:23:32 +05308139static int in_get_active_microphones(const struct audio_stream_in *stream,
8140 struct audio_microphone_characteristic_t *mic_array,
8141 size_t *mic_count) {
8142 struct stream_in *in = (struct stream_in *)stream;
8143 struct audio_device *adev = in->dev;
8144 ALOGVV("%s", __func__);
8145
8146 lock_input_stream(in);
8147 pthread_mutex_lock(&adev->lock);
8148 int ret = platform_get_active_microphones(adev->platform,
8149 audio_channel_count_from_in_mask(in->channel_mask),
8150 in->usecase, mic_array, mic_count);
8151 pthread_mutex_unlock(&adev->lock);
8152 pthread_mutex_unlock(&in->lock);
8153
8154 return ret;
8155}
8156
8157static int adev_get_microphones(const struct audio_hw_device *dev,
8158 struct audio_microphone_characteristic_t *mic_array,
8159 size_t *mic_count) {
8160 struct audio_device *adev = (struct audio_device *)dev;
8161 ALOGVV("%s", __func__);
8162
8163 pthread_mutex_lock(&adev->lock);
8164 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
8165 pthread_mutex_unlock(&adev->lock);
8166
8167 return ret;
8168}
juyuchendb308c22019-01-21 11:57:17 -07008169
8170static void in_update_sink_metadata(struct audio_stream_in *stream,
8171 const struct sink_metadata *sink_metadata) {
8172
8173 if (stream == NULL
8174 || sink_metadata == NULL
8175 || sink_metadata->tracks == NULL) {
8176 return;
8177 }
8178
8179 int error = 0;
8180 struct stream_in *in = (struct stream_in *)stream;
8181 struct audio_device *adev = in->dev;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008182 struct listnode devices;
8183
8184 list_init(&devices);
juyuchendb308c22019-01-21 11:57:17 -07008185
8186 if (sink_metadata->track_count != 0)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008187 reassign_device_list(&devices, sink_metadata->tracks->dest_device, "");
juyuchendb308c22019-01-21 11:57:17 -07008188
8189 lock_input_stream(in);
8190 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008191 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, get_device_types(&devices));
juyuchendb308c22019-01-21 11:57:17 -07008192
Zhou Song503196b2021-07-23 17:31:05 +08008193 if ((in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY ||
8194 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2) &&
8195 !list_empty(&devices) &&
8196 adev->voice_tx_output != NULL) {
juyuchendb308c22019-01-21 11:57:17 -07008197 /* Use the rx device from afe-proxy record to route voice call because
8198 there is no routing if tx device is on primary hal and rx device
8199 is on other hal during voice call. */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008200 assign_devices(&adev->voice_tx_output->device_list, &devices);
juyuchendb308c22019-01-21 11:57:17 -07008201
8202 if (!voice_is_call_state_active(adev)) {
8203 if (adev->mode == AUDIO_MODE_IN_CALL) {
8204 adev->current_call_output = adev->voice_tx_output;
8205 error = voice_start_call(adev);
8206 if (error != 0)
8207 ALOGE("%s: start voice call failed %d", __func__, error);
8208 }
8209 } else {
8210 adev->current_call_output = adev->voice_tx_output;
8211 voice_update_devices_for_all_voice_usecases(adev);
8212 }
8213 }
8214
Zhenlin Lian4f947842022-05-14 15:50:52 +05308215 clear_devices(&devices);
juyuchendb308c22019-01-21 11:57:17 -07008216 pthread_mutex_unlock(&adev->lock);
8217 pthread_mutex_unlock(&in->lock);
8218}
8219
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308220int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07008221 audio_io_handle_t handle,
8222 audio_devices_t devices,
8223 audio_output_flags_t flags,
8224 struct audio_config *config,
8225 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04008226 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008227{
8228 struct audio_device *adev = (struct audio_device *)dev;
8229 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05308230 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008231 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008232 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05308233 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008234 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
8235 bool is_usb_dev = audio_is_usb_out_device(devices) &&
8236 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
8237 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008238 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07008239 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
8240 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008241 bool force_haptic_path =
8242 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07008243 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008244#ifdef AUDIO_GKI_ENABLED
8245 __s32 *generic_dec;
8246#endif
Weiyin Jiang906db3c2021-03-02 13:17:04 +08008247 pthread_mutexattr_t latch_attr;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008248
kunleizdff872d2018-08-20 14:40:33 +08008249 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08008250 is_usb_dev = false;
8251 devices = AUDIO_DEVICE_OUT_SPEAKER;
8252 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
8253 __func__, devices);
Mingshu Pangdbd20562019-11-25 18:04:39 +08008254 if (config->format == AUDIO_FORMAT_DEFAULT)
8255 config->format = AUDIO_FORMAT_PCM_16_BIT;
8256 if (config->sample_rate == 0)
8257 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8258 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8259 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
kunleizd6a9e0c2018-07-30 15:38:52 +08008260 }
8261
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008262 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05308263
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008264 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
8265
Mingming Yin3a941d42016-02-17 18:08:05 -08008266 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04008267 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
8268 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308269
8270
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008271 if (!out) {
8272 return -ENOMEM;
8273 }
8274
Haynes Mathew George204045b2015-02-25 20:32:03 -08008275 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07008276 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Weiyin Jiang906db3c2021-03-02 13:17:04 +08008277 pthread_mutexattr_init(&latch_attr);
8278 pthread_mutexattr_settype(&latch_attr, PTHREAD_MUTEX_RECURSIVE);
8279 pthread_mutex_init(&out->latch_lock, &latch_attr);
8280 pthread_mutexattr_destroy(&latch_attr);
Zhou Song48453a02018-01-10 17:50:59 +08008281 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08008282 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
8283
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008284 if (devices == AUDIO_DEVICE_NONE)
8285 devices = AUDIO_DEVICE_OUT_SPEAKER;
8286
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008287 out->flags = flags;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008288 list_init(&out->device_list);
8289 update_device_list(&out->device_list, devices, address, true /* add devices */);
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07008290 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07008291 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008292 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05308293 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05308294 if (out->channel_mask == AUDIO_CHANNEL_NONE)
8295 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
8296 else
8297 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07008298 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07008299 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08008300 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308301 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308302 out->started = 0;
Zhou Songbaddf9f2020-11-20 13:57:39 +08008303 out->a2dp_muted = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008304 out->hal_output_suspend_supported = 0;
8305 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05308306 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05308307 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05308308 out->pspd_coeff_sent = false;
Phil Burkd898ba62019-06-20 12:49:01 -07008309 out->mmap_shared_memory_fd = -1; // not open
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008310
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05308311 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05308312 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07008313 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
8314
Aalique Grahame22e49102018-12-18 14:23:57 -08008315 if (direct_dev &&
8316 (audio_is_linear_pcm(out->format) ||
8317 config->format == AUDIO_FORMAT_DEFAULT) &&
8318 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
8319 audio_format_t req_format = config->format;
8320 audio_channel_mask_t req_channel_mask = config->channel_mask;
8321 uint32_t req_sample_rate = config->sample_rate;
8322
8323 pthread_mutex_lock(&adev->lock);
8324 if (is_hdmi) {
8325 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
8326 ret = read_hdmi_sink_caps(out);
8327 if (config->sample_rate == 0)
8328 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8329 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8330 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
8331 if (config->format == AUDIO_FORMAT_DEFAULT)
8332 config->format = AUDIO_FORMAT_PCM_16_BIT;
8333 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008334 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
8335 &config->format,
8336 &out->supported_formats[0],
8337 MAX_SUPPORTED_FORMATS,
8338 &config->channel_mask,
8339 &out->supported_channel_masks[0],
8340 MAX_SUPPORTED_CHANNEL_MASKS,
8341 &config->sample_rate,
8342 &out->supported_sample_rates[0],
8343 MAX_SUPPORTED_SAMPLE_RATES);
8344 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008345 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008346
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008347 pthread_mutex_unlock(&adev->lock);
8348 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08008349 if (ret == -ENOSYS) {
8350 /* ignore and go with default */
8351 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08008352 }
8353 // For MMAP NO IRQ, allow conversions in ADSP
8354 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
8355 goto error_open;
8356 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008357 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08008358 goto error_open;
8359 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008360
8361 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
8362 config->sample_rate = req_sample_rate;
8363 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
8364 config->channel_mask = req_channel_mask;
8365 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
8366 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08008367 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008368
8369 out->sample_rate = config->sample_rate;
8370 out->channel_mask = config->channel_mask;
8371 out->format = config->format;
8372 if (is_hdmi) {
8373 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
8374 out->config = pcm_config_hdmi_multi;
8375 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8376 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8377 out->config = pcm_config_mmap_playback;
8378 out->stream.start = out_start;
8379 out->stream.stop = out_stop;
8380 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8381 out->stream.get_mmap_position = out_get_mmap_position;
8382 } else {
8383 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
8384 out->config = pcm_config_hifi;
8385 }
8386
8387 out->config.rate = out->sample_rate;
8388 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
8389 if (is_hdmi) {
8390 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
8391 audio_bytes_per_sample(out->format));
8392 }
8393 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08008394 }
8395
Derek Chenf6318be2017-06-12 17:16:24 -04008396 /* validate bus device address */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008397 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008398 /* extract car audio stream index */
8399 out->car_audio_stream =
8400 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
8401 if (out->car_audio_stream < 0) {
8402 ALOGE("%s: invalid car audio stream %x",
8403 __func__, out->car_audio_stream);
8404 ret = -EINVAL;
8405 goto error_open;
8406 }
Derek Chen5f67a942020-02-24 23:08:13 -08008407 ALOGV("%s: car_audio_stream %x", __func__, out->car_audio_stream);
Derek Chenf6318be2017-06-12 17:16:24 -04008408 }
8409
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008410 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07008411 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008412 if (!voice_extn_is_compress_voip_supported()) {
8413 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
8414 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07008415 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
Lakshman Chaluvarajue7fc9482020-05-30 14:29:29 +05308416 config->channel_mask : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008417 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
8418 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07008419 out->volume_l = INVALID_OUT_VOLUME;
8420 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07008421
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008422 out->config = default_pcm_config_voip_copp;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008423 out->config.rate = out->sample_rate;
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07008424 uint32_t channel_count =
8425 audio_channel_count_from_out_mask(out->channel_mask);
Ramjee Singh968858a2020-08-06 16:30:48 +05308426 out->config.channels = channel_count;
8427
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07008428 uint32_t buffer_size = get_stream_buffer_size(DEFAULT_VOIP_BUF_DURATION_MS,
8429 out->sample_rate, out->format,
8430 channel_count, false);
8431 uint32_t frame_size = audio_bytes_per_sample(out->format) * channel_count;
8432 if (frame_size != 0)
8433 out->config.period_size = buffer_size / frame_size;
8434 else
8435 ALOGW("%s: frame size is 0 for format %#x", __func__, out->format);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008436 }
8437 } else {
8438 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
8439 voice_extn_compress_voip_is_active(out->dev)) &&
8440 (voice_extn_compress_voip_is_config_supported(config))) {
8441 ret = voice_extn_compress_voip_open_output_stream(out);
8442 if (ret != 0) {
8443 ALOGE("%s: Compress voip output cannot be opened, error:%d",
8444 __func__, ret);
8445 goto error_open;
8446 }
Sujin Panicker19027262019-09-16 18:28:06 +05308447 } else {
8448 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8449 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008450 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008451 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008452 } else if (audio_is_linear_pcm(out->format) &&
8453 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
8454 out->channel_mask = config->channel_mask;
8455 out->sample_rate = config->sample_rate;
8456 out->format = config->format;
8457 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
8458 // does this change?
8459 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
8460 out->config.rate = config->sample_rate;
8461 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
8462 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
8463 audio_bytes_per_sample(config->format));
8464 out->config.format = pcm_format_from_audio_format(out->format);
sasevs1e8c0a02023-04-18 10:41:08 +05308465 } else if ((!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) &&
8466 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Kogara Naveen Kumar86ef8192022-12-08 17:04:51 +05308467 ret = audio_extn_auto_hal_open_output_stream(out);
8468 if (ret) {
8469 ALOGE("%s: Failed to open output stream for bus device", __func__);
8470 ret = -EINVAL;
8471 goto error_open;
8472 }
8473 }else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308474 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308475 pthread_mutex_lock(&adev->lock);
8476 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
8477 pthread_mutex_unlock(&adev->lock);
8478
8479 // reject offload during card offline to allow
8480 // fallback to s/w paths
8481 if (offline) {
8482 ret = -ENODEV;
8483 goto error_open;
8484 }
vivek mehta0ea887a2015-08-26 14:01:20 -07008485
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008486 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
8487 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
8488 ALOGE("%s: Unsupported Offload information", __func__);
8489 ret = -EINVAL;
8490 goto error_open;
8491 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008492
Atul Khare3fa6e542017-08-09 00:56:17 +05308493 if (config->offload_info.format == 0)
8494 config->offload_info.format = config->format;
8495 if (config->offload_info.sample_rate == 0)
8496 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008497
Mingming Yin90310102013-11-13 16:57:00 -08008498 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308499 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07008500 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008501 ret = -EINVAL;
8502 goto error_open;
8503 }
8504
Ben Romberger0f8c87b2017-05-24 17:41:11 -07008505 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
8506 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
8507 (audio_extn_passthru_is_passthrough_stream(out)) &&
8508 !((config->sample_rate == 48000) ||
8509 (config->sample_rate == 96000) ||
8510 (config->sample_rate == 192000))) {
8511 ALOGE("%s: Unsupported sample rate %d for audio format %x",
8512 __func__, config->sample_rate, config->offload_info.format);
8513 ret = -EINVAL;
8514 goto error_open;
8515 }
8516
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008517 out->compr_config.codec = (struct snd_codec *)
8518 calloc(1, sizeof(struct snd_codec));
8519
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008520 if (!out->compr_config.codec) {
8521 ret = -ENOMEM;
8522 goto error_open;
8523 }
8524
Dhananjay Kumarac341582017-02-23 23:42:25 +05308525 out->stream.pause = out_pause;
8526 out->stream.resume = out_resume;
8527 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05308528 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05308529 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07008530 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05308531 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07008532 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05308533 } else {
8534 out->usecase = get_offload_usecase(adev, false /* is_compress */);
8535 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07008536 }
vivek mehta446c3962015-09-14 10:57:35 -07008537
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308538 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8539 ALOGD("%s: Setting latency mode to true", __func__);
Meng Wang4c32fb42020-01-16 17:57:11 +08008540#ifdef AUDIO_GKI_ENABLED
8541 /* out->compr_config.codec->reserved[1] is for flags */
8542 out->compr_config.codec->reserved[1] |= audio_extn_utils_get_perf_mode_flag();
8543#else
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308544 out->compr_config.codec->flags |= audio_extn_utils_get_perf_mode_flag();
Meng Wang4c32fb42020-01-16 17:57:11 +08008545#endif
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308546 }
8547
vivek mehta446c3962015-09-14 10:57:35 -07008548 if (out->usecase == USECASE_INVALID) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008549 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Mingming Yin3a941d42016-02-17 18:08:05 -08008550 config->format == 0 && config->sample_rate == 0 &&
8551 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07008552 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08008553 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
8554 } else {
8555 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
8556 ret = -EEXIST;
8557 goto error_open;
8558 }
vivek mehta446c3962015-09-14 10:57:35 -07008559 }
8560
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008561 if (config->offload_info.channel_mask)
8562 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008563 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008564 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008565 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008566 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05308567 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008568 ret = -EINVAL;
8569 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008570 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008571
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008572 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008573 out->sample_rate = config->offload_info.sample_rate;
8574
Mingming Yin3ee55c62014-08-04 14:23:35 -07008575 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008576
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308577 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05308578 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308579 audio_extn_dolby_send_ddp_endp_params(adev);
8580 audio_extn_dolby_set_dmid(adev);
8581 }
vivek mehta0ea887a2015-08-26 14:01:20 -07008582
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008583 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08008584 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008585 out->compr_config.codec->bit_rate =
8586 config->offload_info.bit_rate;
8587 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05308588 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008589 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05308590 /* Update bit width only for non passthrough usecases.
8591 * For passthrough usecases, the output will always be opened @16 bit
8592 */
8593 if (!audio_extn_passthru_is_passthrough_stream(out))
8594 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308595
8596 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
Meng Wang4c32fb42020-01-16 17:57:11 +08008597#ifdef AUDIO_GKI_ENABLED
8598 /* out->compr_config.codec->reserved[1] is for flags */
8599 out->compr_config.codec->reserved[1] |= COMPRESSED_TIMESTAMP_FLAG;
8600 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->reserved[1]);
8601#else
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308602 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
8603 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
Meng Wang4c32fb42020-01-16 17:57:11 +08008604#endif
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308605
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008606 /*TODO: Do we need to change it for passthrough */
8607 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008608
Manish Dewangana6fc5442015-08-24 20:30:31 +05308609 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
8610 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308611 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05308612 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308613 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
8614 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308615
8616 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
8617 AUDIO_FORMAT_PCM) {
8618
8619 /*Based on platform support, configure appropriate alsa format for corresponding
8620 *hal input format.
8621 */
8622 out->compr_config.codec->format = hal_format_to_alsa(
8623 config->offload_info.format);
8624
Ashish Jain83a6cc22016-06-28 14:34:17 +05308625 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05308626 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308627 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308628
Dhananjay Kumarac341582017-02-23 23:42:25 +05308629 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05308630 *hal input format and alsa format might differ based on platform support.
8631 */
8632 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05308633 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308634
8635 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
8636
Deeraj Soman93155a62019-09-30 19:00:37 +05308637 if (property_get_bool("vendor.audio.offload.buffer.duration.enabled", false)) {
8638 if ((config->offload_info.duration_us >= MIN_OFFLOAD_BUFFER_DURATION_MS * 1000) &&
8639 (config->offload_info.duration_us <= MAX_OFFLOAD_BUFFER_DURATION_MS * 1000))
8640 out->info.duration_us = (int64_t)config->offload_info.duration_us;
8641 }
Deeraj Soman65358ab2019-02-07 15:40:49 +05308642
Ashish Jainf1eaa582016-05-23 20:54:24 +05308643 /* Check if alsa session is configured with the same format as HAL input format,
8644 * if not then derive correct fragment size needed to accomodate the
8645 * conversion of HAL input format to alsa format.
8646 */
8647 audio_extn_utils_update_direct_pcm_fragment_size(out);
8648
8649 /*if hal input and output fragment size is different this indicates HAL input format is
8650 *not same as the alsa format
8651 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308652 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05308653 /*Allocate a buffer to convert input data to the alsa configured format.
8654 *size of convert buffer is equal to the size required to hold one fragment size
8655 *worth of pcm data, this is because flinger does not write more than fragment_size
8656 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308657 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
8658 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05308659 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
8660 ret = -ENOMEM;
8661 goto error_open;
8662 }
8663 }
8664 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
8665 out->compr_config.fragment_size =
8666 audio_extn_passthru_get_buffer_size(&config->offload_info);
8667 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8668 } else {
8669 out->compr_config.fragment_size =
8670 platform_get_compress_offload_buffer_size(&config->offload_info);
8671 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8672 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008673
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308674 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8675 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
8676 }
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008677 if (config->offload_info.format == AUDIO_FORMAT_FLAC) {
8678#ifdef AUDIO_GKI_ENABLED
8679 generic_dec =
8680 &(out->compr_config.codec->options.generic.reserved[1]);
8681 ((struct snd_generic_dec_flac *)generic_dec)->sample_size =
8682 AUDIO_OUTPUT_BIT_WIDTH;
8683#else
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05308684 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008685#endif
8686 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008687
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05308688 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
8689 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
8690 }
8691
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008692 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
8693 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008694
Manish Dewangan69426c82017-01-30 17:35:36 +05308695 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
8696 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
8697 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
8698 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8699 out->render_mode = RENDER_MODE_AUDIO_MASTER;
8700 } else {
8701 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
8702 }
Alexy Josephaa54c872014-12-03 02:46:47 -08008703
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05308704 memset(&out->channel_map_param, 0,
8705 sizeof(struct audio_out_channel_map_param));
8706
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008707 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05308708 out->send_next_track_params = false;
8709 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008710 out->offload_state = OFFLOAD_STATE_IDLE;
8711 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08008712 out->writeAt.tv_sec = 0;
8713 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008714
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008715 audio_extn_dts_create_state_notifier_node(out->usecase);
8716
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008717 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
8718 __func__, config->offload_info.version,
8719 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05308720
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308721 /* Check if DSD audio format is supported in codec
8722 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308723 */
8724
8725 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308726 (!platform_check_codec_dsd_support(adev->platform) ||
8727 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308728 ret = -EINVAL;
8729 goto error_open;
8730 }
8731
Ashish Jain5106d362016-05-11 19:23:33 +05308732 /* Disable gapless if any of the following is true
8733 * passthrough playback
8734 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05308735 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05308736 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308737 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308738 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07008739 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308740 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308741 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05308742 check_and_set_gapless_mode(adev, false);
8743 } else
8744 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07008745
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308746 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07008747 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
8748 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308749 if (config->format == AUDIO_FORMAT_DSD) {
8750 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
Meng Wang4c32fb42020-01-16 17:57:11 +08008751#ifdef AUDIO_GKI_ENABLED
8752 /* out->compr_config.codec->reserved[0] is for compr_passthr */
8753 out->compr_config.codec->reserved[0] = PASSTHROUGH_DSD;
8754#else
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308755 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
Meng Wang4c32fb42020-01-16 17:57:11 +08008756#endif
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308757 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07008758
8759 create_offload_callback_thread(out);
8760
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008761 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008762 switch (config->sample_rate) {
8763 case 0:
8764 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8765 break;
8766 case 8000:
8767 case 16000:
8768 case 48000:
8769 out->sample_rate = config->sample_rate;
8770 break;
8771 default:
8772 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
8773 config->sample_rate);
8774 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8775 ret = -EINVAL;
8776 goto error_open;
8777 }
8778 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8779 switch (config->channel_mask) {
8780 case AUDIO_CHANNEL_NONE:
8781 case AUDIO_CHANNEL_OUT_STEREO:
8782 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8783 break;
8784 default:
8785 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
8786 config->channel_mask);
8787 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8788 ret = -EINVAL;
8789 goto error_open;
8790 }
8791 switch (config->format) {
8792 case AUDIO_FORMAT_DEFAULT:
8793 case AUDIO_FORMAT_PCM_16_BIT:
8794 out->format = AUDIO_FORMAT_PCM_16_BIT;
8795 break;
8796 default:
8797 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
8798 config->format);
8799 config->format = AUDIO_FORMAT_PCM_16_BIT;
8800 ret = -EINVAL;
8801 goto error_open;
8802 }
8803
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05308804 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008805 if (ret != 0) {
8806 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008807 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008808 goto error_open;
8809 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008810 } else if (is_single_device_type_equal(&out->device_list,
8811 AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08008812 switch (config->sample_rate) {
8813 case 0:
8814 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
8815 break;
8816 case 8000:
8817 case 16000:
8818 case 48000:
8819 out->sample_rate = config->sample_rate;
8820 break;
8821 default:
8822 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
8823 config->sample_rate);
8824 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8825 ret = -EINVAL;
8826 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008827 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008828 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8829 switch (config->channel_mask) {
8830 case AUDIO_CHANNEL_NONE:
8831 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8832 break;
8833 case AUDIO_CHANNEL_OUT_STEREO:
8834 out->channel_mask = config->channel_mask;
8835 break;
8836 default:
8837 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
8838 config->channel_mask);
8839 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8840 ret = -EINVAL;
8841 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008842 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008843 switch (config->format) {
8844 case AUDIO_FORMAT_DEFAULT:
8845 out->format = AUDIO_FORMAT_PCM_16_BIT;
8846 break;
8847 case AUDIO_FORMAT_PCM_16_BIT:
8848 out->format = config->format;
8849 break;
8850 default:
8851 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
8852 config->format);
8853 config->format = AUDIO_FORMAT_PCM_16_BIT;
8854 ret = -EINVAL;
8855 break;
8856 }
8857 if (ret != 0)
8858 goto error_open;
8859
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008860 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
8861 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08008862 out->config.rate = out->sample_rate;
8863 out->config.channels =
8864 audio_channel_count_from_out_mask(out->channel_mask);
8865 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008866 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008867 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05308868 unsigned int channels = 0;
8869 /*Update config params to default if not set by the caller*/
8870 if (config->sample_rate == 0)
8871 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8872 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8873 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8874 if (config->format == AUDIO_FORMAT_DEFAULT)
8875 config->format = AUDIO_FORMAT_PCM_16_BIT;
8876
8877 channels = audio_channel_count_from_out_mask(out->channel_mask);
8878
Varun Balaraje49253e2017-07-06 19:48:56 +05308879 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
8880 out->usecase = get_interactive_usecase(adev);
8881 out->config = pcm_config_low_latency;
8882 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05308883 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008884 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
8885 out->flags);
8886 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07008887 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8888 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8889 out->config = pcm_config_mmap_playback;
8890 out->stream.start = out_start;
8891 out->stream.stop = out_stop;
8892 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8893 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308894 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8895 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008896 out->hal_output_suspend_supported =
8897 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
8898 out->dynamic_pm_qos_config_supported =
8899 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
8900 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08008901 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
8902 } else {
8903 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
8904 //the mixer path will be a string similar to "low-latency-playback resume"
8905 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
8906 strlcat(out->pm_qos_mixer_path,
8907 " resume", MAX_MIXER_PATH_LEN);
8908 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
8909 out->pm_qos_mixer_path);
8910 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308911 out->config = pcm_config_low_latency;
8912 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
8913 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
8914 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05308915 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
8916 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
8917 if (out->config.period_size <= 0) {
8918 ALOGE("Invalid configuration period size is not valid");
8919 ret = -EINVAL;
8920 goto error_open;
8921 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008922 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
8923 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
8924 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008925 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
8926 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
8927 out->config = pcm_config_haptics_audio;
8928 if (force_haptic_path)
8929 adev->haptics_config = pcm_config_haptics_audio;
8930 else
8931 adev->haptics_config = pcm_config_haptics;
8932
Meng Wangd08ce322020-04-02 08:59:20 +08008933 channels =
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008934 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
8935
8936 if (force_haptic_path) {
8937 out->config.channels = 1;
8938 adev->haptics_config.channels = 1;
8939 } else
8940 adev->haptics_config.channels = audio_channel_count_from_out_mask(out->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL);
Kogara Naveen Kumar86ef8192022-12-08 17:04:51 +05308941 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05308942 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008943 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8944 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308945 }
8946 out->hal_ip_format = format = out->format;
8947 out->config.format = hal_format_to_pcm(out->hal_ip_format);
8948 out->hal_op_format = pcm_format_to_hal(out->config.format);
8949 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
8950 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008951 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05308952 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308953 if (out->hal_ip_format != out->hal_op_format) {
8954 uint32_t buffer_size = out->config.period_size *
8955 format_to_bitwidth_table[out->hal_op_format] *
8956 out->config.channels;
8957 out->convert_buffer = calloc(1, buffer_size);
8958 if (out->convert_buffer == NULL){
8959 ALOGE("Allocation failed for convert buffer for size %d",
8960 out->compr_config.fragment_size);
8961 ret = -ENOMEM;
8962 goto error_open;
8963 }
8964 ALOGD("Convert buffer allocated of size %d", buffer_size);
8965 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008966 }
8967
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008968 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
8969 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308970
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008971 /* TODO remove this hardcoding and check why width is zero*/
8972 if (out->bit_width == 0)
8973 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308974 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008975 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008976 &out->device_list, out->flags,
8977 out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05308978 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05308979 &out->app_type_cfg);
Kogara Naveen Kumar86ef8192022-12-08 17:04:51 +05308980 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
8981 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08008982 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008983 if(adev->primary_output == NULL)
8984 adev->primary_output = out;
8985 else {
8986 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008987 ret = -EEXIST;
8988 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008989 }
8990 }
8991
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008992 /* Check if this usecase is already existing */
8993 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07008994 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
8995 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008996 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008997 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008998 ret = -EEXIST;
8999 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009000 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009001
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009002 pthread_mutex_unlock(&adev->lock);
9003
9004 out->stream.common.get_sample_rate = out_get_sample_rate;
9005 out->stream.common.set_sample_rate = out_set_sample_rate;
9006 out->stream.common.get_buffer_size = out_get_buffer_size;
9007 out->stream.common.get_channels = out_get_channels;
9008 out->stream.common.get_format = out_get_format;
9009 out->stream.common.set_format = out_set_format;
9010 out->stream.common.standby = out_standby;
9011 out->stream.common.dump = out_dump;
9012 out->stream.common.set_parameters = out_set_parameters;
9013 out->stream.common.get_parameters = out_get_parameters;
9014 out->stream.common.add_audio_effect = out_add_audio_effect;
9015 out->stream.common.remove_audio_effect = out_remove_audio_effect;
9016 out->stream.get_latency = out_get_latency;
9017 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08009018#ifdef NO_AUDIO_OUT
9019 out->stream.write = out_write_for_no_output;
9020#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009021 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08009022#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009023 out->stream.get_render_position = out_get_render_position;
9024 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07009025 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009026
Haynes Mathew George16081042017-05-31 17:16:49 -07009027 if (out->realtime)
9028 out->af_period_multiplier = af_period_multiplier;
9029 else
9030 out->af_period_multiplier = 1;
9031
Andy Hunga1f48fa2019-07-01 18:14:53 -07009032 out->kernel_buffer_size = out->config.period_size * out->config.period_count;
9033
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009034 out->standby = 1;
Zhou Songbaddf9f2020-11-20 13:57:39 +08009035 out->volume_l = PLAYBACK_GAIN_MAX;
9036 out->volume_r = PLAYBACK_GAIN_MAX;
Eric Laurenta9024de2013-04-04 09:19:12 -07009037 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07009038 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009039
9040 config->format = out->stream.common.get_format(&out->stream.common);
9041 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
9042 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05309043 register_format(out->format, out->supported_formats);
9044 register_channel_mask(out->channel_mask, out->supported_channel_masks);
9045 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009046
Dechen Chai22768452021-07-30 09:29:16 +05309047#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -08009048 out->error_log = error_log_create(
9049 ERROR_LOG_ENTRIES,
9050 1000000000 /* aggregate consecutive identical errors within one second in ns */);
Dechen Chai22768452021-07-30 09:29:16 +05309051#endif
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309052 /*
9053 By locking output stream before registering, we allow the callback
9054 to update stream's state only after stream's initial state is set to
9055 adev state.
9056 */
9057 lock_output_stream(out);
9058 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
9059 pthread_mutex_lock(&adev->lock);
9060 out->card_status = adev->card_status;
9061 pthread_mutex_unlock(&adev->lock);
9062 pthread_mutex_unlock(&out->lock);
9063
Aalique Grahame22e49102018-12-18 14:23:57 -08009064 stream_app_type_cfg_init(&out->app_type_cfg);
9065
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009066 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309067 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07009068 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08009069
9070 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
9071 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
9072 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08009073 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05309074 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08009075 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07009076 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05309077 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
9078 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08009079 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
9080 out->usecase, PCM_PLAYBACK);
9081 hdlr_stream_cfg.flags = out->flags;
9082 hdlr_stream_cfg.type = PCM_PLAYBACK;
9083 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
9084 &hdlr_stream_cfg);
9085 if (ret) {
9086 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
9087 out->adsp_hdlr_stream_handle = NULL;
9088 }
9089 }
Gangadhar Sb0210342019-02-22 17:39:41 +05309090 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
9091 is_direct_passthough, false);
9092 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
9093 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07009094 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07009095 if (ret < 0) {
9096 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
9097 out->ip_hdlr_handle = NULL;
9098 }
9099 }
Derek Chenf939fb72018-11-13 13:34:41 -08009100
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009101 ret = io_streams_map_insert(adev, &out->stream.common,
9102 out->handle, AUDIO_PATCH_HANDLE_NONE);
9103 if (ret != 0)
9104 goto error_open;
9105
Susan Wang6dd13092021-01-25 10:27:11 -05009106 out->out_ctxt.output = out;
Derek Chenf939fb72018-11-13 13:34:41 -08009107
9108 pthread_mutex_lock(&adev->lock);
Susan Wang6dd13092021-01-25 10:27:11 -05009109 list_add_tail(&adev->active_outputs_list, &out->out_ctxt.list);
Derek Chenf939fb72018-11-13 13:34:41 -08009110 pthread_mutex_unlock(&adev->lock);
9111
Eric Laurent994a6932013-07-17 11:51:42 -07009112 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009113 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07009114
9115error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05309116 if (out->convert_buffer)
9117 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07009118 free(out);
9119 *stream_out = NULL;
9120 ALOGD("%s: exit: ret %d", __func__, ret);
9121 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009122}
9123
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309124void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009125 struct audio_stream_out *stream)
9126{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07009127 struct stream_out *out = (struct stream_out *)stream;
9128 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009129 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07009130
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009131 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309132
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009133 io_streams_map_remove(adev, out->handle);
9134
Susan Wang6dd13092021-01-25 10:27:11 -05009135 // remove out_ctxt early to prevent the stream
9136 // being opened in a race condition
9137 pthread_mutex_lock(&adev->lock);
9138 list_remove(&out->out_ctxt.list);
9139 pthread_mutex_unlock(&adev->lock);
9140
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309141 // must deregister from sndmonitor first to prevent races
9142 // between the callback and close_stream
9143 audio_extn_snd_mon_unregister_listener(out);
9144
Ben Rombergerd771a7c2017-02-22 18:05:17 -08009145 /* close adsp hdrl session before standby */
9146 if (out->adsp_hdlr_stream_handle) {
9147 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
9148 if (ret)
9149 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
9150 out->adsp_hdlr_stream_handle = NULL;
9151 }
9152
Manish Dewangan21a850a2017-08-14 12:03:55 +05309153 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07009154 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
9155 out->ip_hdlr_handle = NULL;
9156 }
9157
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009158 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309159 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009160 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05309161 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309162 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009163 if(ret != 0)
9164 ALOGE("%s: Compress voip output cannot be closed, error:%d",
9165 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009166 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009167 out_standby(&stream->common);
9168
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07009169 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08009170 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07009171 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07009172 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07009173 if (out->compr_config.codec != NULL)
9174 free(out->compr_config.codec);
9175 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009176
Zhou Songbaddf9f2020-11-20 13:57:39 +08009177 out->a2dp_muted = false;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05309178
Varun Balaraje49253e2017-07-06 19:48:56 +05309179 if (is_interactive_usecase(out->usecase))
9180 free_interactive_usecase(adev, out->usecase);
9181
Ashish Jain83a6cc22016-06-28 14:34:17 +05309182 if (out->convert_buffer != NULL) {
9183 free(out->convert_buffer);
9184 out->convert_buffer = NULL;
9185 }
9186
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009187 if (adev->voice_tx_output == out)
9188 adev->voice_tx_output = NULL;
9189
Dechen Chai22768452021-07-30 09:29:16 +05309190#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -08009191 error_log_destroy(out->error_log);
9192 out->error_log = NULL;
Dechen Chai22768452021-07-30 09:29:16 +05309193#endif
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05309194 if (adev->primary_output == out)
9195 adev->primary_output = NULL;
9196
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07009197 pthread_cond_destroy(&out->cond);
9198 pthread_mutex_destroy(&out->lock);
Weiyin Jiang280ea742020-09-08 20:28:22 +08009199 pthread_mutex_destroy(&out->pre_lock);
9200 pthread_mutex_destroy(&out->latch_lock);
9201 pthread_mutex_destroy(&out->position_query_lock);
Derek Chenf939fb72018-11-13 13:34:41 -08009202
9203 pthread_mutex_lock(&adev->lock);
Zhenlin Lian4f947842022-05-14 15:50:52 +05309204 clear_devices(&out->device_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009205 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08009206 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07009207 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009208}
9209
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05009210void in_set_power_policy(uint8_t enable)
9211{
9212 struct listnode *node;
9213
9214 ALOGD("%s: Enter, state %d", __func__, enable);
9215
9216 pthread_mutex_lock(&adev->lock);
9217 adev->in_power_policy = enable ? POWER_POLICY_STATUS_ONLINE : POWER_POLICY_STATUS_OFFLINE;
9218 pthread_mutex_unlock(&adev->lock);
9219
9220 if (!enable) {
9221 list_for_each(node, &adev->active_inputs_list) {
9222 streams_input_ctxt_t *in_ctxt = node_to_item(node,
9223 streams_input_ctxt_t,
9224 list);
9225 struct stream_in *in = in_ctxt->input;
9226 in_standby(&in->stream.common);
9227 }
9228 }
9229
9230 ALOGD("%s: Exit", __func__);
9231}
9232
9233void out_set_power_policy(uint8_t enable)
9234{
9235 struct listnode *node;
9236
9237 ALOGD("%s: Enter, state %d", __func__, enable);
9238
9239 pthread_mutex_lock(&adev->lock);
E V Ravi317be872022-02-23 19:08:15 +05309240 adev->out_power_policy = enable ? POWER_POLICY_STATUS_ONLINE : POWER_POLICY_STATUS_OFFLINE;
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05009241 pthread_mutex_unlock(&adev->lock);
9242
9243 if (!enable) {
9244 list_for_each(node, &adev->active_outputs_list) {
9245 streams_output_ctxt_t *out_ctxt = node_to_item(node,
9246 streams_output_ctxt_t,
9247 list);
9248 struct stream_out *out = out_ctxt->output;
9249 out_on_error(&out->stream.common);
9250 }
9251 }
9252
9253 ALOGD("%s: Exit", __func__);
9254}
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009255static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
9256{
9257 struct audio_device *adev = (struct audio_device *)dev;
9258 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009259 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07009260 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009261 int ret;
9262 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08009263 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08009264 struct listnode *node;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07009265 int controller = -1, stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009266
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009267 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009268 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009269
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05309270 if (!parms)
9271 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05309272
Derek Chen6f293672019-04-01 01:40:24 -07009273 /* notify adev and input/output streams on the snd card status */
9274 adev_snd_mon_cb((void *)adev, parms);
9275
Weiyin Jiang24f55292020-12-22 14:35:46 +08009276 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
9277 if (ret >= 0) {
9278 list_for_each(node, &adev->active_outputs_list) {
9279 streams_output_ctxt_t *out_ctxt = node_to_item(node,
9280 streams_output_ctxt_t,
9281 list);
9282 out_snd_mon_cb((void *)out_ctxt->output, parms);
9283 }
Derek Chen6f293672019-04-01 01:40:24 -07009284
Weiyin Jiang24f55292020-12-22 14:35:46 +08009285 list_for_each(node, &adev->active_inputs_list) {
9286 streams_input_ctxt_t *in_ctxt = node_to_item(node,
9287 streams_input_ctxt_t,
9288 list);
9289 in_snd_mon_cb((void *)in_ctxt->input, parms);
9290 }
Derek Chen6f293672019-04-01 01:40:24 -07009291 }
9292
Zhou Songd6d71752019-05-21 18:08:51 +08009293 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05309294 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
9295 if (ret >= 0) {
9296 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08009297 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05309298 adev->bt_sco_on = true;
Shalini Manjunatha3a2e06e2021-02-01 12:23:49 +05309299 /*
9300 * When ever BT_SCO=ON arrives, make sure to route
9301 * all use cases to SCO device, otherwise due to delay in
9302 * BT_SCO=ON and lack of synchronization with create audio patch
9303 * request for SCO device, some times use case not routed properly to
9304 * SCO device
9305 */
9306 struct audio_usecase *usecase;
9307 struct listnode *node;
9308 list_for_each(node, &adev->usecase_list) {
9309 usecase = node_to_item(node, struct audio_usecase, list);
Anver sadhiquef0efca32021-09-03 15:25:44 +05309310 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
Anver sadhique93f3c912021-08-11 11:19:45 +05309311 (!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 +05309312 ALOGD("BT_SCO ON, switch all in use case to it");
9313 select_devices(adev, usecase->id);
9314 }
Mingshu Pangef517202021-04-22 10:35:00 +08009315 if (usecase->stream.out && (usecase->type == PCM_PLAYBACK ||
9316 usecase->type == VOICE_CALL) &&
Anver sadhique93f3c912021-08-11 11:19:45 +05309317 (!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 +05309318 ALOGD("BT_SCO ON, switch all out use case to it");
9319 select_devices(adev, usecase->id);
9320 }
9321 }
9322 }
9323 else {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05309324 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08009325 audio_extn_sco_reset_configuration();
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08009326 }
9327 }
9328
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009329 status = voice_set_parameters(adev, parms);
9330 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08009331 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009332
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009333 status = platform_set_parameters(adev->platform, parms);
9334 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08009335 goto done;
9336
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009337 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
9338 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07009339 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009340 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
9341 adev->bluetooth_nrec = true;
9342 else
9343 adev->bluetooth_nrec = false;
9344 }
9345
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009346 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
9347 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009348 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
9349 adev->screen_off = false;
9350 else
9351 adev->screen_off = true;
Quinn Male70f20f32019-06-26 16:50:26 -07009352 audio_extn_sound_trigger_update_screen_status(adev->screen_off);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009353 }
9354
Eric Laurent4b084132018-10-19 17:33:43 -07009355 ret = str_parms_get_int(parms, "rotation", &val);
9356 if (ret >= 0) {
9357 bool reverse_speakers = false;
9358 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
9359 switch (val) {
9360 // FIXME: note that the code below assumes that the speakers are in the correct placement
9361 // relative to the user when the device is rotated 90deg from its default rotation. This
9362 // assumption is device-specific, not platform-specific like this code.
9363 case 270:
9364 reverse_speakers = true;
9365 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
9366 break;
9367 case 0:
9368 case 180:
9369 camera_rotation = CAMERA_ROTATION_PORTRAIT;
9370 break;
9371 case 90:
9372 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
9373 break;
9374 default:
9375 ALOGE("%s: unexpected rotation of %d", __func__, val);
9376 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07009377 }
Eric Laurent4b084132018-10-19 17:33:43 -07009378 if (status == 0) {
9379 // check and set swap
9380 // - check if orientation changed and speaker active
9381 // - set rotation and cache the rotation value
9382 adev->camera_orientation =
9383 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
9384 if (!audio_extn_is_maxx_audio_enabled())
9385 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
9386 }
9387 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07009388
Mingming Yin514a8bc2014-07-29 15:22:21 -07009389 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
9390 if (ret >= 0) {
9391 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
9392 adev->bt_wb_speech_enabled = true;
9393 else
9394 adev->bt_wb_speech_enabled = false;
9395 }
9396
Zhou Song12c29502019-03-16 10:37:18 +08009397 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
9398 if (ret >= 0) {
9399 val = atoi(value);
9400 adev->swb_speech_mode = val;
9401 }
9402
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07009403 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
9404 if (ret >= 0) {
9405 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309406 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08009407 if (audio_is_output_device(val) &&
9408 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07009409 ALOGV("cache new ext disp type and edid");
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07009410 platform_get_controller_stream_from_params(parms, &controller, &stream);
9411 platform_set_ext_display_device_v2(adev->platform, controller, stream);
9412 ret = platform_get_ext_disp_type_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07009413 if (ret < 0) {
9414 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05309415 } else {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07009416 platform_cache_edid_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07009417 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309418 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07009419 /*
9420 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
9421 * Per AudioPolicyManager, USB device is higher priority than WFD.
9422 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
9423 * If WFD use case occupies AFE proxy, it may result unintended behavior while
9424 * starting voice call on USB
9425 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08009426 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309427 if (ret >= 0)
9428 audio_extn_usb_add_device(device, atoi(value));
9429
Zhou Song6f862822017-11-06 17:27:57 +08009430 if (!audio_extn_usb_is_tunnel_supported()) {
9431 ALOGV("detected USB connect .. disable proxy");
9432 adev->allow_afe_proxy_usage = false;
9433 }
Zhou Song503196b2021-07-23 17:31:05 +08009434 } else if (audio_is_hearing_aid_out_device(device) &&
9435 property_get_bool("persist.vendor.audio.ha_proxy.enabled", false)) {
9436 adev->ha_proxy_enable = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07009437 }
9438 }
9439
9440 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
9441 if (ret >= 0) {
9442 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309443 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07009444 /*
9445 * The HDMI / Displayport disconnect handling has been moved to
9446 * audio extension to ensure that its parameters are not
9447 * invalidated prior to updating sysfs of the disconnect event
9448 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
9449 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309450 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08009451 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309452 if (ret >= 0)
9453 audio_extn_usb_remove_device(device, atoi(value));
9454
Zhou Song6f862822017-11-06 17:27:57 +08009455 if (!audio_extn_usb_is_tunnel_supported()) {
9456 ALOGV("detected USB disconnect .. enable proxy");
9457 adev->allow_afe_proxy_usage = true;
9458 }
Zhou Song503196b2021-07-23 17:31:05 +08009459 } else if (audio_is_hearing_aid_out_device(device)) {
9460 adev->ha_proxy_enable = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07009461 }
9462 }
9463
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009464 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08009465
9466 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08009467 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309468 struct audio_usecase *usecase;
9469 struct listnode *node;
9470 list_for_each(node, &adev->usecase_list) {
9471 usecase = node_to_item(node, struct audio_usecase, list);
Weiyin Jiangff56ff32020-05-08 14:32:21 +08009472 if ((usecase->stream.out == NULL) || (usecase->type != PCM_PLAYBACK))
9473 continue;
9474
9475 if (is_a2dp_out_device_type(&usecase->device_list)) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309476 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05309477 audio_extn_a2dp_set_handoff_mode(true);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05309478 ALOGD("Switching to speaker and muting the stream before select_devices");
9479 check_a2dp_restore_l(adev, usecase->stream.out, false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309480 //force device switch to re configure encoder
9481 select_devices(adev, usecase->id);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05309482 ALOGD("Unmuting the stream after select_devices");
Zhou Songbaddf9f2020-11-20 13:57:39 +08009483 check_a2dp_restore_l(adev, usecase->stream.out, true);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05309484 audio_extn_a2dp_set_handoff_mode(false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309485 break;
Zhou Songd01e7a22020-09-23 22:49:01 +08009486 } else if (is_offload_usecase(usecase->stream.out->usecase)) {
Weiyin Jiang280ea742020-09-08 20:28:22 +08009487 pthread_mutex_lock(&usecase->stream.out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +08009488 if (usecase->stream.out->a2dp_muted) {
Weiyin Jiang280ea742020-09-08 20:28:22 +08009489 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
9490 reassign_device_list(&usecase->stream.out->device_list,
9491 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, "");
9492 check_a2dp_restore_l(adev, usecase->stream.out, true);
9493 break;
9494 }
9495 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309496 }
9497 }
9498 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009499
9500 //handle vr audio setparam
9501 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9502 value, sizeof(value));
9503 if (ret >= 0) {
9504 ALOGI("Setting vr mode to be %s", value);
9505 if (!strncmp(value, "true", 4)) {
9506 adev->vr_audio_mode_enabled = true;
9507 ALOGI("Setting vr mode to true");
9508 } else if (!strncmp(value, "false", 5)) {
9509 adev->vr_audio_mode_enabled = false;
9510 ALOGI("Setting vr mode to false");
9511 } else {
9512 ALOGI("wrong vr mode set");
9513 }
9514 }
9515
Eric Laurent4b084132018-10-19 17:33:43 -07009516 //FIXME: to be replaced by proper video capture properties API
9517 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
9518 if (ret >= 0) {
9519 int camera_facing = CAMERA_FACING_BACK;
9520 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
9521 camera_facing = CAMERA_FACING_FRONT;
9522 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
9523 camera_facing = CAMERA_FACING_BACK;
9524 else {
9525 ALOGW("%s: invalid camera facing value: %s", __func__, value);
9526 goto done;
9527 }
9528 adev->camera_orientation =
9529 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
9530 struct audio_usecase *usecase;
9531 struct listnode *node;
9532 list_for_each(node, &adev->usecase_list) {
9533 usecase = node_to_item(node, struct audio_usecase, list);
9534 struct stream_in *in = usecase->stream.in;
9535 if (usecase->type == PCM_CAPTURE && in != NULL &&
9536 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
9537 select_devices(adev, in->usecase);
9538 }
9539 }
9540 }
9541
Tahir Dawson7fabad42022-06-21 12:37:55 -04009542 audio_extn_auto_hal_set_parameters(adev, parms);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05309543 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08009544done:
9545 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009546 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05309547error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009548 ALOGV("%s: exit with code(%d)", __func__, status);
9549 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009550}
9551
9552static char* adev_get_parameters(const struct audio_hw_device *dev,
9553 const char *keys)
9554{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05309555 ALOGD("%s:%s", __func__, keys);
9556
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009557 struct audio_device *adev = (struct audio_device *)dev;
9558 struct str_parms *reply = str_parms_create();
9559 struct str_parms *query = str_parms_create_str(keys);
9560 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05309561 char value[256] = {0};
9562 int ret = 0;
9563
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009564 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08009565 if (reply) {
9566 str_parms_destroy(reply);
9567 }
9568 if (query) {
9569 str_parms_destroy(query);
9570 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009571 ALOGE("adev_get_parameters: failed to create query or reply");
9572 return NULL;
9573 }
9574
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009575 //handle vr audio getparam
9576
9577 ret = str_parms_get_str(query,
9578 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9579 value, sizeof(value));
9580
9581 if (ret >= 0) {
9582 bool vr_audio_enabled = false;
9583 pthread_mutex_lock(&adev->lock);
9584 vr_audio_enabled = adev->vr_audio_mode_enabled;
9585 pthread_mutex_unlock(&adev->lock);
9586
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07009587 ALOGV("getting vr mode to %d", vr_audio_enabled);
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009588
9589 if (vr_audio_enabled) {
9590 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9591 "true");
9592 goto exit;
9593 } else {
9594 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9595 "false");
9596 goto exit;
9597 }
9598 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009599
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009600 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009601 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08009602 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08009603 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009604 platform_get_parameters(adev->platform, query, reply);
justinwengd5395152019-11-04 12:23:09 +08009605 audio_extn_ma_get_parameters(adev, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05309606 pthread_mutex_unlock(&adev->lock);
9607
Naresh Tannirud7205b62014-06-20 02:54:48 +05309608exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009609 str = str_parms_to_str(reply);
9610 str_parms_destroy(query);
9611 str_parms_destroy(reply);
9612
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07009613 ALOGV("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009614 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009615}
9616
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009617static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009618{
9619 return 0;
9620}
9621
9622static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
9623{
Haynes Mathew George5191a852013-09-11 14:19:36 -07009624 int ret;
9625 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08009626
9627 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
9628
Haynes Mathew George5191a852013-09-11 14:19:36 -07009629 pthread_mutex_lock(&adev->lock);
9630 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07009631 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07009632 pthread_mutex_unlock(&adev->lock);
9633 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009634}
9635
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009636static int adev_set_master_volume(struct audio_hw_device *dev __unused,
9637 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009638{
9639 return -ENOSYS;
9640}
9641
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009642static int adev_get_master_volume(struct audio_hw_device *dev __unused,
9643 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009644{
9645 return -ENOSYS;
9646}
9647
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009648static int adev_set_master_mute(struct audio_hw_device *dev __unused,
9649 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009650{
9651 return -ENOSYS;
9652}
9653
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009654static int adev_get_master_mute(struct audio_hw_device *dev __unused,
9655 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009656{
9657 return -ENOSYS;
9658}
9659
9660static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
9661{
9662 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07009663 struct listnode *node;
9664 struct audio_usecase *usecase = NULL;
9665 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08009666
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009667 pthread_mutex_lock(&adev->lock);
9668 if (adev->mode != mode) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309669 ALOGD("%s: mode %d , prev_mode %d \n", __func__, mode , adev->mode);
9670 adev->prev_mode = adev->mode; /* prev_mode is kept to handle voip concurrency*/
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009671 adev->mode = mode;
Weiyin Jiang96b96f72020-09-22 16:48:19 +08009672 if (mode == AUDIO_MODE_CALL_SCREEN) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309673 adev->current_call_output = adev->primary_output;
9674 voice_start_call(adev);
9675 } else if (voice_is_in_call_or_call_screen(adev) &&
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08009676 (mode == AUDIO_MODE_NORMAL ||
9677 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07009678 list_for_each(node, &adev->usecase_list) {
9679 usecase = node_to_item(node, struct audio_usecase, list);
9680 if (usecase->type == VOICE_CALL)
9681 break;
9682 }
9683 if (usecase &&
9684 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
9685 ret = audio_extn_usb_check_and_set_svc_int(usecase,
9686 true);
9687 if (ret != 0) {
9688 /* default service interval was successfully updated,
9689 reopen USB backend with new service interval */
9690 check_usecases_codec_backend(adev,
9691 usecase,
9692 usecase->out_snd_device);
9693 }
9694 }
9695
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009696 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07009697 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009698 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08009699 // restore device for other active usecases after stop call
9700 list_for_each(node, &adev->usecase_list) {
9701 usecase = node_to_item(node, struct audio_usecase, list);
9702 select_devices(adev, usecase->id);
9703 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009704 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009705 }
9706 pthread_mutex_unlock(&adev->lock);
9707 return 0;
9708}
9709
9710static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
9711{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009712 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08009713 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009714
9715 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08009716 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009717 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009718
Derek Chend2530072014-11-24 12:39:14 -08009719 if (adev->ext_hw_plugin)
9720 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009721
9722 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009723 pthread_mutex_unlock(&adev->lock);
9724
9725 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009726}
9727
9728static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
9729{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009730 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009731 return 0;
9732}
9733
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009734static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009735 const struct audio_config *config)
9736{
Avinash Chandrad7296d42021-08-04 15:07:47 +05309737 bool is_usb_hifi = IS_USB_HIFI;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009738 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009739
Aalique Grahame22e49102018-12-18 14:23:57 -08009740 /* Don't know if USB HIFI in this context so use true to be conservative */
9741 if (check_input_parameters(config->sample_rate, config->format, channel_count,
Avinash Chandrad7296d42021-08-04 15:07:47 +05309742 is_usb_hifi) != 0)
Aalique Grahame22e49102018-12-18 14:23:57 -08009743 return 0;
9744
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009745 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
9746 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009747}
9748
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009749static bool adev_input_allow_hifi_record(struct audio_device *adev,
9750 audio_devices_t devices,
9751 audio_input_flags_t flags,
9752 audio_source_t source) {
9753 const bool allowed = true;
9754
9755 if (!audio_is_usb_in_device(devices))
9756 return !allowed;
9757
9758 switch (flags) {
9759 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009760 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07009761 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
9762 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009763 default:
9764 return !allowed;
9765 }
9766
9767 switch (source) {
9768 case AUDIO_SOURCE_DEFAULT:
9769 case AUDIO_SOURCE_MIC:
9770 case AUDIO_SOURCE_UNPROCESSED:
9771 break;
9772 default:
9773 return !allowed;
9774 }
9775
9776 switch (adev->mode) {
9777 case 0:
9778 break;
9779 default:
9780 return !allowed;
9781 }
9782
9783 return allowed;
9784}
9785
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009786static int adev_update_voice_comm_input_stream(struct stream_in *in,
9787 struct audio_config *config)
9788{
9789 bool valid_rate = (config->sample_rate == 8000 ||
9790 config->sample_rate == 16000 ||
9791 config->sample_rate == 32000 ||
9792 config->sample_rate == 48000);
9793 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
9794
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009795 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08009796 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009797 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9798 in->config = default_pcm_config_voip_copp;
9799 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
9800 DEFAULT_VOIP_BUF_DURATION_MS,
9801 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009802 } else {
9803 ALOGW("%s No valid input in voip, use defaults"
9804 "sample rate %u, channel mask 0x%X",
9805 __func__, config->sample_rate, in->channel_mask);
9806 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009807 in->config.rate = config->sample_rate;
9808 in->sample_rate = config->sample_rate;
9809 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009810 //XXX needed for voice_extn_compress_voip_open_input_stream
9811 in->config.rate = config->sample_rate;
9812 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
Shalini Manjunathaa763cc42019-08-23 15:13:46 +05309813 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009814 voice_extn_compress_voip_is_active(in->dev)) &&
9815 (voice_extn_compress_voip_is_format_supported(in->format)) &&
9816 valid_rate && valid_ch) {
9817 voice_extn_compress_voip_open_input_stream(in);
9818 // update rate entries to match config from AF
9819 in->config.rate = config->sample_rate;
9820 in->sample_rate = config->sample_rate;
9821 } else {
9822 ALOGW("%s compress voip not active, use defaults", __func__);
9823 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009824 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009825 return 0;
9826}
9827
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009828static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07009829 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009830 audio_devices_t devices,
9831 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009832 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309833 audio_input_flags_t flags,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009834 const char *address,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009835 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009836{
9837 struct audio_device *adev = (struct audio_device *)dev;
9838 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009839 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009840 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009841 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05309842 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009843 bool is_usb_dev = audio_is_usb_in_device(devices);
9844 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
9845 devices,
9846 flags,
9847 source);
Andy Hung94320602018-10-29 18:31:12 -07009848 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
9849 " sample_rate %u, channel_mask %#x, format %#x",
9850 __func__, flags, is_usb_dev, may_use_hifi_record,
9851 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309852
kunleizdff872d2018-08-20 14:40:33 +08009853 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08009854 is_usb_dev = false;
9855 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
9856 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
9857 __func__, devices);
9858 }
9859
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009860 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009861
9862 if (!(is_usb_dev && may_use_hifi_record)) {
9863 if (config->sample_rate == 0)
9864 config->sample_rate = 48000;
9865 if (config->channel_mask == AUDIO_CHANNEL_NONE)
9866 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9867 if (config->format == AUDIO_FORMAT_DEFAULT)
9868 config->format = AUDIO_FORMAT_PCM_16_BIT;
9869
9870 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
9871
Aalique Grahame22e49102018-12-18 14:23:57 -08009872 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9873 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009874 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05309875 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009876
9877 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009878
9879 if (!in) {
9880 ALOGE("failed to allocate input stream");
9881 return -ENOMEM;
9882 }
9883
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309884 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05309885 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
9886 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009887 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07009888 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009889
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009890 in->stream.common.get_sample_rate = in_get_sample_rate;
9891 in->stream.common.set_sample_rate = in_set_sample_rate;
9892 in->stream.common.get_buffer_size = in_get_buffer_size;
9893 in->stream.common.get_channels = in_get_channels;
9894 in->stream.common.get_format = in_get_format;
9895 in->stream.common.set_format = in_set_format;
9896 in->stream.common.standby = in_standby;
9897 in->stream.common.dump = in_dump;
9898 in->stream.common.set_parameters = in_set_parameters;
9899 in->stream.common.get_parameters = in_get_parameters;
9900 in->stream.common.add_audio_effect = in_add_audio_effect;
9901 in->stream.common.remove_audio_effect = in_remove_audio_effect;
9902 in->stream.set_gain = in_set_gain;
9903 in->stream.read = in_read;
9904 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08009905 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309906 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07009907 in->stream.set_microphone_direction = in_set_microphone_direction;
9908 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07009909 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009910
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009911 list_init(&in->device_list);
9912 update_device_list(&in->device_list, devices, address, true);
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009913 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009914 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009915 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009916 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009917 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07009918 in->bit_width = 16;
9919 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07009920 in->direction = MIC_DIRECTION_UNSPECIFIED;
9921 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08009922 list_init(&in->aec_list);
9923 list_init(&in->ns_list);
Phil Burkd898ba62019-06-20 12:49:01 -07009924 in->mmap_shared_memory_fd = -1; // not open
Haynes Mathew George46740472017-10-27 18:40:12 -07009925
Andy Hung94320602018-10-29 18:31:12 -07009926 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08009927 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
9928 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
9929 /* Force channel config requested to mono if incall
9930 record is being requested for only uplink/downlink */
9931 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
9932 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9933 ret = -EINVAL;
9934 goto err_open;
9935 }
9936 }
9937
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009938 if (is_usb_dev && may_use_hifi_record) {
9939 /* HiFi record selects an appropriate format, channel, rate combo
9940 depending on sink capabilities*/
9941 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
9942 &config->format,
9943 &in->supported_formats[0],
9944 MAX_SUPPORTED_FORMATS,
9945 &config->channel_mask,
9946 &in->supported_channel_masks[0],
9947 MAX_SUPPORTED_CHANNEL_MASKS,
9948 &config->sample_rate,
9949 &in->supported_sample_rates[0],
9950 MAX_SUPPORTED_SAMPLE_RATES);
9951 if (ret != 0) {
9952 ret = -EINVAL;
9953 goto err_open;
9954 }
9955 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009956 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309957 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05309958 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
9959 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
9960 in->config.format = PCM_FORMAT_S32_LE;
9961 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309962 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
9963 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
9964 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
9965 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
9966 bool ret_error = false;
9967 in->bit_width = 24;
9968 /* 24 bit is restricted to UNPROCESSED source only,also format supported
9969 from HAL is 24_packed and 8_24
9970 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
9971 24_packed return error indicating supported format is 24_packed
9972 *> In case of any other source requesting 24 bit or float return error
9973 indicating format supported is 16 bit only.
9974
9975 on error flinger will retry with supported format passed
9976 */
9977 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
9978 (source != AUDIO_SOURCE_CAMCORDER)) {
9979 config->format = AUDIO_FORMAT_PCM_16_BIT;
9980 if (config->sample_rate > 48000)
9981 config->sample_rate = 48000;
9982 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07009983 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
9984 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309985 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
9986 ret_error = true;
9987 }
9988
9989 if (ret_error) {
9990 ret = -EINVAL;
9991 goto err_open;
9992 }
9993 }
9994
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009995 in->channel_mask = config->channel_mask;
9996 in->format = config->format;
9997
9998 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309999
Huicheng Liu1404ba12020-09-11 01:03:25 -040010000 /* validate bus device address */
10001 if (compare_device_type(&in->device_list, AUDIO_DEVICE_IN_BUS)) {
10002 /* extract car audio stream index */
10003 in->car_audio_stream =
10004 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
10005 if (in->car_audio_stream < 0) {
10006 ALOGE("%s: invalid car audio stream %x",
10007 __func__, in->car_audio_stream);
10008 ret = -EINVAL;
10009 goto err_open;
10010 }
10011 ALOGV("%s: car_audio_stream 0x%x", __func__, in->car_audio_stream);
Huicheng Liuea4fd422021-01-12 18:34:50 -050010012 ret = audio_extn_auto_hal_open_input_stream(in);
10013 if (ret) {
10014 ALOGE("%s: Failed to open input stream for bus device", __func__);
10015 ret = -EINVAL;
10016 goto err_open;
10017 }
Huicheng Liu1404ba12020-09-11 01:03:25 -040010018 }
10019
Susan Wange3959562021-03-11 11:50:26 -050010020 /* reassign use case for echo reference stream on automotive platforms */
10021 if (in->source == AUDIO_SOURCE_ECHO_REFERENCE) {
10022 ret = audio_extn_auto_hal_open_echo_reference_stream(in);
10023 }
10024
Kogara Naveen Kumar379ff692022-01-31 11:56:51 +053010025 if ((in->source == AUDIO_SOURCE_FM_TUNER) || (devices == AUDIO_DEVICE_IN_FM_TUNER)) {
Samyak Jain0aa07ab2019-04-04 14:36:32 +053010026 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
10027 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
10028 else {
10029 ret = -EINVAL;
10030 goto err_open;
10031 }
10032 }
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +053010033#ifdef PLATFORM_AUTO
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +053010034 if ((config->sample_rate == 48000 ||
10035 config->sample_rate == 32000 ||
10036 config->sample_rate == 24000 ||
10037 config->sample_rate == 16000 ||
10038 config->sample_rate == 8000)&&
Deeraj Somanfa377bf2019-02-06 12:57:59 +053010039 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
10040 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +053010041 (flags & AUDIO_INPUT_FLAG_FAST) != 0)
10042#else
10043 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
10044 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
10045 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
10046 (flags & AUDIO_INPUT_FLAG_FAST) != 0)
10047#endif
10048{
Haynes Mathew George484e8d22017-07-31 18:55:17 -070010049 is_low_latency = true;
10050#if LOW_LATENCY_CAPTURE_USE_CASE
Revathi Uddarajud9f23d92020-07-27 10:55:06 +053010051 if ((flags & AUDIO_INPUT_FLAG_VOIP_TX) != 0)
10052 in->usecase = USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY;
10053 else
10054 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Haynes Mathew George484e8d22017-07-31 18:55:17 -070010055#endif
10056 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -080010057 if (!in->realtime) {
10058 in->config = pcm_config_audio_capture;
10059 frame_size = audio_stream_in_frame_size(&in->stream);
10060 buffer_size = get_input_buffer_size(config->sample_rate,
10061 config->format,
10062 channel_count,
10063 is_low_latency);
10064 in->config.period_size = buffer_size / frame_size;
10065 in->config.rate = config->sample_rate;
10066 in->af_period_multiplier = 1;
10067 } else {
10068 // period size is left untouched for rt mode playback
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +053010069#ifdef PLATFORM_AUTO
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +053010070 switch(config->sample_rate)
10071 {
10072 case 48000:
10073 in->config = pcm_config_audio_capture_rt_48KHz;
10074 break;
10075 case 32000:
10076 in->config = pcm_config_audio_capture_rt_32KHz;
10077 break;
10078 case 24000:
10079 in->config = pcm_config_audio_capture_rt_24KHz;
10080 break;
10081 case 16000:
10082 in->config = pcm_config_audio_capture_rt_16KHz;
10083 break;
10084 case 8000:
10085 in->config = pcm_config_audio_capture_rt_8KHz;
10086 break;
10087 default:
10088 in->config = pcm_config_audio_capture_rt_48KHz;
10089 }
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +053010090#else
10091 in->config = pcm_config_audio_capture_rt_48KHz;
10092#endif
Aalique Grahame22e49102018-12-18 14:23:57 -080010093 in->af_period_multiplier = af_period_multiplier;
10094 }
Kogara Naveen Kumarc5758232022-11-07 20:25:40 +053010095
10096 /* assign concurrent capture usecase if record has to caried out from
10097 * actual hardware input source */
10098 if (audio_extn_is_concurrent_capture_enabled() &&
10099 !audio_is_virtual_input_source(in->source)) {
10100 /* Acquire lock to avoid two concurrent use cases initialized to
10101 same pcm record use case */
10102 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY) {
10103 pthread_mutex_lock(&adev->lock);
10104 if (!(adev->pcm_low_latency_record_uc_state)) {
10105 ALOGD("%s: using USECASE_AUDIO_RECORD_LOW_LATENCY",__func__);
10106 adev->pcm_low_latency_record_uc_state = 1;
10107 pthread_mutex_unlock(&adev->lock);
10108 } else if (audio_extn_is_concurrent_low_latency_pcm_record_enabled()) {
10109 in->usecase = get_low_latency_record_usecase(adev);
10110 pthread_mutex_unlock(&adev->lock);
10111 } else {
10112 pthread_mutex_unlock(&adev->lock);
10113 /* Assign compress record use case for second record */
10114 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
10115 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
10116 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
10117 if (audio_extn_cin_applicable_stream(in)) {
10118 in->sample_rate = config->sample_rate;
10119 ret = audio_extn_cin_configure_input_stream(in, config);
10120 if (ret)
10121 goto err_open;
10122 }
10123 }
10124 }
10125 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -070010126 }
10127
Susan Wangb803cb52021-10-14 12:03:36 -040010128 /* Additional sample rates added below must also be present
10129 in audio_policy_configuration.xml for mmap_no_irq_in */
10130 bool valid_mmap_record_rate = (config->sample_rate == 8000 ||
10131 config->sample_rate == 16000 ||
Susan Wang89da9042021-10-14 12:03:36 -040010132 config->sample_rate == 24000 ||
Susan Wangb803cb52021-10-14 12:03:36 -040010133 config->sample_rate == 32000 ||
10134 config->sample_rate == 48000);
10135 if (valid_mmap_record_rate &&
10136 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -070010137 in->realtime = 0;
10138 in->usecase = USECASE_AUDIO_RECORD_MMAP;
10139 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -070010140 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -070010141 in->stream.start = in_start;
10142 in->stream.stop = in_stop;
10143 in->stream.create_mmap_buffer = in_create_mmap_buffer;
10144 in->stream.get_mmap_position = in_get_mmap_position;
Ramjee Singhbcb3b6c2021-11-17 13:19:16 +053010145 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -070010146 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
Haynes Mathew George46740472017-10-27 18:40:12 -070010147 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -070010148 in->usecase = USECASE_AUDIO_RECORD_HIFI;
10149 in->config = pcm_config_audio_capture;
10150 frame_size = audio_stream_in_frame_size(&in->stream);
10151 buffer_size = get_input_buffer_size(config->sample_rate,
10152 config->format,
10153 channel_count,
10154 false /*is_low_latency*/);
10155 in->config.period_size = buffer_size / frame_size;
10156 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -070010157 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -070010158 switch (config->format) {
10159 case AUDIO_FORMAT_PCM_32_BIT:
10160 in->bit_width = 32;
10161 break;
10162 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
10163 case AUDIO_FORMAT_PCM_8_24_BIT:
10164 in->bit_width = 24;
10165 break;
10166 default:
10167 in->bit_width = 16;
10168 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010169 } else if (is_single_device_type_equal(&in->device_list,
10170 AUDIO_DEVICE_IN_TELEPHONY_RX) ||
10171 is_single_device_type_equal(&in->device_list,
10172 AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070010173 if (config->sample_rate == 0)
10174 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
10175 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
10176 config->sample_rate != 8000) {
10177 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
10178 ret = -EINVAL;
10179 goto err_open;
10180 }
10181 if (config->format == AUDIO_FORMAT_DEFAULT)
10182 config->format = AUDIO_FORMAT_PCM_16_BIT;
10183 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
10184 config->format = AUDIO_FORMAT_PCM_16_BIT;
10185 ret = -EINVAL;
10186 goto err_open;
10187 }
10188
10189 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
Zhou Song62ea0282020-03-22 19:53:01 +080010190 if (adev->ha_proxy_enable &&
10191 is_single_device_type_equal(&in->device_list,
10192 AUDIO_DEVICE_IN_TELEPHONY_RX))
10193 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY2;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070010194 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070010195 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -080010196 in->af_period_multiplier = 1;
10197 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
Shalini Manjunathaac412b32020-01-03 15:00:14 +053010198 (!voice_extn_is_compress_voip_supported()) &&
Aalique Grahame22e49102018-12-18 14:23:57 -080010199 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
10200 (config->sample_rate == 8000 ||
10201 config->sample_rate == 16000 ||
10202 config->sample_rate == 32000 ||
10203 config->sample_rate == 48000) &&
10204 channel_count == 1) {
10205 in->usecase = USECASE_AUDIO_RECORD_VOIP;
10206 in->config = pcm_config_audio_capture;
10207 frame_size = audio_stream_in_frame_size(&in->stream);
10208 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
10209 config->sample_rate,
10210 config->format,
10211 channel_count, false /*is_low_latency*/);
10212 in->config.period_size = buffer_size / frame_size;
10213 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
10214 in->config.rate = config->sample_rate;
10215 in->af_period_multiplier = 1;
Mingshu Pangc2d65042021-01-14 16:19:10 +080010216 } else if (in->realtime) {
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +053010217#ifdef PLATFORM_AUTO
Kogara Naveen Kumara688a812022-04-27 16:45:59 +053010218 switch(config->sample_rate)
10219 {
10220 case 48000:
10221 in->config = pcm_config_audio_capture_rt_48KHz;
10222 break;
10223 case 32000:
10224 in->config = pcm_config_audio_capture_rt_32KHz;
10225 break;
10226 case 24000:
10227 in->config = pcm_config_audio_capture_rt_24KHz;
10228 break;
10229 case 16000:
10230 in->config = pcm_config_audio_capture_rt_16KHz;
10231 break;
10232 case 8000:
10233 in->config = pcm_config_audio_capture_rt_8KHz;
10234 break;
10235 default:
10236 in->config = pcm_config_audio_capture_rt_48KHz;
10237 }
Mingshu Pangc2d65042021-01-14 16:19:10 +080010238 in->config.format = pcm_format_from_audio_format(config->format);
10239 in->af_period_multiplier = af_period_multiplier;
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +053010240#else
10241 in->config = pcm_config_audio_capture_rt_48KHz;
10242#endif
10243} else {
Revathi Uddarajud2634032017-12-07 14:42:34 +053010244 int ret_val;
10245 pthread_mutex_lock(&adev->lock);
10246 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
10247 in, config, &channel_mask_updated);
10248 pthread_mutex_unlock(&adev->lock);
10249
10250 if (!ret_val) {
10251 if (channel_mask_updated == true) {
10252 ALOGD("%s: return error to retry with updated channel mask (%#x)",
10253 __func__, config->channel_mask);
10254 ret = -EINVAL;
10255 goto err_open;
10256 }
10257 ALOGD("%s: created multi-channel session succesfully",__func__);
10258 } else if (audio_extn_compr_cap_enabled() &&
10259 audio_extn_compr_cap_format_supported(config->format) &&
10260 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
10261 audio_extn_compr_cap_init(in);
10262 } else if (audio_extn_cin_applicable_stream(in)) {
Deeraj Soman14230922019-01-30 16:39:30 +053010263 ret = audio_extn_cin_configure_input_stream(in, config);
Revathi Uddarajud2634032017-12-07 14:42:34 +053010264 if (ret)
10265 goto err_open;
10266 } else {
10267 in->config = pcm_config_audio_capture;
10268 in->config.rate = config->sample_rate;
10269 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +053010270 in->format = config->format;
10271 frame_size = audio_stream_in_frame_size(&in->stream);
10272 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -070010273 config->format,
10274 channel_count,
10275 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +020010276 /* prevent division-by-zero */
10277 if (frame_size == 0) {
10278 ALOGE("%s: Error frame_size==0", __func__);
10279 ret = -EINVAL;
10280 goto err_open;
10281 }
10282
Revathi Uddarajud2634032017-12-07 14:42:34 +053010283 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -080010284 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -080010285
Revathi Uddarajud2634032017-12-07 14:42:34 +053010286 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
10287 /* optionally use VOIP usecase depending on config(s) */
10288 ret = adev_update_voice_comm_input_stream(in, config);
10289 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -080010290
Revathi Uddarajud2634032017-12-07 14:42:34 +053010291 if (ret) {
10292 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
10293 goto err_open;
10294 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -080010295 }
Jaideep Sharmad305a4a2020-02-27 14:29:04 +053010296
10297 /* assign concurrent capture usecase if record has to caried out from
10298 * actual hardware input source */
10299 if (audio_extn_is_concurrent_capture_enabled() &&
10300 !audio_is_virtual_input_source(in->source)) {
Samyak Jainc37062f2019-04-25 18:41:06 +053010301 /* Acquire lock to avoid two concurrent use cases initialized to
10302 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +080010303
Samyak Jainc37062f2019-04-25 18:41:06 +053010304 if (in->usecase == USECASE_AUDIO_RECORD) {
10305 pthread_mutex_lock(&adev->lock);
10306 if (!(adev->pcm_record_uc_state)) {
10307 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
10308 adev->pcm_record_uc_state = 1;
10309 pthread_mutex_unlock(&adev->lock);
Krishna Kishor Jha0f4d8482022-02-18 10:56:05 +053010310 } else if (audio_extn_is_concurrent_pcm_record_enabled()) {
10311 in->usecase = get_record_usecase(adev);
10312 pthread_mutex_unlock(&adev->lock);
Samyak Jainc37062f2019-04-25 18:41:06 +053010313 } else {
10314 pthread_mutex_unlock(&adev->lock);
10315 /* Assign compress record use case for second record */
10316 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
10317 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
10318 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
10319 if (audio_extn_cin_applicable_stream(in)) {
10320 in->sample_rate = config->sample_rate;
Deeraj Soman14230922019-01-30 16:39:30 +053010321 ret = audio_extn_cin_configure_input_stream(in, config);
Samyak Jainc37062f2019-04-25 18:41:06 +053010322 if (ret)
10323 goto err_open;
10324 }
10325 }
10326 }
kunleiz28c73e72019-03-27 17:24:04 +080010327 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -070010328 }
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +053010329
Ramjee Singh82fd0c12019-08-21 16:31:33 +053010330 if (audio_extn_ssr_get_stream() != in)
10331 in->config.channels = channel_count;
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -070010332
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -070010333 in->sample_rate = in->config.rate;
10334
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010335 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
10336 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010337 &in->device_list, flags, in->format,
Haynes Mathew George4ffef292017-11-21 15:08:02 -080010338 in->sample_rate, in->bit_width,
10339 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +053010340 register_format(in->format, in->supported_formats);
10341 register_channel_mask(in->channel_mask, in->supported_channel_masks);
10342 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010343
Dechen Chai22768452021-07-30 09:29:16 +053010344#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -080010345 in->error_log = error_log_create(
10346 ERROR_LOG_ENTRIES,
10347 1000000000 /* aggregate consecutive identical errors within one second */);
Dechen Chai22768452021-07-30 09:29:16 +053010348#endif
Aalique Grahame22e49102018-12-18 14:23:57 -080010349
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010350 /* This stream could be for sound trigger lab,
10351 get sound trigger pcm if present */
10352 audio_extn_sound_trigger_check_and_get_session(in);
10353
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010354 lock_input_stream(in);
10355 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
10356 pthread_mutex_lock(&adev->lock);
10357 in->card_status = adev->card_status;
10358 pthread_mutex_unlock(&adev->lock);
10359 pthread_mutex_unlock(&in->lock);
10360
Aalique Grahame22e49102018-12-18 14:23:57 -080010361 stream_app_type_cfg_init(&in->app_type_cfg);
10362
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010363 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -080010364
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010365 ret = io_streams_map_insert(adev, &in->stream.common,
10366 handle, AUDIO_PATCH_HANDLE_NONE);
10367 if (ret != 0)
10368 goto err_open;
10369
Susan Wang6dd13092021-01-25 10:27:11 -050010370 in->in_ctxt.input = in;
Derek Chenf939fb72018-11-13 13:34:41 -080010371
10372 pthread_mutex_lock(&adev->lock);
Susan Wang6dd13092021-01-25 10:27:11 -050010373 list_add_tail(&adev->active_inputs_list, &in->in_ctxt.list);
Derek Chenf939fb72018-11-13 13:34:41 -080010374 pthread_mutex_unlock(&adev->lock);
10375
Eric Laurent994a6932013-07-17 11:51:42 -070010376 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -080010377 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010378
10379err_open:
Krishna Kishor Jha0f4d8482022-02-18 10:56:05 +053010380 if (audio_extn_is_concurrent_pcm_record_enabled() && is_pcm_record_usecase(in->usecase)) {
10381 free_record_usecase(adev, in->usecase);
10382 } else if (in->usecase == USECASE_AUDIO_RECORD) {
Samyak Jainc37062f2019-04-25 18:41:06 +053010383 pthread_mutex_lock(&adev->lock);
10384 adev->pcm_record_uc_state = 0;
10385 pthread_mutex_unlock(&adev->lock);
10386 }
Kogara Naveen Kumarc5758232022-11-07 20:25:40 +053010387 if (audio_extn_is_concurrent_low_latency_pcm_record_enabled() && is_pcm_low_latency_record_usecase(in->usecase)) {
10388 free_low_latency_record_usecase(adev, in->usecase);
10389 } else if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY) {
10390 pthread_mutex_lock(&adev->lock);
10391 adev->pcm_low_latency_record_uc_state = 0;
10392 pthread_mutex_unlock(&adev->lock);
10393 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010394 free(in);
10395 *stream_in = NULL;
10396 return ret;
10397}
10398
10399static void adev_close_input_stream(struct audio_hw_device *dev,
10400 struct audio_stream_in *stream)
10401{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080010402 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -070010403 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -070010404 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +053010405
Sidipotu Ashokf43018c2014-05-02 16:21:50 +053010406 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080010407
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010408 if (in == NULL) {
10409 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
10410 return;
10411 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010412 io_streams_map_remove(adev, in->capture_handle);
10413
Susan Wang6dd13092021-01-25 10:27:11 -050010414 // remove out_ctxt early to prevent the stream
10415 // being opened in a race condition
10416 pthread_mutex_lock(&adev->lock);
10417 list_remove(&in->in_ctxt.list);
10418 pthread_mutex_unlock(&adev->lock);
10419
kunleiz70e57612018-12-28 17:50:23 +080010420 /* must deregister from sndmonitor first to prevent races
10421 * between the callback and close_stream
10422 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010423 audio_extn_snd_mon_unregister_listener(stream);
10424
kunleiz70e57612018-12-28 17:50:23 +080010425 /* Disable echo reference if there are no active input, hfp call
10426 * and sound trigger while closing input stream
10427 */
Eric Laurent637e2d42018-11-15 12:24:31 -080010428 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +080010429 !audio_extn_hfp_is_active(adev) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010430 !audio_extn_sound_trigger_check_ec_ref_enable()) {
10431 struct listnode out_devices;
10432 list_init(&out_devices);
10433 platform_set_echo_reference(adev, false, &out_devices);
Zhenlin Lian4f947842022-05-14 15:50:52 +053010434 clear_devices(&out_devices);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010435 } else
kunleiz70e57612018-12-28 17:50:23 +080010436 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +053010437
Dechen Chai22768452021-07-30 09:29:16 +053010438#ifndef LINUX_ENABLED
Weiyin Jiang2995f662019-04-17 14:25:12 +080010439 error_log_destroy(in->error_log);
10440 in->error_log = NULL;
Dechen Chai22768452021-07-30 09:29:16 +053010441#endif
Pallavid7c7a272018-01-16 11:22:55 +053010442
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080010443 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +053010444 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080010445 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +053010446 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080010447 if (ret != 0)
10448 ALOGE("%s: Compress voip input cannot be closed, error:%d",
10449 __func__, ret);
10450 } else
10451 in_standby(&stream->common);
10452
Weiyin Jiang280ea742020-09-08 20:28:22 +080010453 pthread_mutex_destroy(&in->lock);
10454 pthread_mutex_destroy(&in->pre_lock);
10455
Revathi Uddarajud2634032017-12-07 14:42:34 +053010456 pthread_mutex_lock(&adev->lock);
Krishna Kishor Jha0f4d8482022-02-18 10:56:05 +053010457 if (audio_extn_is_concurrent_pcm_record_enabled() && is_pcm_record_usecase(in->usecase)) {
10458 free_record_usecase(adev, in->usecase);
10459 } else if (in->usecase == USECASE_AUDIO_RECORD) {
Samyak Jain15fda662018-12-18 16:40:52 +053010460 adev->pcm_record_uc_state = 0;
10461 }
10462
Kogara Naveen Kumarc5758232022-11-07 20:25:40 +053010463 if (audio_extn_is_concurrent_low_latency_pcm_record_enabled() && is_pcm_low_latency_record_usecase(in->usecase)) {
10464 free_low_latency_record_usecase(adev, in->usecase);
10465 } else if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY) {
10466 adev->pcm_low_latency_record_uc_state = 0;
10467 }
10468
Kunlei Zhang5d5d8d92020-02-26 15:00:59 +080010469 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
10470 adev->enable_voicerx = false;
10471 }
10472
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -070010473 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -070010474 audio_extn_ssr_deinit();
10475 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010476
Garmond Leunge2433c32017-09-28 21:51:22 -070010477 if (audio_extn_ffv_get_stream() == in) {
10478 audio_extn_ffv_stream_deinit();
10479 }
10480
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010481 if (audio_extn_compr_cap_enabled() &&
Subhadra Jagadeesan63a1e832023-01-13 11:26:38 +053010482 audio_extn_compr_cap_format_supported(pcm_format_to_audio_format((in->config).format)))
Mingming Yine62d7842013-10-25 16:26:03 -070010483 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +053010484
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +053010485 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +053010486 audio_extn_cin_free_input_stream_resources(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010487
Mingming Yinfd7607b2016-01-22 12:48:44 -080010488 if (in->is_st_session) {
10489 ALOGV("%s: sound trigger pcm stop lab", __func__);
10490 audio_extn_sound_trigger_stop_lab(in);
10491 }
Zhenlin Lian4f947842022-05-14 15:50:52 +053010492 clear_devices(&in->device_list);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010493 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +053010494 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010495 return;
10496}
10497
Aalique Grahame22e49102018-12-18 14:23:57 -080010498/* verifies input and output devices and their capabilities.
10499 *
10500 * This verification is required when enabling extended bit-depth or
10501 * sampling rates, as not all qcom products support it.
10502 *
10503 * Suitable for calling only on initialization such as adev_open().
10504 * It fills the audio_device use_case_table[] array.
10505 *
10506 * Has a side-effect that it needs to configure audio routing / devices
10507 * in order to power up the devices and read the device parameters.
10508 * It does not acquire any hw device lock. Should restore the devices
10509 * back to "normal state" upon completion.
10510 */
10511static int adev_verify_devices(struct audio_device *adev)
10512{
10513 /* enumeration is a bit difficult because one really wants to pull
10514 * the use_case, device id, etc from the hidden pcm_device_table[].
10515 * In this case there are the following use cases and device ids.
10516 *
10517 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
10518 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
10519 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
10520 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
10521 * [USECASE_AUDIO_RECORD] = {0, 0},
10522 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
10523 * [USECASE_VOICE_CALL] = {2, 2},
10524 *
10525 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
10526 * USECASE_VOICE_CALL omitted, but possible for either input or output.
10527 */
10528
10529 /* should be the usecases enabled in adev_open_input_stream() */
10530 static const int test_in_usecases[] = {
10531 USECASE_AUDIO_RECORD,
10532 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
10533 };
10534 /* should be the usecases enabled in adev_open_output_stream()*/
10535 static const int test_out_usecases[] = {
10536 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
10537 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
10538 };
10539 static const usecase_type_t usecase_type_by_dir[] = {
10540 PCM_PLAYBACK,
10541 PCM_CAPTURE,
10542 };
10543 static const unsigned flags_by_dir[] = {
10544 PCM_OUT,
10545 PCM_IN,
10546 };
10547
10548 size_t i;
10549 unsigned dir;
10550 const unsigned card_id = adev->snd_card;
10551
10552 for (dir = 0; dir < 2; ++dir) {
10553 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
10554 const unsigned flags_dir = flags_by_dir[dir];
10555 const size_t testsize =
10556 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
10557 const int *testcases =
10558 dir ? test_in_usecases : test_out_usecases;
10559 const audio_devices_t audio_device =
10560 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
10561
10562 for (i = 0; i < testsize; ++i) {
10563 const audio_usecase_t audio_usecase = testcases[i];
10564 int device_id;
10565 struct pcm_params **pparams;
10566 struct stream_out out;
10567 struct stream_in in;
10568 struct audio_usecase uc_info;
10569 int retval;
10570
10571 pparams = &adev->use_case_table[audio_usecase];
10572 pcm_params_free(*pparams); /* can accept null input */
10573 *pparams = NULL;
10574
10575 /* find the device ID for the use case (signed, for error) */
10576 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
10577 if (device_id < 0)
10578 continue;
10579
10580 /* prepare structures for device probing */
10581 memset(&uc_info, 0, sizeof(uc_info));
10582 uc_info.id = audio_usecase;
10583 uc_info.type = usecase_type;
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010584 list_init(&uc_info.device_list);
Aalique Grahame22e49102018-12-18 14:23:57 -080010585 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -080010586 memset(&in, 0, sizeof(in));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010587 list_init(&in.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010588 update_device_list(&in.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -080010589 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
10590 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -080010591 }
10592 memset(&out, 0, sizeof(out));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010593 list_init(&out.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010594 update_device_list(&out.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -080010595 uc_info.stream.out = &out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010596 update_device_list(&uc_info.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -080010597 uc_info.in_snd_device = SND_DEVICE_NONE;
10598 uc_info.out_snd_device = SND_DEVICE_NONE;
10599 list_add_tail(&adev->usecase_list, &uc_info.list);
10600
10601 /* select device - similar to start_(in/out)put_stream() */
10602 retval = select_devices(adev, audio_usecase);
10603 if (retval >= 0) {
10604 *pparams = pcm_params_get(card_id, device_id, flags_dir);
10605#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -070010606 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -080010607 if (*pparams) {
10608 ALOGV("%s: (%s) card %d device %d", __func__,
10609 dir ? "input" : "output", card_id, device_id);
10610 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
10611 } else {
10612 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
10613 }
10614#endif
10615 }
10616
10617 /* deselect device - similar to stop_(in/out)put_stream() */
10618 /* 1. Get and set stream specific mixer controls */
10619 retval = disable_audio_route(adev, &uc_info);
10620 /* 2. Disable the rx device */
10621 retval = disable_snd_device(adev,
10622 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
10623 list_remove(&uc_info.list);
10624 }
10625 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010626 return 0;
10627}
10628
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010629int update_patch(unsigned int num_sources,
10630 const struct audio_port_config *sources,
10631 unsigned int num_sinks,
10632 const struct audio_port_config *sinks,
10633 audio_patch_handle_t handle,
10634 struct audio_patch_info *p_info,
10635 patch_type_t patch_type, bool new_patch)
10636{
Aniket Kumar Latad13758f2020-08-06 15:11:36 -070010637 ALOGV("%s: enter", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010638
10639 if (p_info == NULL) {
10640 ALOGE("%s: Invalid patch pointer", __func__);
10641 return -EINVAL;
10642 }
10643
10644 if (new_patch) {
10645 p_info->patch = (struct audio_patch *) calloc(1, sizeof(struct audio_patch));
10646 if (p_info->patch == NULL) {
10647 ALOGE("%s: Could not allocate patch", __func__);
10648 return -ENOMEM;
10649 }
10650 }
10651
10652 p_info->patch->id = handle;
10653 p_info->patch->num_sources = num_sources;
10654 p_info->patch->num_sinks = num_sinks;
10655
10656 for (int i = 0; i < num_sources; i++)
10657 p_info->patch->sources[i] = sources[i];
10658 for (int i = 0; i < num_sinks; i++)
10659 p_info->patch->sinks[i] = sinks[i];
10660
10661 p_info->patch_type = patch_type;
10662 return 0;
10663}
10664
10665audio_patch_handle_t generate_patch_handle()
10666{
10667 static audio_patch_handle_t patch_handle = AUDIO_PATCH_HANDLE_NONE;
10668 if (++patch_handle < 0)
10669 patch_handle = AUDIO_PATCH_HANDLE_NONE + 1;
10670 return patch_handle;
10671}
10672
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010673int adev_create_audio_patch(struct audio_hw_device *dev,
10674 unsigned int num_sources,
10675 const struct audio_port_config *sources,
10676 unsigned int num_sinks,
10677 const struct audio_port_config *sinks,
10678 audio_patch_handle_t *handle)
10679{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010680 int ret = 0;
10681 struct audio_device *adev = (struct audio_device *)dev;
10682 struct audio_patch_info *p_info = NULL;
10683 patch_type_t patch_type = PATCH_NONE;
10684 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10685 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
10686 struct audio_stream_info *s_info = NULL;
10687 struct audio_stream *stream = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010688 struct listnode devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010689 audio_devices_t device_type = AUDIO_DEVICE_NONE;
10690 bool new_patch = false;
10691 char addr[AUDIO_DEVICE_MAX_ADDRESS_LEN];
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010692
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010693 ALOGD("%s: enter: num sources %d, num_sinks %d, handle %d", __func__,
10694 num_sources, num_sinks, *handle);
10695
10696 if (num_sources == 0 || num_sources > AUDIO_PATCH_PORTS_MAX ||
10697 num_sinks == 0 || num_sinks > AUDIO_PATCH_PORTS_MAX) {
10698 ALOGE("%s: Invalid patch arguments", __func__);
10699 ret = -EINVAL;
10700 goto done;
10701 }
10702
10703 if (num_sources > 1) {
10704 ALOGE("%s: Multiple sources are not supported", __func__);
10705 ret = -EINVAL;
10706 goto done;
10707 }
10708
10709 if (sources == NULL || sinks == NULL) {
10710 ALOGE("%s: Invalid sources or sinks port config", __func__);
10711 ret = -EINVAL;
10712 goto done;
10713 }
10714
10715 ALOGV("%s: source role %d, source type %d", __func__,
10716 sources[0].type, sources[0].role);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010717 list_init(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010718
10719 // Populate source/sink information and fetch stream info
10720 switch (sources[0].type) {
10721 case AUDIO_PORT_TYPE_DEVICE: // Patch for audio capture or loopback
10722 device_type = sources[0].ext.device.type;
10723 strlcpy(&addr[0], &sources[0].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010724 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010725 if (sinks[0].type == AUDIO_PORT_TYPE_MIX) {
10726 patch_type = PATCH_CAPTURE;
10727 io_handle = sinks[0].ext.mix.handle;
10728 input_source = sinks[0].ext.mix.usecase.source;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010729 ALOGD("%s: Capture patch from device %x to mix %d",
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010730 __func__, device_type, io_handle);
10731 } else {
10732 // Device to device patch is not implemented.
10733 // This space will need changes if audio HAL
10734 // handles device to device patches in the future.
10735 patch_type = PATCH_DEVICE_LOOPBACK;
10736 }
10737 break;
10738 case AUDIO_PORT_TYPE_MIX: // Patch for audio playback
10739 io_handle = sources[0].ext.mix.handle;
10740 for (int i = 0; i < num_sinks; i++) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010741 device_type = sinks[i].ext.device.type;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010742 strlcpy(&addr[0], &sinks[i].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010743 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010744 }
10745 patch_type = PATCH_PLAYBACK;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010746 ALOGD("%s: Playback patch from mix handle %d to device %x",
10747 __func__, io_handle, get_device_types(&devices));
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010748 break;
10749 case AUDIO_PORT_TYPE_SESSION:
10750 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010751 ALOGE("%s: Unsupported source type %d", __func__, sources[0].type);
10752 ret = -EINVAL;
10753 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010754 }
10755
10756 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010757
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010758 // Generate patch info and update patch
10759 if (*handle == AUDIO_PATCH_HANDLE_NONE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010760 *handle = generate_patch_handle();
10761 p_info = (struct audio_patch_info *)
10762 calloc(1, sizeof(struct audio_patch_info));
10763 if (p_info == NULL) {
10764 ALOGE("%s: Failed to allocate memory", __func__);
10765 pthread_mutex_unlock(&adev->lock);
10766 ret = -ENOMEM;
10767 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010768 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010769 new_patch = true;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010770 } else {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010771 p_info = fetch_patch_info_l(adev, *handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010772 if (p_info == NULL) {
10773 ALOGE("%s: Unable to fetch patch for received patch handle %d",
10774 __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010775 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010776 ret = -EINVAL;
10777 goto done;
10778 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010779 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010780 update_patch(num_sources, sources, num_sinks, sinks,
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010781 *handle, p_info, patch_type, new_patch);
10782
10783 // Fetch stream info of associated mix for playback or capture patches
10784 if (p_info->patch_type == PATCH_PLAYBACK ||
10785 p_info->patch_type == PATCH_CAPTURE) {
10786 s_info = hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10787 if (s_info == NULL) {
10788 ALOGE("%s: Failed to obtain stream info", __func__);
10789 if (new_patch)
10790 free(p_info);
10791 pthread_mutex_unlock(&adev->lock);
10792 ret = -EINVAL;
10793 goto done;
10794 }
10795 ALOGV("%s: Fetched stream info with io_handle %d", __func__, io_handle);
10796 s_info->patch_handle = *handle;
10797 stream = s_info->stream;
10798 }
10799 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010800
10801 // Update routing for stream
10802 if (stream != NULL) {
Revathi Uddaraju4255a632021-12-02 05:11:13 -080010803 if (p_info->patch_type == PATCH_PLAYBACK) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010804 ret = route_output_stream((struct stream_out *) stream, &devices);
Revathi Uddaraju4255a632021-12-02 05:11:13 -080010805 } else if (p_info->patch_type == PATCH_CAPTURE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010806 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Revathi Uddaraju4255a632021-12-02 05:11:13 -080010807 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010808 if (ret < 0) {
10809 pthread_mutex_lock(&adev->lock);
10810 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10811 if (new_patch)
10812 free(p_info);
10813 pthread_mutex_unlock(&adev->lock);
10814 ALOGE("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10815 goto done;
10816 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010817 }
10818
10819 // Add new patch to patch map
10820 if (!ret && new_patch) {
10821 pthread_mutex_lock(&adev->lock);
10822 hashmapPut(adev->patch_map, (void *) (intptr_t) *handle, (void *) p_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010823 ALOGD("%s: Added a new patch with handle %d", __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010824 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010825 }
10826
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010827done:
Zhenlin Lian4f947842022-05-14 15:50:52 +053010828 clear_devices(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010829 audio_extn_hw_loopback_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010830 num_sources,
10831 sources,
10832 num_sinks,
10833 sinks,
10834 handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010835 audio_extn_auto_hal_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010836 num_sources,
10837 sources,
10838 num_sinks,
10839 sinks,
10840 handle);
10841 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010842}
10843
10844int adev_release_audio_patch(struct audio_hw_device *dev,
10845 audio_patch_handle_t handle)
10846{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010847 struct audio_device *adev = (struct audio_device *) dev;
10848 int ret = 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010849 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010850 struct audio_stream *stream = NULL;
Derek Chenf939fb72018-11-13 13:34:41 -080010851
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010852 if (handle == AUDIO_PATCH_HANDLE_NONE) {
10853 ALOGE("%s: Invalid patch handle %d", __func__, handle);
10854 ret = -EINVAL;
10855 goto done;
10856 }
10857
10858 ALOGD("%s: Remove patch with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010859 pthread_mutex_lock(&adev->lock);
10860 struct audio_patch_info *p_info = fetch_patch_info_l(adev, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010861 if (p_info == NULL) {
10862 ALOGE("%s: Patch info not found with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010863 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010864 ret = -EINVAL;
10865 goto done;
10866 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010867 struct audio_patch *patch = p_info->patch;
10868 if (patch == NULL) {
10869 ALOGE("%s: Patch not found for handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010870 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010871 ret = -EINVAL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010872 goto done;
10873 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010874 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10875 switch (patch->sources[0].type) {
10876 case AUDIO_PORT_TYPE_MIX:
10877 io_handle = patch->sources[0].ext.mix.handle;
10878 break;
10879 case AUDIO_PORT_TYPE_DEVICE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010880 if (p_info->patch_type == PATCH_CAPTURE)
10881 io_handle = patch->sinks[0].ext.mix.handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010882 break;
10883 case AUDIO_PORT_TYPE_SESSION:
10884 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010885 pthread_mutex_unlock(&adev->lock);
10886 ret = -EINVAL;
10887 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010888 }
10889
10890 // Remove patch and reset patch handle in stream info
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010891 patch_type_t patch_type = p_info->patch_type;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010892 patch_map_remove_l(adev, handle);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010893 if (patch_type == PATCH_PLAYBACK ||
10894 patch_type == PATCH_CAPTURE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010895 struct audio_stream_info *s_info =
10896 hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10897 if (s_info == NULL) {
10898 ALOGE("%s: stream for io_handle %d is not available", __func__, io_handle);
10899 pthread_mutex_unlock(&adev->lock);
10900 goto done;
10901 }
10902 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10903 stream = s_info->stream;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010904 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010905 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010906
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010907 if (stream != NULL) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010908 struct listnode devices;
10909 list_init(&devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010910 if (patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010911 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010912 else if (patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010913 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Zhenlin Lian4f947842022-05-14 15:50:52 +053010914 clear_devices(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010915 }
10916
10917 if (ret < 0)
10918 ALOGW("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10919
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010920done:
10921 audio_extn_hw_loopback_release_audio_patch(dev, handle);
10922 audio_extn_auto_hal_release_audio_patch(dev, handle);
10923
10924 ALOGV("%s: Successfully released patch %d", __func__, handle);
Derek Chenf939fb72018-11-13 13:34:41 -080010925 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010926}
10927
10928int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
10929{
Derek Chenf13dd492018-11-13 14:53:51 -080010930 int ret = 0;
10931
10932 ret = audio_extn_hw_loopback_get_audio_port(dev, config);
10933 ret |= audio_extn_auto_hal_get_audio_port(dev, config);
10934 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010935}
10936
10937int adev_set_audio_port_config(struct audio_hw_device *dev,
10938 const struct audio_port_config *config)
10939{
Derek Chenf13dd492018-11-13 14:53:51 -080010940 int ret = 0;
10941
10942 ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
10943 ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
10944 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010945}
10946
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -070010947static int adev_dump(const audio_hw_device_t *device __unused,
10948 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010949{
10950 return 0;
10951}
10952
10953static int adev_close(hw_device_t *device)
10954{
Aalique Grahame22e49102018-12-18 14:23:57 -080010955 size_t i;
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010956 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -070010957
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010958 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -070010959 return 0;
10960
10961 pthread_mutex_lock(&adev_init_lock);
10962
10963 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +053010964 if (audio_extn_spkr_prot_is_enabled())
10965 audio_extn_spkr_prot_deinit();
Jaideep Sharmaa2b49672019-09-10 20:37:03 +053010966 audio_extn_battery_properties_listener_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010967 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010968 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -080010969 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010970 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -080010971 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010972 audio_extn_utils_release_streams_cfg_lists(
10973 &adev->streams_output_cfg_list,
10974 &adev->streams_input_cfg_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010975 if (audio_extn_qap_is_enabled())
10976 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010977 if (audio_extn_qaf_is_enabled())
10978 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -070010979 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +080010980 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -070010981 free(adev->snd_dev_ref_cnt);
10982 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010983 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
10984 pcm_params_free(adev->use_case_table[i]);
10985 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010986 if (adev->adm_deinit)
10987 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010988 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010989 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010990 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010991 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010992 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010993 if (adev->device_cfg_params) {
10994 free(adev->device_cfg_params);
10995 adev->device_cfg_params = NULL;
10996 }
Derek Chend2530072014-11-24 12:39:14 -080010997 if(adev->ext_hw_plugin)
10998 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -080010999 audio_extn_auto_hal_deinit();
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011000 free_map(adev->patch_map);
11001 free_map(adev->io_streams_map);
Kiran Kandi910e1862013-10-29 13:29:42 -070011002 free(device);
11003 adev = NULL;
11004 }
11005 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +053011006 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011007 return 0;
11008}
11009
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070011010/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
11011 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
11012 * just that it _might_ work.
11013 */
11014static int period_size_is_plausible_for_low_latency(int period_size)
11015{
11016 switch (period_size) {
11017 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -070011018 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070011019 case 240:
11020 case 320:
11021 case 480:
11022 return 1;
11023 default:
11024 return 0;
11025 }
11026}
11027
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053011028static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
11029{
11030 bool is_snd_card_status = false;
11031 bool is_ext_device_status = false;
11032 char value[32];
11033 int card = -1;
11034 card_status_t status;
11035
11036 if (cookie != adev || !parms)
11037 return;
11038
11039 if (!parse_snd_card_status(parms, &card, &status)) {
11040 is_snd_card_status = true;
11041 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
11042 is_ext_device_status = true;
11043 } else {
11044 // not a valid event
11045 return;
11046 }
11047
11048 pthread_mutex_lock(&adev->lock);
11049 if (card == adev->snd_card || is_ext_device_status) {
11050 if (is_snd_card_status && adev->card_status != status) {
Jaideep Sharmacb402512020-09-24 17:51:07 +053011051 ALOGD("%s card_status %d", __func__, status);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053011052 adev->card_status = status;
11053 platform_snd_card_update(adev->platform, status);
11054 audio_extn_fm_set_parameters(adev, parms);
Derek Chend6f371d2019-03-01 13:45:58 -080011055 audio_extn_auto_hal_set_parameters(adev, parms);
Zhou Song4f43e352019-07-02 00:32:23 +080011056 if (status == CARD_STATUS_OFFLINE)
11057 audio_extn_sco_reset_configuration();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053011058 } else if (is_ext_device_status) {
11059 platform_set_parameters(adev->platform, parms);
11060 }
11061 }
11062 pthread_mutex_unlock(&adev->lock);
11063 return;
11064}
11065
Weiyin Jiang280ea742020-09-08 20:28:22 +080011066/* adev lock held */
11067int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011068{
11069 struct audio_usecase *uc_info;
Zhou Song407e5aa2020-12-27 19:13:04 +080011070 struct audio_usecase *usecase;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080011071 struct listnode devices;
Zhou Song407e5aa2020-12-27 19:13:04 +080011072 struct listnode *node;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011073
11074 uc_info = get_usecase_from_list(adev, out->usecase);
11075 if (uc_info == NULL) {
11076 ALOGE("%s: Could not find the usecase (%d) in the list",
11077 __func__, out->usecase);
11078 return -EINVAL;
11079 }
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080011080 list_init(&devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011081
Zhou Songbaddf9f2020-11-20 13:57:39 +080011082 ALOGD("%s: enter: usecase(%d: %s), a2dp muted %d", __func__,
11083 out->usecase, use_case_table[out->usecase], out->a2dp_muted);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011084
11085 if (restore) {
Weiyin Jiang280ea742020-09-08 20:28:22 +080011086 pthread_mutex_lock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011087 // restore A2DP device for active usecases and unmute if required
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080011088 if (is_a2dp_out_device_type(&out->device_list)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011089 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
Zhou Songe5225132019-09-26 15:33:36 +080011090 if (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)
11091 select_devices(adev, uc_info->id);
Zhou Songbaddf9f2020-11-20 13:57:39 +080011092
11093 if (is_offload_usecase(out->usecase)) {
11094 if (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)
Weiyin Jiang280ea742020-09-08 20:28:22 +080011095 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
Zhou Songbaddf9f2020-11-20 13:57:39 +080011096 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
11097 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
11098 } else {
11099 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011100 }
Zhou Songbaddf9f2020-11-20 13:57:39 +080011101 out->a2dp_muted = false;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011102 }
Weiyin Jiang280ea742020-09-08 20:28:22 +080011103 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011104 } else {
Weiyin Jiang280ea742020-09-08 20:28:22 +080011105 pthread_mutex_lock(&out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +080011106 // mute stream and switch to speaker if suspended
11107 if (!out->a2dp_muted && !out->standby) {
Zhou Songcf77af02021-05-14 18:21:14 +080011108 if ((is_a2dp_out_device_type(&devices) && list_length(&devices) == 1) ||
11109 (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)) {
Zhou Song8edbbdb2021-01-14 16:48:03 +080011110 out->a2dp_muted = true;
11111 if (is_offload_usecase(out->usecase)) {
11112 if (out->offload_state == OFFLOAD_STATE_PLAYING)
11113 compress_pause(out->compr);
11114 out_set_compr_volume(&out->stream, (float)0, (float)0);
Zhou Song8edbbdb2021-01-14 16:48:03 +080011115 } else {
Weiyin Jiang906db3c2021-03-02 13:17:04 +080011116 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
11117 out_set_voip_volume(&out->stream, (float)0, (float)0);
11118 else
11119 out_set_pcm_volume(&out->stream, (float)0, (float)0);
11120
Zhou Song8edbbdb2021-01-14 16:48:03 +080011121 /* wait for stale pcm drained before switching to speaker */
11122 uint32_t latency =
11123 (out->config.period_count * out->config.period_size * 1000) /
11124 (out->config.rate);
11125 usleep(latency * 1000);
11126 }
Zhou Songbaddf9f2020-11-20 13:57:39 +080011127 }
Manish Chaturvedi0a8305f2023-03-17 15:47:37 +053011128 assign_devices(&devices, &out->device_list);
11129 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
11130 list_for_each(node, &adev->usecase_list) {
11131 usecase = node_to_item(node, struct audio_usecase, list);
11132 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
11133 !is_a2dp_out_device_type(&usecase->stream.out->device_list) &&
11134 !is_sco_out_device_type(&usecase->stream.out->device_list) &&
11135 platform_check_backends_match(SND_DEVICE_OUT_SPEAKER,
11136 usecase->out_snd_device)) {
11137 assign_devices(&out->device_list, &usecase->stream.out->device_list);
11138 break;
11139 }
11140 }
Zhou Songbaddf9f2020-11-20 13:57:39 +080011141 select_devices(adev, out->usecase);
Zhou Song8edbbdb2021-01-14 16:48:03 +080011142 ALOGD("%s: switched to device:%s and stream muted:%d", __func__,
11143 platform_get_snd_device_name(uc_info->out_snd_device), out->a2dp_muted);
Zhou Songbaddf9f2020-11-20 13:57:39 +080011144 if (is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011145 if (out->offload_state == OFFLOAD_STATE_PLAYING)
11146 compress_resume(out->compr);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011147 }
Zhou Songbaddf9f2020-11-20 13:57:39 +080011148 assign_devices(&out->device_list, &devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011149 }
Weiyin Jiang280ea742020-09-08 20:28:22 +080011150 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011151 }
Zhenlin Lian4f947842022-05-14 15:50:52 +053011152 clear_devices(&devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011153 ALOGV("%s: exit", __func__);
11154 return 0;
11155}
11156
Haynes Mathew George01156f92018-04-13 15:29:54 -070011157void adev_on_battery_status_changed(bool charging)
11158{
11159 pthread_mutex_lock(&adev->lock);
11160 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
11161 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +080011162 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -070011163 pthread_mutex_unlock(&adev->lock);
11164}
11165
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011166static int adev_open(const hw_module_t *module, const char *name,
11167 hw_device_t **device)
11168{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053011169 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -080011170 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053011171 char mixer_ctl_name[128] = {0};
11172 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053011173
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080011174 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011175 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
11176
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070011177 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -070011178 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070011179 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -070011180 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070011181 ALOGD("%s: returning existing instance of adev", __func__);
11182 ALOGD("%s: exit", __func__);
11183 pthread_mutex_unlock(&adev_init_lock);
11184 return 0;
11185 }
11186
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011187 adev = calloc(1, sizeof(struct audio_device));
11188
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -070011189 if (!adev) {
11190 pthread_mutex_unlock(&adev_init_lock);
11191 return -ENOMEM;
11192 }
11193
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -070011194 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
11195
Weiyin Jiange6ce6312019-01-28 18:28:22 +080011196 // register audio ext hidl at the earliest
11197 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053011198#ifdef DYNAMIC_LOG_ENABLED
11199 register_for_dynamic_logging("hal");
11200#endif
11201
Derek Chenf939fb72018-11-13 13:34:41 -080011202 /* default audio HAL major version */
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011203 uint32_t maj_version = 3;
Derek Chenf939fb72018-11-13 13:34:41 -080011204 if(property_get("vendor.audio.hal.maj.version", value, NULL))
11205 maj_version = atoi(value);
11206
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011207 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -080011208 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011209 adev->device.common.module = (struct hw_module_t *)module;
11210 adev->device.common.close = adev_close;
11211
11212 adev->device.init_check = adev_init_check;
11213 adev->device.set_voice_volume = adev_set_voice_volume;
11214 adev->device.set_master_volume = adev_set_master_volume;
11215 adev->device.get_master_volume = adev_get_master_volume;
11216 adev->device.set_master_mute = adev_set_master_mute;
11217 adev->device.get_master_mute = adev_get_master_mute;
11218 adev->device.set_mode = adev_set_mode;
11219 adev->device.set_mic_mute = adev_set_mic_mute;
11220 adev->device.get_mic_mute = adev_get_mic_mute;
11221 adev->device.set_parameters = adev_set_parameters;
11222 adev->device.get_parameters = adev_get_parameters;
11223 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
11224 adev->device.open_output_stream = adev_open_output_stream;
11225 adev->device.close_output_stream = adev_close_output_stream;
11226 adev->device.open_input_stream = adev_open_input_stream;
11227 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053011228 adev->device.create_audio_patch = adev_create_audio_patch;
11229 adev->device.release_audio_patch = adev_release_audio_patch;
11230 adev->device.get_audio_port = adev_get_audio_port;
11231 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011232 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +053011233 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011234
11235 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011236 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -080011237 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011238 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011239 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -080011240 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -070011241 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +053011242 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -070011243 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -070011244 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -070011245 /* Init audio and voice feature */
11246 audio_extn_feature_init();
11247 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070011248 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -080011249 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -080011250 list_init(&adev->active_inputs_list);
11251 list_init(&adev->active_outputs_list);
Rahul Sharma99770982019-03-06 17:05:26 +053011252 list_init(&adev->audio_patch_record_list);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011253 adev->io_streams_map = hashmapCreate(AUDIO_IO_PORTS_MAX, audio_extn_utils_hash_fn,
11254 audio_extn_utils_hash_eq);
11255 if (!adev->io_streams_map) {
11256 ALOGE("%s: Could not create io streams map", __func__);
11257 ret = -ENOMEM;
11258 goto adev_open_err;
11259 }
11260 adev->patch_map = hashmapCreate(AUDIO_PATCH_PORTS_MAX, audio_extn_utils_hash_fn,
11261 audio_extn_utils_hash_eq);
11262 if (!adev->patch_map) {
11263 ALOGE("%s: Could not create audio patch map", __func__);
11264 ret = -ENOMEM;
11265 goto adev_open_err;
11266 }
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -080011267 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -070011268 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +053011269 adev->pcm_record_uc_state = 0;
Kogara Naveen Kumarc5758232022-11-07 20:25:40 +053011270 adev->pcm_low_latency_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +053011271 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +053011272 adev->perf_lock_opts[0] = 0x101;
11273 adev->perf_lock_opts[1] = 0x20E;
11274 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +080011275 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -070011276 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053011277 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070011278 adev->adm_routing_changed = false;
Revathi Uddarajub26e3932020-06-10 14:51:02 +053011279 adev->a2dp_started = false;
Zhou Song503196b2021-07-23 17:31:05 +080011280 adev->ha_proxy_enable = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +053011281
Zhou Song68ebc352019-12-05 17:11:15 +080011282 audio_extn_perf_lock_init();
11283
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011284 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -070011285 adev->platform = platform_init(adev);
11286 if (!adev->platform) {
Eric Laurentb23d5282013-05-14 15:27:20 -070011287 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011288 ret = -EINVAL;
11289 goto adev_open_err;
Eric Laurentb23d5282013-05-14 15:27:20 -070011290 }
Eric Laurentc4aef752013-09-12 17:45:53 -070011291
Aalique Grahame22e49102018-12-18 14:23:57 -080011292 adev->extspk = audio_extn_extspk_init(adev);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053011293 if (audio_extn_qap_is_enabled()) {
11294 ret = audio_extn_qap_init(adev);
11295 if (ret < 0) {
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053011296 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011297 goto adev_open_err;
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053011298 }
11299 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
11300 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
11301 }
Aalique Grahame22e49102018-12-18 14:23:57 -080011302
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053011303 if (audio_extn_qaf_is_enabled()) {
11304 ret = audio_extn_qaf_init(adev);
11305 if (ret < 0) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053011306 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011307 goto adev_open_err;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053011308 }
11309
11310 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
11311 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
11312 }
11313
Derek Chenae7b0342019-02-08 15:17:04 -080011314 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -080011315 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
11316
Eric Laurentc4aef752013-09-12 17:45:53 -070011317 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
11318 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
11319 if (adev->visualizer_lib == NULL) {
11320 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
11321 } else {
11322 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
11323 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080011324 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070011325 "visualizer_hal_start_output");
11326 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080011327 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070011328 "visualizer_hal_stop_output");
11329 }
11330 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +053011331 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080011332 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -080011333 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +080011334 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +053011335 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070011336 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -070011337
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080011338 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
11339 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
11340 if (adev->offload_effects_lib == NULL) {
11341 ALOGE("%s: DLOPEN failed for %s", __func__,
11342 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
11343 } else {
11344 ALOGV("%s: DLOPEN successful for %s", __func__,
11345 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
11346 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +053011347 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080011348 "offload_effects_bundle_hal_start_output");
11349 adev->offload_effects_stop_output =
11350 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
11351 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080011352 adev->offload_effects_set_hpx_state =
11353 (int (*)(bool))dlsym(adev->offload_effects_lib,
11354 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +053011355 adev->offload_effects_get_parameters =
11356 (void (*)(struct str_parms *, struct str_parms *))
11357 dlsym(adev->offload_effects_lib,
11358 "offload_effects_bundle_get_parameters");
11359 adev->offload_effects_set_parameters =
11360 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
11361 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080011362 }
11363 }
11364
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070011365 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
11366 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
11367 if (adev->adm_lib == NULL) {
11368 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
11369 } else {
11370 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
11371 adev->adm_init = (adm_init_t)
11372 dlsym(adev->adm_lib, "adm_init");
11373 adev->adm_deinit = (adm_deinit_t)
11374 dlsym(adev->adm_lib, "adm_deinit");
11375 adev->adm_register_input_stream = (adm_register_input_stream_t)
11376 dlsym(adev->adm_lib, "adm_register_input_stream");
11377 adev->adm_register_output_stream = (adm_register_output_stream_t)
11378 dlsym(adev->adm_lib, "adm_register_output_stream");
11379 adev->adm_deregister_stream = (adm_deregister_stream_t)
11380 dlsym(adev->adm_lib, "adm_deregister_stream");
11381 adev->adm_request_focus = (adm_request_focus_t)
11382 dlsym(adev->adm_lib, "adm_request_focus");
11383 adev->adm_abandon_focus = (adm_abandon_focus_t)
11384 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -070011385 adev->adm_set_config = (adm_set_config_t)
11386 dlsym(adev->adm_lib, "adm_set_config");
11387 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
11388 dlsym(adev->adm_lib, "adm_request_focus_v2");
11389 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
11390 dlsym(adev->adm_lib, "adm_is_noirq_avail");
11391 adev->adm_on_routing_change = (adm_on_routing_change_t)
11392 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070011393 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
11394 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070011395 }
11396 }
11397
Aalique Grahame22e49102018-12-18 14:23:57 -080011398 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070011399 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +080011400 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Kunlei Zhanga3c4cb02021-03-05 16:03:54 +080011401 adev->fluence_nn_usecase_id = USECASE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -080011402 //initialize this to false for now,
11403 //this will be set to true through set param
11404 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070011405
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -070011406 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011407 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -080011408
11409 if (k_enable_extended_precision)
11410 adev_verify_devices(adev);
11411
Xiaojun Sang785b5da2017-08-03 15:52:29 +080011412 adev->dsp_bit_width_enforce_mode =
11413 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011414
Dhananjay Kumard6d32152016-10-13 16:11:03 +053011415 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
11416 &adev->streams_output_cfg_list,
11417 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070011418
Kiran Kandi910e1862013-10-29 13:29:42 -070011419 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070011420
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070011421 int trial;
Manisha Agarwalc75a0202019-12-06 18:48:25 +053011422 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070011423 trial = atoi(value);
11424 if (period_size_is_plausible_for_low_latency(trial)) {
11425 pcm_config_low_latency.period_size = trial;
11426 pcm_config_low_latency.start_threshold = trial / 4;
11427 pcm_config_low_latency.avail_min = trial / 4;
11428 configured_low_latency_capture_period_size = trial;
11429 }
11430 }
ronghuiz93177262021-04-21 19:58:13 +080011431 if (property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070011432 trial = atoi(value);
11433 if (period_size_is_plausible_for_low_latency(trial)) {
11434 configured_low_latency_capture_period_size = trial;
11435 }
11436 }
11437
Vignesh Kulothungan7d374312018-02-21 17:12:00 -080011438 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
11439
Eric Laurent4b084132018-10-19 17:33:43 -070011440 adev->camera_orientation = CAMERA_DEFAULT;
11441
Manisha Agarwalc75a0202019-12-06 18:48:25 +053011442 if (property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -070011443 af_period_multiplier = atoi(value);
11444 if (af_period_multiplier < 0)
11445 af_period_multiplier = 2;
11446 else if (af_period_multiplier > 4)
11447 af_period_multiplier = 4;
11448
11449 ALOGV("new period_multiplier = %d", af_period_multiplier);
11450 }
11451
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080011452 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080011453
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -070011454 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070011455 pthread_mutex_unlock(&adev_init_lock);
11456
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070011457 if (adev->adm_init)
11458 adev->adm_data = adev->adm_init();
11459
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053011460 qahwi_init(*device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080011461 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053011462
11463 audio_extn_snd_mon_init();
11464 pthread_mutex_lock(&adev->lock);
11465 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
11466 adev->card_status = CARD_STATUS_ONLINE;
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -050011467 adev->out_power_policy = POWER_POLICY_STATUS_ONLINE;
11468 adev->in_power_policy = POWER_POLICY_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -070011469 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
11470 /*
11471 * if the battery state callback happens before charging can be queried,
11472 * it will be guarded with the adev->lock held in the cb function and so
11473 * the callback value will reflect the latest state
11474 */
11475 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053011476 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +080011477 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -070011478 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +080011479 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053011480 /* Allocate memory for Device config params */
11481 adev->device_cfg_params = (struct audio_device_config_param*)
11482 calloc(platform_get_max_codec_backend(),
11483 sizeof(struct audio_device_config_param));
11484 if (adev->device_cfg_params == NULL)
11485 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053011486
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053011487 /*
11488 * Check if new PSPD matrix mixer control is supported. If not
11489 * supported, then set flag so that old mixer ctrl is sent while
11490 * sending pspd coefficients on older kernel version. Query mixer
11491 * control for default pcm id and channel value one.
11492 */
11493 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
11494 "AudStr %d ChMixer Weight Ch %d", 0, 1);
11495
11496 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
11497 if (!ctl) {
11498 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
11499 __func__, mixer_ctl_name);
11500 adev->use_old_pspd_mix_ctrl = true;
11501 }
11502
Jaideep Sharma0fa53812020-09-17 09:00:11 +053011503 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011504 return 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011505
11506adev_open_err:
11507 free_map(adev->patch_map);
11508 free_map(adev->io_streams_map);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080011509 free(adev->snd_dev_ref_cnt);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011510 pthread_mutex_destroy(&adev->lock);
11511 free(adev);
11512 adev = NULL;
11513 *device = NULL;
11514 pthread_mutex_unlock(&adev_init_lock);
11515 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011516}
11517
11518static struct hw_module_methods_t hal_module_methods = {
11519 .open = adev_open,
11520};
11521
11522struct audio_module HAL_MODULE_INFO_SYM = {
11523 .common = {
11524 .tag = HARDWARE_MODULE_TAG,
11525 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
11526 .hal_api_version = HARDWARE_HAL_API_VERSION,
11527 .id = AUDIO_HARDWARE_MODULE_ID,
11528 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -080011529 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011530 .methods = &hal_module_methods,
11531 },
11532};