blob: e852b0e1fb335bf2a2e8eb2508149c751ee05ad1 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Ramu Gottipatifa5be522021-12-28 19:18:21 +05302 * Copyright (c) 2013-2022, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Sandhya Mutha Naga Venkataa597a962023-02-07 11:35:51 +053036 *
37 * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080038 */
39
40#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070041#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080042/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070043/*#define VERY_VERY_VERBOSE_LOGGING*/
44#ifdef VERY_VERY_VERBOSE_LOGGING
45#define ALOGVV ALOGV
46#else
47#define ALOGVV(a...) do { } while(0)
48#endif
George Gao3018ede2019-10-23 13:23:00 -070049#include <limits.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080050#include <errno.h>
51#include <pthread.h>
52#include <stdint.h>
53#include <sys/time.h>
54#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080055#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070056#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070057#include <sys/resource.h>
58#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080059
Aalique Grahame22e49102018-12-18 14:23:57 -080060#include <log/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070061#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080062#include <cutils/str_parms.h>
63#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070064#include <cutils/atomic.h>
65#include <cutils/sched_policy.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070066#include <hardware/audio_effect.h>
Haynes Mathew George484e8d22017-07-31 18:55:17 -070067#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070068#include <system/thread_defs.h>
Haynes Mathew George16081042017-05-31 17:16:49 -070069#include <tinyalsa/asoundlib.h>
Andy Hunga1f48fa2019-07-01 18:14:53 -070070#include <utils/Timers.h> // systemTime
Eric Laurentb23d5282013-05-14 15:27:20 -070071#include <audio_effects/effect_aec.h>
72#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053073#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080074#include "audio_hw.h"
Wei Wangf7ca6c92017-11-21 14:51:20 -080075#include "audio_perf.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070076#include "platform_api.h"
77#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070078#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080079#include "voice_extn.h"
Ashish Jaind5694242017-09-05 20:09:06 +053080#include "ip_hdlr_intf.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080081
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070082#include "sound/compress_params.h"
Xiaojun Sang782e5b12020-06-29 21:13:06 +080083
84#ifdef AUDIO_GKI_ENABLED
85#include "sound/audio_compressed_formats.h"
86#endif
87
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080088#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080089
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053090#ifdef DYNAMIC_LOG_ENABLED
91#include <log_xml_parser.h>
92#define LOG_MASK HAL_MOD_FILE_AUDIO_HW
93#include <log_utils.h>
94#endif
95
Krishna Kishor Jhaaf83fd82022-11-15 17:54:07 +053096#define SKIP_INPUT_SOURCE_PRIORITY
97
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070098#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053099/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
100#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700101#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700102#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Arun Mirpuri5d170872019-03-26 13:21:31 -0700103#define MMAP_PLAYBACK_VOLUME_MAX 0x2000
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530104#define PCM_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530105#define DSD_VOLUME_MIN_DB (-110)
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700106#define INVALID_OUT_VOLUME -1
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700107#define AUDIO_IO_PORTS_MAX 32
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700108
Zhou Songbaddf9f2020-11-20 13:57:39 +0800109#define PLAYBACK_GAIN_MAX 1.0f
Aalique Grahame22e49102018-12-18 14:23:57 -0800110#define RECORD_GAIN_MIN 0.0f
111#define RECORD_GAIN_MAX 1.0f
112#define RECORD_VOLUME_CTL_MAX 0x2000
113
114/* treat as unsigned Q1.13 */
115#define APP_TYPE_GAIN_DEFAULT 0x2000
116
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700117#define PROXY_OPEN_RETRY_COUNT 100
118#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800119
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800120#define GET_USECASE_AUDIO_PLAYBACK_PRIMARY(db) \
121 (db)? USECASE_AUDIO_PLAYBACK_DEEP_BUFFER : \
122 USECASE_AUDIO_PLAYBACK_LOW_LATENCY
123#define GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(db) \
124 (db)? pcm_config_deep_buffer : pcm_config_low_latency
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800125
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700126#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700127#define DEFAULT_VOIP_BUF_DURATION_MS 20
128#define DEFAULT_VOIP_BIT_DEPTH_BYTE sizeof(int16_t)
129#define DEFAULT_VOIP_SAMP_RATE 48000
130
131#define VOIP_IO_BUF_SIZE(SR, DURATION_MS, BIT_DEPTH) (SR)/1000 * DURATION_MS * BIT_DEPTH
132
133struct pcm_config default_pcm_config_voip_copp = {
134 .channels = 1,
135 .rate = DEFAULT_VOIP_SAMP_RATE, /* changed when the stream is opened */
136 .period_size = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
137 .period_count = 2,
138 .format = PCM_FORMAT_S16_LE,
kunleiz95b597a2017-10-23 17:07:33 +0800139 .avail_min = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
140 .stop_threshold = INT_MAX,
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700141};
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700142
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700143#define MIN_CHANNEL_COUNT 1
144#define DEFAULT_CHANNEL_COUNT 2
145#define MAX_HIFI_CHANNEL_COUNT 8
146
Aalique Grahame22e49102018-12-18 14:23:57 -0800147#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
148#define MAX_CHANNEL_COUNT 1
149#else
150#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
151#define XSTR(x) STR(x)
152#define STR(x) #x
153#endif
154
Avinash Chandrad7296d42021-08-04 15:07:47 +0530155#define IS_USB_HIFI (MAX_HIFI_CHANNEL_COUNT >= MAX_CHANNEL_COUNT) ? \
156 true : false
157
Dechen Chai22768452021-07-30 09:29:16 +0530158#ifdef LINUX_ENABLED
159static inline int64_t audio_utils_ns_from_timespec(const struct timespec *ts)
160{
161 return ts->tv_sec * 1000000000LL + ts->tv_nsec;
162}
163#endif
164
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700165static unsigned int configured_low_latency_capture_period_size =
166 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
167
Haynes Mathew George16081042017-05-31 17:16:49 -0700168#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
169#define MMAP_PERIOD_COUNT_MIN 32
170#define MMAP_PERIOD_COUNT_MAX 512
171#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
172
Aalique Grahame22e49102018-12-18 14:23:57 -0800173/* This constant enables extended precision handling.
174 * TODO The flag is off until more testing is done.
175 */
176static const bool k_enable_extended_precision = false;
Arun Mirpurie008ed22019-03-21 11:21:04 -0700177extern int AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Aalique Grahame22e49102018-12-18 14:23:57 -0800178
Eric Laurentb23d5282013-05-14 15:27:20 -0700179struct pcm_config pcm_config_deep_buffer = {
180 .channels = 2,
181 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
182 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
183 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
184 .format = PCM_FORMAT_S16_LE,
185 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
186 .stop_threshold = INT_MAX,
187 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
188};
189
190struct pcm_config pcm_config_low_latency = {
191 .channels = 2,
192 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
193 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
194 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
195 .format = PCM_FORMAT_S16_LE,
196 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
197 .stop_threshold = INT_MAX,
198 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
199};
200
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800201struct pcm_config pcm_config_haptics_audio = {
202 .channels = 1,
203 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
204 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
205 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
206 .format = PCM_FORMAT_S16_LE,
207 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
208 .stop_threshold = INT_MAX,
209 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
210};
211
212struct pcm_config pcm_config_haptics = {
213 .channels = 1,
214 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
215 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
216 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
217 .format = PCM_FORMAT_S16_LE,
218 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
219 .stop_threshold = INT_MAX,
220 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
221};
222
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700223static int af_period_multiplier = 4;
224struct pcm_config pcm_config_rt = {
225 .channels = 2,
226 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
227 .period_size = ULL_PERIOD_SIZE, //1 ms
228 .period_count = 512, //=> buffer size is 512ms
229 .format = PCM_FORMAT_S16_LE,
230 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
231 .stop_threshold = INT_MAX,
232 .silence_threshold = 0,
233 .silence_size = 0,
234 .avail_min = ULL_PERIOD_SIZE, //1 ms
235};
236
Eric Laurentb23d5282013-05-14 15:27:20 -0700237struct pcm_config pcm_config_hdmi_multi = {
238 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
239 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
240 .period_size = HDMI_MULTI_PERIOD_SIZE,
241 .period_count = HDMI_MULTI_PERIOD_COUNT,
242 .format = PCM_FORMAT_S16_LE,
243 .start_threshold = 0,
244 .stop_threshold = INT_MAX,
245 .avail_min = 0,
246};
247
Haynes Mathew George16081042017-05-31 17:16:49 -0700248struct pcm_config pcm_config_mmap_playback = {
249 .channels = 2,
250 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
251 .period_size = MMAP_PERIOD_SIZE,
252 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
253 .format = PCM_FORMAT_S16_LE,
254 .start_threshold = MMAP_PERIOD_SIZE*8,
255 .stop_threshold = INT32_MAX,
256 .silence_threshold = 0,
257 .silence_size = 0,
258 .avail_min = MMAP_PERIOD_SIZE, //1 ms
259};
260
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700261struct pcm_config pcm_config_hifi = {
262 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
263 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
264 .period_size = HIFI_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
265 .period_count = HIFI_BUFFER_OUTPUT_PERIOD_COUNT,
266 .format = PCM_FORMAT_S24_3LE,
267 .start_threshold = 0,
268 .stop_threshold = INT_MAX,
269 .avail_min = 0,
270};
271
Eric Laurentb23d5282013-05-14 15:27:20 -0700272struct pcm_config pcm_config_audio_capture = {
273 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700274 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
275 .format = PCM_FORMAT_S16_LE,
276};
277
Haynes Mathew George16081042017-05-31 17:16:49 -0700278struct pcm_config pcm_config_mmap_capture = {
279 .channels = 2,
280 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
281 .period_size = MMAP_PERIOD_SIZE,
282 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
283 .format = PCM_FORMAT_S16_LE,
284 .start_threshold = 0,
285 .stop_threshold = INT_MAX,
286 .silence_threshold = 0,
287 .silence_size = 0,
288 .avail_min = MMAP_PERIOD_SIZE, //1 ms
289};
290
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700291#define AFE_PROXY_CHANNEL_COUNT 2
292#define AFE_PROXY_SAMPLING_RATE 48000
293
294#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
295#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
296
297struct pcm_config pcm_config_afe_proxy_playback = {
298 .channels = AFE_PROXY_CHANNEL_COUNT,
299 .rate = AFE_PROXY_SAMPLING_RATE,
300 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
301 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
302 .format = PCM_FORMAT_S16_LE,
303 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
304 .stop_threshold = INT_MAX,
305 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
306};
307
308#define AFE_PROXY_RECORD_PERIOD_SIZE 768
309#define AFE_PROXY_RECORD_PERIOD_COUNT 4
310
Aalique Grahame22e49102018-12-18 14:23:57 -0800311struct pcm_config pcm_config_audio_capture_rt = {
312 .channels = 2,
313 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
314 .period_size = ULL_PERIOD_SIZE,
315 .period_count = 512,
316 .format = PCM_FORMAT_S16_LE,
317 .start_threshold = 0,
318 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
319 .silence_threshold = 0,
320 .silence_size = 0,
321 .avail_min = ULL_PERIOD_SIZE, //1 ms
322};
323
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +0530324struct pcm_config pcm_config_audio_capture_rt_48KHz = {
325 .channels = 2,
326 .rate = 48000,
327 .period_size = 48,
328 .period_count = 512,
329 .format = PCM_FORMAT_S16_LE,
330 .start_threshold = 0,
331 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
332 .silence_threshold = 0,
333 .silence_size = 0,
334 .avail_min = 48, //1 ms
335};
336struct pcm_config pcm_config_audio_capture_rt_32KHz = {
337 .channels = 2,
338 .rate = 32000,
339 .period_size = 32,
340 .period_count = 512,
341 .format = PCM_FORMAT_S16_LE,
342 .start_threshold = 0,
343 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
344 .silence_threshold = 0,
345 .silence_size = 0,
346 .avail_min = 32, //1 ms
347};
348struct pcm_config pcm_config_audio_capture_rt_24KHz = {
349 .channels = 2,
350 .rate = 24000,
351 .period_size = 24,
352 .period_count = 512,
353 .format = PCM_FORMAT_S16_LE,
354 .start_threshold = 0,
355 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
356 .silence_threshold = 0,
357 .silence_size = 0,
358 .avail_min = 24, //1 ms
359};
360struct pcm_config pcm_config_audio_capture_rt_16KHz = {
361 .channels = 2,
362 .rate = 16000,
363 .period_size = 16,
364 .period_count = 512,
365 .format = PCM_FORMAT_S16_LE,
366 .start_threshold = 0,
367 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
368 .silence_threshold = 0,
369 .silence_size = 0,
370 .avail_min = 16, //1 ms
371};
372struct pcm_config pcm_config_audio_capture_rt_8KHz = {
373 .channels = 2,
374 .rate = 8000,
375 .period_size = 8,
376 .period_count = 512,
377 .format = PCM_FORMAT_S16_LE,
378 .start_threshold = 0,
379 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
380 .silence_threshold = 0,
381 .silence_size = 0,
382 .avail_min = 8, //1 ms
383};
384
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700385struct pcm_config pcm_config_afe_proxy_record = {
386 .channels = AFE_PROXY_CHANNEL_COUNT,
387 .rate = AFE_PROXY_SAMPLING_RATE,
388 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
389 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
390 .format = PCM_FORMAT_S16_LE,
391 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
392 .stop_threshold = INT_MAX,
393 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
394};
395
Ashish Jainf1eaa582016-05-23 20:54:24 +0530396#define AUDIO_MAX_PCM_FORMATS 7
397
398const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
399 [AUDIO_FORMAT_DEFAULT] = 0,
400 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
401 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
402 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
403 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
404 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
405 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
406};
407
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800408const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700409 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
410 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800411 [USECASE_AUDIO_PLAYBACK_WITH_HAPTICS] = "audio-with-haptics-playback",
Meng Wang51d8c2a2020-04-27 15:23:21 +0800412 [USECASE_AUDIO_PLAYBACK_HAPTICS] = "haptics-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700413 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
414 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700415 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700416 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700417 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
418 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
419 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
420 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
421 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
422 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
423 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
424 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
Haynes Mathew George16081042017-05-31 17:16:49 -0700425 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
426 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700427 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Aalique Grahame22e49102018-12-18 14:23:57 -0800428 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
vivek mehta0ea887a2015-08-26 14:01:20 -0700429
Eric Laurentb23d5282013-05-14 15:27:20 -0700430 [USECASE_AUDIO_RECORD] = "audio-record",
Krishna Kishor Jha0f4d8482022-02-18 10:56:05 +0530431 [USECASE_AUDIO_RECORD2] = "audio-record2",
432 [USECASE_AUDIO_RECORD3] = "audio-record3",
Mingming Yine62d7842013-10-25 16:26:03 -0700433 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530434 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
435 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
436 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Dhananjay Kumar376e38b2017-09-28 22:26:23 +0530437 [USECASE_AUDIO_RECORD_COMPRESS5] = "audio-record-compress5",
438 [USECASE_AUDIO_RECORD_COMPRESS6] = "audio-record-compress6",
Eric Laurentb23d5282013-05-14 15:27:20 -0700439 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Kogara Naveen Kumarc5758232022-11-07 20:25:40 +0530440 [USECASE_AUDIO_RECORD_LOW_LATENCY2] = "low-latency-record2",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700441 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700442 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700443 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700444
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800445 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800446 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Derek Chenf7092792017-05-23 12:23:53 -0400447 [USECASE_AUDIO_HFP_SCO_DOWNLINK] = "hfp-sco-downlink",
448 [USECASE_AUDIO_HFP_SCO_WB_DOWNLINK] = "hfp-sco-wb-downlink",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700449
Derek Chenf7092792017-05-23 12:23:53 -0400450 [USECASE_VOICE_CALL] = "voice-call",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700451 [USECASE_VOICE2_CALL] = "voice2-call",
452 [USECASE_VOLTE_CALL] = "volte-call",
453 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800454 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800455 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
456 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800457 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700458 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
459 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
460 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800461 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
462 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
463 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
464
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700465 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
466 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700467 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
468 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700469
470 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
471 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Zhou Song62ea0282020-03-22 19:53:01 +0800472 [USECASE_AUDIO_RECORD_AFE_PROXY2] = "afe-proxy-record2",
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +0530473 [USECASE_AUDIO_PLAYBACK_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700474
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530475 /* Transcode loopback cases */
Surendar Karka93cd25a2018-08-28 14:21:37 +0530476 [USECASE_AUDIO_TRANSCODE_LOOPBACK_RX] = "audio-transcode-loopback-rx",
477 [USECASE_AUDIO_TRANSCODE_LOOPBACK_TX] = "audio-transcode-loopback-tx",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700478
479 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
480 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Revathi Uddarajud9f23d92020-07-27 10:55:06 +0530481 [USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY] = "audio-record-voip-low-latency",
Varun Balaraje49253e2017-07-06 19:48:56 +0530482 /* For Interactive Audio Streams */
483 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
484 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
485 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
486 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
487 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
488 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
489 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
490 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700491
Aniket Kumar Lata7fd86e12018-02-20 19:26:10 -0800492 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture",
493
Derek Chenf6318be2017-06-12 17:16:24 -0400494 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
495
496 [USECASE_AUDIO_PLAYBACK_MEDIA] = "media-playback",
Kogara Naveen Kumarc5758232022-11-07 20:25:40 +0530497 [USECASE_AUDIO_PLAYBACK_MEDIA_LL] = "media-playback-ll",
Derek Chenf6318be2017-06-12 17:16:24 -0400498 [USECASE_AUDIO_PLAYBACK_SYS_NOTIFICATION] = "sys-notification-playback",
499 [USECASE_AUDIO_PLAYBACK_NAV_GUIDANCE] = "nav-guidance-playback",
Kogara Naveen Kumarc5758232022-11-07 20:25:40 +0530500 [USECASE_AUDIO_PLAYBACK_NAV_GUIDANCE_LL] = "nav-guidance-playback-ll",
Derek Chenf6318be2017-06-12 17:16:24 -0400501 [USECASE_AUDIO_PLAYBACK_PHONE] = "phone-playback",
Kogara Naveen Kumar65828fe2022-10-14 16:41:04 +0530502 [USECASE_AUDIO_PLAYBACK_PHONE_LL] = "phone-playback-ll",
Susan Wang117cf6f2022-04-06 20:11:46 -0400503 [USECASE_AUDIO_PLAYBACK_ALERTS] = "alerts-playback",
Kogara Naveen Kumarc5758232022-11-07 20:25:40 +0530504 [USECASE_AUDIO_PLAYBACK_ALERTS_LL] = "alerts-playback-ll",
Derek Chen1bcdc6b2020-02-06 22:44:53 -0800505 [USECASE_AUDIO_PLAYBACK_FRONT_PASSENGER] = "front-passenger-playback",
Derek Chendf05eea2019-08-01 13:57:49 -0700506 [USECASE_AUDIO_PLAYBACK_REAR_SEAT] = "rear-seat-playback",
Rahul Sharma99770982019-03-06 17:05:26 +0530507 [USECASE_AUDIO_FM_TUNER_EXT] = "fm-tuner-ext",
Derek Chena30a5f42019-12-03 11:17:09 -0500508 [USECASE_ICC_CALL] = "icc-call",
Huicheng Liu1404ba12020-09-11 01:03:25 -0400509
510 [USECASE_AUDIO_RECORD_BUS] = "audio-record",
511 [USECASE_AUDIO_RECORD_BUS_FRONT_PASSENGER] = "front-passenger-record",
512 [USECASE_AUDIO_RECORD_BUS_REAR_SEAT] = "rear-seat-record",
Fei Tongaffdf732020-02-20 20:39:05 +0800513 [USECASE_AUDIO_PLAYBACK_SYNTHESIZER] = "synth-loopback",
Susan Wange3959562021-03-11 11:50:26 -0500514 [USECASE_AUDIO_RECORD_ECHO_REF_EXT] = "echo-reference-external",
Eric Laurentb23d5282013-05-14 15:27:20 -0700515};
516
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700517static const audio_usecase_t offload_usecases[] = {
518 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700519 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
520 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
521 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
522 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
523 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
524 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
525 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
526 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700527};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800528
Varun Balaraje49253e2017-07-06 19:48:56 +0530529static const audio_usecase_t interactive_usecases[] = {
530 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
531 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
532 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
533 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
534 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
535 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
536 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
537 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
538};
539
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800540#define STRING_TO_ENUM(string) { #string, string }
541
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800542struct string_to_enum {
543 const char *name;
544 uint32_t value;
545};
546
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700547static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800548 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800549 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
550 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
551 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700552 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800553 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
554 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800555 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700556 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
557 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
558 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
559 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
560 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
561 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
562 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
563 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
564 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
565 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
566 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800567};
568
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700569static const struct string_to_enum formats_name_to_enum_table[] = {
570 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
571 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
572 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700573 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
574 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
575 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700576 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800577 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
578 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700579 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800580};
581
582//list of all supported sample rates by HDMI specification.
583static const int out_hdmi_sample_rates[] = {
584 32000, 44100, 48000, 88200, 96000, 176400, 192000,
585};
586
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700587static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800588 STRING_TO_ENUM(32000),
589 STRING_TO_ENUM(44100),
590 STRING_TO_ENUM(48000),
591 STRING_TO_ENUM(88200),
592 STRING_TO_ENUM(96000),
593 STRING_TO_ENUM(176400),
594 STRING_TO_ENUM(192000),
Mingshu pange8aedf12019-10-25 15:38:27 +0800595 STRING_TO_ENUM(352800),
596 STRING_TO_ENUM(384000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700597};
598
Carter Hsu2e429db2019-05-14 18:50:52 +0800599struct in_effect_list {
600 struct listnode list;
601 effect_handle_t handle;
602};
603
Krishna Kishor Jha0f4d8482022-02-18 10:56:05 +0530604static const audio_usecase_t record_usecases[] = {
605 USECASE_AUDIO_RECORD,
606 USECASE_AUDIO_RECORD2,
607 USECASE_AUDIO_RECORD3,
608};
609
Kogara Naveen Kumarc5758232022-11-07 20:25:40 +0530610static const audio_usecase_t low_latency_record_usecases[] = {
611 USECASE_AUDIO_RECORD_LOW_LATENCY,
612 USECASE_AUDIO_RECORD_LOW_LATENCY2,
613};
614
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700615static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700616static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700617static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700618//cache last MBDRC cal step level
619static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700620
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530621static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Arun Mirpuri5d170872019-03-26 13:21:31 -0700622static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800623static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530624static int out_set_pcm_volume(struct audio_stream_out *stream, float left, float right);
Krishna Kishor Jha10ad39f2022-02-21 17:02:47 +0530625#ifdef SOFT_VOLUME
626static int out_set_soft_volume_params(struct audio_stream_out *stream);
627#endif
Derek Chen6f293672019-04-01 01:40:24 -0700628static void adev_snd_mon_cb(void *cookie, struct str_parms *parms);
629static void in_snd_mon_cb(void * stream, struct str_parms * parms);
630static void out_snd_mon_cb(void * stream, struct str_parms * parms);
631
Zhou Song331c8e52019-08-26 14:16:12 +0800632static int configure_btsco_sample_rate(snd_device_t snd_device);
633
Vatsal Buchac09ae062018-11-14 13:25:08 +0530634#ifdef AUDIO_FEATURE_ENABLED_GCOV
635extern void __gcov_flush();
636static void enable_gcov()
637{
638 __gcov_flush();
639}
640#else
641static void enable_gcov()
642{
643}
644#endif
645
justinweng20fb6d82019-02-21 18:49:00 -0700646static int in_set_microphone_direction(const struct audio_stream_in *stream,
647 audio_microphone_direction_t dir);
648static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom);
649
Krishna Kishor Jha0f4d8482022-02-18 10:56:05 +0530650static bool is_pcm_record_usecase(audio_usecase_t uc_id)
651{
652 unsigned int record_uc_index;
653 unsigned int num_usecase = sizeof(record_usecases)/sizeof(record_usecases[0]);
654
655 for (record_uc_index = 0; record_uc_index < num_usecase; record_uc_index++) {
656 if (uc_id == record_usecases[record_uc_index])
657 return true;
658 }
659 return false;
660}
661
662static audio_usecase_t get_record_usecase(struct audio_device *adev)
663{
664 audio_usecase_t ret_uc = USECASE_INVALID;
665 unsigned int record_uc_index;
666 unsigned int num_usecase = sizeof(record_usecases)/sizeof(record_usecases[0]);
667
668 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
669 for (record_uc_index = 0; record_uc_index < num_usecase; record_uc_index++) {
670 if (!(adev->pcm_record_uc_state & (0x1 << record_uc_index))) {
671 adev->pcm_record_uc_state |= 0x1 << record_uc_index;
672 ret_uc = record_usecases[record_uc_index];
673 break;
674 }
675 }
676
677 ALOGV("%s: pcm record usecase is %d", __func__, ret_uc);
678 return ret_uc;
679}
680
681static void free_record_usecase(struct audio_device *adev,
682 audio_usecase_t uc_id)
683{
684 unsigned int record_uc_index;
685 unsigned int num_usecase = sizeof(record_usecases)/sizeof(record_usecases[0]);
686
687 for (record_uc_index = 0; record_uc_index < num_usecase; record_uc_index++) {
688 if (record_usecases[record_uc_index] == uc_id) {
689 adev->pcm_record_uc_state &= ~(0x1 << record_uc_index);
690 break;
691 }
692 }
693 ALOGV("%s: free pcm record usecase %d", __func__, uc_id);
694}
695
Kogara Naveen Kumarc5758232022-11-07 20:25:40 +0530696static bool is_pcm_low_latency_record_usecase(audio_usecase_t uc_id)
697{
698 unsigned int record_uc_index;
699 unsigned int num_usecase = sizeof(low_latency_record_usecases)/sizeof(low_latency_record_usecases[0]);
700 ALOGD("%s: Check low latency pcm record usecase", __func__);
701
702 for (record_uc_index = 0; record_uc_index < num_usecase; record_uc_index++) {
703 if (uc_id == low_latency_record_usecases[record_uc_index])
704 return true;
705 }
706 return false;
707}
708
709static audio_usecase_t get_low_latency_record_usecase(struct audio_device *adev)
710{
711 audio_usecase_t ret_uc = USECASE_INVALID;
712 unsigned int record_uc_index;
713 unsigned int num_usecase = sizeof(low_latency_record_usecases)/sizeof(low_latency_record_usecases[0]);
714
715 ALOGD("%s: get_low_latency_record_usecase: %d", __func__, num_usecase);
716 for (record_uc_index = 0; record_uc_index < num_usecase; record_uc_index++) {
717 if (!(adev->pcm_low_latency_record_uc_state & (0x1 << record_uc_index))) {
718 adev->pcm_low_latency_record_uc_state |= 0x1 << record_uc_index;
719 ALOGD("%s: get_low_latency_record_usecase: %d", __func__, record_uc_index);
720 ret_uc = low_latency_record_usecases[record_uc_index];
721 break;
722 }
723 }
724
725 ALOGD("%s: low latency pcm record usecase is %d", __func__, ret_uc);
726 return ret_uc;
727}
728
729static void free_low_latency_record_usecase(struct audio_device *adev,
730 audio_usecase_t uc_id)
731{
732 unsigned int record_uc_index;
733 unsigned int num_usecase = sizeof(low_latency_record_usecases)/sizeof(low_latency_record_usecases[0]);
734
735 for (record_uc_index = 0; record_uc_index < num_usecase; record_uc_index++) {
736 if (low_latency_record_usecases[record_uc_index] == uc_id) {
737 adev->pcm_low_latency_record_uc_state &= ~(0x1 << record_uc_index);
738 break;
739 }
740 }
741 ALOGD("%s: free low latency pcm record usecase %d", __func__, uc_id);
742}
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700743static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
744 int flags __unused)
745{
746 int dir = 0;
747 switch (uc_id) {
748 case USECASE_AUDIO_RECORD_LOW_LATENCY:
Revathi Uddarajud9f23d92020-07-27 10:55:06 +0530749 case USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY:
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700750 dir = 1;
751 case USECASE_AUDIO_PLAYBACK_ULL:
752 break;
753 default:
754 return false;
755 }
756
757 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
758 PCM_PLAYBACK : PCM_CAPTURE);
759 if (adev->adm_is_noirq_avail)
760 return adev->adm_is_noirq_avail(adev->adm_data,
761 adev->snd_card, dev_id, dir);
762 return false;
763}
764
765static void register_out_stream(struct stream_out *out)
766{
767 struct audio_device *adev = out->dev;
768 if (is_offload_usecase(out->usecase) ||
769 !adev->adm_register_output_stream)
770 return;
771
772 // register stream first for backward compatibility
773 adev->adm_register_output_stream(adev->adm_data,
774 out->handle,
775 out->flags);
776
777 if (!adev->adm_set_config)
778 return;
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +0530779#ifdef PLATFORM_AUTO
Kogara Naveen Kumar6db5fb02022-05-07 00:22:50 +0530780 if (out->realtime || (out->flags & AUDIO_OUTPUT_FLAG_SYS_NOTIFICATION))
781 adev->adm_set_config(adev->adm_data,
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700782 out->handle,
783 out->pcm, &out->config);
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +0530784#else
785 if (out->realtime)
786 adev->adm_set_config(adev->adm_data,
787 out->handle,
788 out->pcm, &out->config);
789#endif
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700790}
791
792static void register_in_stream(struct stream_in *in)
793{
794 struct audio_device *adev = in->dev;
795 if (!adev->adm_register_input_stream)
796 return;
797
798 adev->adm_register_input_stream(adev->adm_data,
799 in->capture_handle,
800 in->flags);
801
802 if (!adev->adm_set_config)
803 return;
804
805 if (in->realtime)
806 adev->adm_set_config(adev->adm_data,
807 in->capture_handle,
808 in->pcm,
809 &in->config);
810}
811
812static void request_out_focus(struct stream_out *out, long ns)
813{
814 struct audio_device *adev = out->dev;
815
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700816 if (adev->adm_request_focus_v2)
817 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
818 else if (adev->adm_request_focus)
819 adev->adm_request_focus(adev->adm_data, out->handle);
820}
821
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700822static int request_in_focus(struct stream_in *in, long ns)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700823{
824 struct audio_device *adev = in->dev;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700825 int ret = 0;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700826
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700827 if (adev->adm_request_focus_v2_1)
828 ret = adev->adm_request_focus_v2_1(adev->adm_data, in->capture_handle, ns);
829 else if (adev->adm_request_focus_v2)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700830 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
831 else if (adev->adm_request_focus)
832 adev->adm_request_focus(adev->adm_data, in->capture_handle);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700833
834 return ret;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700835}
836
837static void release_out_focus(struct stream_out *out)
838{
839 struct audio_device *adev = out->dev;
840
841 if (adev->adm_abandon_focus)
842 adev->adm_abandon_focus(adev->adm_data, out->handle);
843}
844
845static void release_in_focus(struct stream_in *in)
846{
847 struct audio_device *adev = in->dev;
848 if (adev->adm_abandon_focus)
849 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
850}
851
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530852static int parse_snd_card_status(struct str_parms *parms, int *card,
853 card_status_t *status)
854{
855 char value[32]={0};
856 char state[32]={0};
857
858 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
859 if (ret < 0)
860 return -1;
861
862 // sscanf should be okay as value is of max length 32.
863 // same as sizeof state.
864 if (sscanf(value, "%d,%s", card, state) < 2)
865 return -1;
866
867 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
868 CARD_STATUS_OFFLINE;
869 return 0;
870}
871
Avinash Chandrad7296d42021-08-04 15:07:47 +0530872bool is_combo_audio_input_device(struct listnode *devices){
873
Sandhya Mutha Naga Venkata153d95e2022-07-12 14:54:43 +0530874 if ((devices == NULL) || (!list_empty(devices)))
Avinash Chandrad7296d42021-08-04 15:07:47 +0530875 return false;
876
877 if(compare_device_type(devices, AUDIO_DEVICE_IN_BUILTIN_MIC|AUDIO_DEVICE_IN_SPEAKER_MIC2))
878 return true;
879 else
880 return false;
881}
882
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700883static inline void adjust_frames_for_device_delay(struct stream_out *out,
884 uint32_t *dsp_frames) {
885 // Adjustment accounts for A2dp encoder latency with offload usecases
886 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -0800887 if (is_a2dp_out_device_type(&out->device_list)) {
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700888 unsigned long offset =
889 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
890 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
891 }
892}
893
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700894static inline bool free_entry(void *key __unused,
895 void *value, void *context __unused)
896{
897 free(value);
898 return true;
899}
900
901static inline void free_map(Hashmap *map)
902{
903 if (map) {
904 hashmapForEach(map, free_entry, (void *) NULL);
905 hashmapFree(map);
906 }
907}
908
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800909static inline void patch_map_remove_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700910 audio_patch_handle_t patch_handle)
911{
912 if (patch_handle == AUDIO_PATCH_HANDLE_NONE)
913 return;
914
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700915 struct audio_patch_info *p_info =
916 hashmapGet(adev->patch_map, (void *) (intptr_t) patch_handle);
917 if (p_info) {
918 ALOGV("%s: Remove patch %d", __func__, patch_handle);
919 hashmapRemove(adev->patch_map, (void *) (intptr_t) patch_handle);
920 free(p_info->patch);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700921 free(p_info);
922 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700923}
924
925static inline int io_streams_map_insert(struct audio_device *adev,
926 struct audio_stream *stream,
927 audio_io_handle_t handle,
928 audio_patch_handle_t patch_handle)
929{
930 struct audio_stream_info *s_info =
931 (struct audio_stream_info *) calloc(1, sizeof(struct audio_stream_info));
932
933 if (s_info == NULL) {
934 ALOGE("%s: Could not allocate stream info", __func__);
935 return -ENOMEM;
936 }
937 s_info->stream = stream;
938 s_info->patch_handle = patch_handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700939
940 pthread_mutex_lock(&adev->lock);
941 struct audio_stream_info *stream_info =
942 hashmapPut(adev->io_streams_map, (void *) (intptr_t) handle, (void *) s_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700943 if (stream_info != NULL)
944 free(stream_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800945 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Latad13758f2020-08-06 15:11:36 -0700946 ALOGV("%s: Added stream in io_streams_map with handle %d", __func__, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700947 return 0;
948}
949
950static inline void io_streams_map_remove(struct audio_device *adev,
951 audio_io_handle_t handle)
952{
953 pthread_mutex_lock(&adev->lock);
954 struct audio_stream_info *s_info =
955 hashmapRemove(adev->io_streams_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700956 if (s_info == NULL)
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800957 goto done;
Aniket Kumar Latad13758f2020-08-06 15:11:36 -0700958 ALOGV("%s: Removed stream with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800959 patch_map_remove_l(adev, s_info->patch_handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700960 free(s_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800961done:
962 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700963 return;
964}
965
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800966static struct audio_patch_info* fetch_patch_info_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700967 audio_patch_handle_t handle)
968{
969 struct audio_patch_info *p_info = NULL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700970 p_info = (struct audio_patch_info *)
971 hashmapGet(adev->patch_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700972 return p_info;
973}
974
vivek mehtaa76401a2015-04-24 14:12:15 -0700975__attribute__ ((visibility ("default")))
976bool audio_hw_send_gain_dep_calibration(int level) {
977 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700978 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700979
980 pthread_mutex_lock(&adev_init_lock);
981
982 if (adev != NULL && adev->platform != NULL) {
983 pthread_mutex_lock(&adev->lock);
984 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700985
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530986 // cache level info for any of the use case which
987 // was not started.
988 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700989
vivek mehtaa76401a2015-04-24 14:12:15 -0700990 pthread_mutex_unlock(&adev->lock);
991 } else {
992 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
993 }
994
995 pthread_mutex_unlock(&adev_init_lock);
996
997 return ret_val;
998}
999
Ashish Jain5106d362016-05-11 19:23:33 +05301000static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
1001{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08001002 bool gapless_enabled = false;
1003 const char *mixer_ctl_name = "Compress Gapless Playback";
1004 struct mixer_ctl *ctl;
1005
1006 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07001007 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +05301008
1009 /*Disable gapless if its AV playback*/
1010 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08001011
1012 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1013 if (!ctl) {
1014 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1015 __func__, mixer_ctl_name);
1016 return -EINVAL;
1017 }
1018
1019 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
1020 ALOGE("%s: Could not set gapless mode %d",
1021 __func__, gapless_enabled);
1022 return -EINVAL;
1023 }
1024 return 0;
1025}
Haynes Mathew George5191a852013-09-11 14:19:36 -07001026
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -07001027__attribute__ ((visibility ("default")))
1028int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
1029 int table_size) {
1030 int ret_val = 0;
1031 ALOGV("%s: enter ... ", __func__);
1032
1033 pthread_mutex_lock(&adev_init_lock);
1034 if (adev == NULL) {
1035 ALOGW("%s: adev is NULL .... ", __func__);
1036 goto done;
1037 }
1038
1039 pthread_mutex_lock(&adev->lock);
1040 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
1041 pthread_mutex_unlock(&adev->lock);
1042done:
1043 pthread_mutex_unlock(&adev_init_lock);
1044 ALOGV("%s: exit ... ", __func__);
1045 return ret_val;
1046}
1047
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001048bool audio_hw_send_qdsp_parameter(int stream_type, float vol, bool active)
Aalique Grahame22e49102018-12-18 14:23:57 -08001049{
1050 bool ret = false;
1051 ALOGV("%s: enter ...", __func__);
1052
1053 pthread_mutex_lock(&adev_init_lock);
1054
1055 if (adev != NULL && adev->platform != NULL) {
1056 pthread_mutex_lock(&adev->lock);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001057 ret = audio_extn_qdsp_set_state(adev, stream_type, vol, active);
Aalique Grahame22e49102018-12-18 14:23:57 -08001058 pthread_mutex_unlock(&adev->lock);
1059 }
1060
1061 pthread_mutex_unlock(&adev_init_lock);
1062
1063 ALOGV("%s: exit with ret %d", __func__, ret);
1064 return ret;
1065}
Aalique Grahame22e49102018-12-18 14:23:57 -08001066
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001067static bool is_supported_format(audio_format_t format)
1068{
Eric Laurent86e17132013-09-12 17:49:30 -07001069 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +05301070 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +05301071 format == AUDIO_FORMAT_AAC_LC ||
1072 format == AUDIO_FORMAT_AAC_HE_V1 ||
1073 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +05301074 format == AUDIO_FORMAT_AAC_ADTS_LC ||
1075 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
1076 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05301077 format == AUDIO_FORMAT_AAC_LATM_LC ||
1078 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
1079 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +05301080 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
1081 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +05301082 format == AUDIO_FORMAT_PCM_FLOAT ||
1083 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -07001084 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301085 format == AUDIO_FORMAT_AC3 ||
1086 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -07001087 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301088 format == AUDIO_FORMAT_DTS ||
1089 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001090 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301091 format == AUDIO_FORMAT_ALAC ||
1092 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301093 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301094 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001095 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05301096 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07001097 format == AUDIO_FORMAT_APTX ||
1098 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08001099 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001100
1101 return false;
1102}
1103
Kunlei Zhang67cc7072020-12-18 17:16:49 +08001104static bool is_supported_conc_usecase_for_power_mode_call(struct audio_device *adev)
1105{
1106 struct listnode *node;
1107 struct audio_usecase *usecase;
1108
1109 list_for_each(node, &adev->usecase_list) {
1110 usecase = node_to_item(node, struct audio_usecase, list);
1111 if (usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1112 ALOGD("%s: FM usecase is active, not setting power mode", __func__);
1113 return false;
1114 }
1115 }
1116
1117 return true;
1118}
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001119static inline bool is_mmap_usecase(audio_usecase_t uc_id)
1120{
1121 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
Zhou Song62ea0282020-03-22 19:53:01 +08001122 (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY2) ||
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001123 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
1124}
1125
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07001126static inline bool is_valid_volume(float left, float right)
1127{
1128 return ((left >= 0.0f && right >= 0.0f) ? true : false);
1129}
1130
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301131static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301132{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301133 ALOGV("%s", __func__);
1134 audio_route_apply_and_update_path(adev->audio_route,
1135 "asrc-mode");
1136 adev->asrc_mode_enabled = true;
1137}
1138
1139static void disable_asrc_mode(struct audio_device *adev)
1140{
1141 ALOGV("%s", __func__);
1142 audio_route_reset_and_update_path(adev->audio_route,
1143 "asrc-mode");
1144 adev->asrc_mode_enabled = false;
1145}
1146
Saurav Kumarc1411662020-10-14 10:50:45 +05301147static void check_and_configure_headphone(struct audio_device *adev,
1148 struct audio_usecase *uc_info,
1149 snd_device_t snd_device)
1150{
1151 struct listnode *node;
1152 struct audio_usecase *usecase;
1153 int new_backend_idx, usecase_backend_idx;
1154 bool spkr_hph_single_be_native_concurrency;
1155
1156 new_backend_idx = platform_get_backend_index(snd_device);
1157 spkr_hph_single_be_native_concurrency = platform_get_spkr_hph_single_be_native_concurrency_flag();
Zhou Songd4b18c42021-01-14 15:15:29 +08001158 if ((spkr_hph_single_be_native_concurrency && (new_backend_idx == DEFAULT_CODEC_BACKEND)) ||
1159 uc_info->id == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
Saurav Kumarc1411662020-10-14 10:50:45 +05301160 list_for_each(node, &adev->usecase_list) {
1161 usecase = node_to_item(node, struct audio_usecase, list);
1162 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
1163 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
1164 if (((usecase_backend_idx == HEADPHONE_BACKEND) ||
1165 (usecase_backend_idx == HEADPHONE_44_1_BACKEND)) &&
1166 ((usecase->stream.out->sample_rate % OUTPUT_SAMPLING_RATE_44100) == 0)) {
1167 disable_audio_route(adev, usecase);
1168 disable_snd_device(adev, usecase->out_snd_device);
1169 usecase->stream.out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Saurav Kumar70902382020-10-28 11:16:04 +05301170 platform_check_and_set_codec_backend_cfg(adev, usecase,
1171 usecase->out_snd_device);
Saurav Kumarc1411662020-10-14 10:50:45 +05301172 enable_snd_device(adev, usecase->out_snd_device);
Zhou Songd4b18c42021-01-14 15:15:29 +08001173 enable_audio_route(adev, usecase);
Saurav Kumarc1411662020-10-14 10:50:45 +05301174 }
1175 }
Revathi Uddaraju2c0eac02021-07-27 02:06:42 -07001176 else if ((usecase->type != PCM_CAPTURE) && (usecase == uc_info)) {
1177 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
1178 if (((usecase_backend_idx == HEADPHONE_BACKEND) ||
1179 (usecase_backend_idx == HEADPHONE_44_1_BACKEND)) &&
1180 ((usecase->stream.out->sample_rate % OUTPUT_SAMPLING_RATE_44100) == 0)) {
1181 usecase->stream.out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1182 platform_check_and_set_codec_backend_cfg(adev, usecase,
1183 usecase->out_snd_device);
1184 }
1185 }
Saurav Kumarc1411662020-10-14 10:50:45 +05301186 }
1187 }
1188}
1189
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301190/*
1191 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
1192 * 44.1 or Native DSD backends are enabled for any of current use case.
1193 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
1194 * - Disable current mix path use case(Headphone backend) and re-enable it with
1195 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
1196 * e.g. Naitve DSD or Headphone 44.1 -> + 48
1197 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301198static void check_and_set_asrc_mode(struct audio_device *adev,
1199 struct audio_usecase *uc_info,
1200 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301201{
1202 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301203 int i, num_new_devices = 0;
1204 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
1205 /*
1206 *Split snd device for new combo use case
1207 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
1208 */
1209 if (platform_split_snd_device(adev->platform,
1210 snd_device,
1211 &num_new_devices,
1212 split_new_snd_devices) == 0) {
1213 for (i = 0; i < num_new_devices; i++)
1214 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
1215 } else {
1216 int new_backend_idx = platform_get_backend_index(snd_device);
1217 if (((new_backend_idx == HEADPHONE_BACKEND) ||
1218 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
1219 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
1220 !adev->asrc_mode_enabled) {
1221 struct listnode *node = NULL;
1222 struct audio_usecase *uc = NULL;
1223 struct stream_out *curr_out = NULL;
1224 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
1225 int i, num_devices, ret = 0;
1226 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301227
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301228 list_for_each(node, &adev->usecase_list) {
1229 uc = node_to_item(node, struct audio_usecase, list);
1230 curr_out = (struct stream_out*) uc->stream.out;
1231 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
1232 /*
1233 *Split snd device for existing combo use case
1234 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
1235 */
1236 ret = platform_split_snd_device(adev->platform,
1237 uc->out_snd_device,
1238 &num_devices,
1239 split_snd_devices);
1240 if (ret < 0 || num_devices == 0) {
1241 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
1242 split_snd_devices[0] = uc->out_snd_device;
1243 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -08001244 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301245 for (i = 0; i < num_devices; i++) {
1246 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
1247 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
1248 if((new_backend_idx == HEADPHONE_BACKEND) &&
1249 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
1250 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07001251 ALOGV("%s:DSD or native stream detected enabling asrcmode in hardware",
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301252 __func__);
1253 enable_asrc_mode(adev);
1254 break;
1255 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
1256 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
1257 (usecase_backend_idx == HEADPHONE_BACKEND)) {
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07001258 ALOGV("%s: 48K stream detected, disabling and enabling it \
1259 with asrcmode in hardware", __func__);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301260 disable_audio_route(adev, uc);
1261 disable_snd_device(adev, uc->out_snd_device);
1262 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
1263 if (new_backend_idx == DSD_NATIVE_BACKEND)
1264 audio_route_apply_and_update_path(adev->audio_route,
1265 "hph-true-highquality-mode");
1266 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
1267 (curr_out->bit_width >= 24))
1268 audio_route_apply_and_update_path(adev->audio_route,
1269 "hph-highquality-mode");
1270 enable_asrc_mode(adev);
1271 enable_snd_device(adev, uc->out_snd_device);
1272 enable_audio_route(adev, uc);
1273 break;
1274 }
1275 }
1276 // reset split devices count
1277 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -08001278 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301279 if (adev->asrc_mode_enabled)
1280 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301281 }
1282 }
1283 }
1284}
1285
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001286static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
1287 struct audio_effect_config effect_config,
1288 unsigned int param_value)
1289{
1290 char mixer_ctl_name[] = "Audio Effect";
1291 struct mixer_ctl *ctl;
1292 long set_values[6];
Eric Laurent637e2d42018-11-15 12:24:31 -08001293 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001294
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001295 if (in == NULL) {
1296 ALOGE("%s: active input stream is NULL", __func__);
1297 return -EINVAL;
1298 }
1299
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001300 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1301 if (!ctl) {
1302 ALOGE("%s: Could not get mixer ctl - %s",
1303 __func__, mixer_ctl_name);
1304 return -EINVAL;
1305 }
1306
1307 set_values[0] = 1; //0:Rx 1:Tx
1308 set_values[1] = in->app_type_cfg.app_type;
1309 set_values[2] = (long)effect_config.module_id;
1310 set_values[3] = (long)effect_config.instance_id;
1311 set_values[4] = (long)effect_config.param_id;
1312 set_values[5] = param_value;
1313
1314 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
1315
1316 return 0;
1317
1318}
1319
1320static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
1321 int effect_type, unsigned int *param_value)
1322{
1323 int ret = 0;
1324 struct audio_effect_config other_effect_config;
1325 struct audio_usecase *usecase = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08001326 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001327
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001328 if (in == NULL) {
1329 ALOGE("%s: active input stream is NULL", __func__);
1330 return -EINVAL;
1331 }
1332
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001333 usecase = get_usecase_from_list(adev, in->usecase);
1334 if (!usecase)
1335 return -EINVAL;
1336
1337 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
1338 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
1339 if (ret < 0) {
1340 ALOGE("%s Failed to get effect params %d", __func__, ret);
1341 return ret;
1342 }
1343
1344 if (module_id == other_effect_config.module_id) {
1345 //Same module id for AEC/NS. Values need to be combined
1346 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
1347 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
1348 *param_value |= other_effect_config.param_value;
1349 }
1350 }
1351
1352 return ret;
1353}
1354
1355static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
Gangadhar Sb0210342019-02-22 17:39:41 +05301356{
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001357 struct audio_effect_config effect_config;
1358 struct audio_usecase *usecase = NULL;
1359 int ret = 0;
1360 unsigned int param_value = 0;
Eric Laurent637e2d42018-11-15 12:24:31 -08001361 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001362
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001363 if(!voice_extn_is_dynamic_ecns_enabled())
1364 return ENOSYS;
1365
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001366 if (!in) {
1367 ALOGE("%s: Invalid input stream", __func__);
1368 return -EINVAL;
1369 }
1370
1371 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
1372
1373 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +08001374 if (usecase == NULL) {
1375 ALOGE("%s: Could not find the usecase (%d) in the list",
1376 __func__, in->usecase);
1377 return -EINVAL;
1378 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001379
1380 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
1381 if (ret < 0) {
1382 ALOGE("%s Failed to get module id %d", __func__, ret);
1383 return ret;
1384 }
1385 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
1386 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
1387
1388 if(enable)
1389 param_value = effect_config.param_value;
1390
1391 /*Special handling for AEC & NS effects Param values need to be
1392 updated if module ids are same*/
1393
1394 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
1395 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
1396 if (ret < 0)
1397 return ret;
1398 }
1399
1400 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
1401
1402 return ret;
1403}
1404
1405static void check_and_enable_effect(struct audio_device *adev)
1406{
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001407 if(!voice_extn_is_dynamic_ecns_enabled())
1408 return;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001409
Eric Laurent637e2d42018-11-15 12:24:31 -08001410 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001411
Eric Laurent637e2d42018-11-15 12:24:31 -08001412 if (in != NULL && !in->standby) {
1413 if (in->enable_aec)
1414 enable_disable_effect(adev, EFFECT_AEC, true);
1415
1416 if (in->enable_ns &&
1417 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1418 enable_disable_effect(adev, EFFECT_NS, true);
1419 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001420 }
1421}
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001422
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001423int pcm_ioctl(struct pcm *pcm, int request, ...)
1424{
1425 va_list ap;
1426 void * arg;
1427 int pcm_fd = *(int*)pcm;
1428
1429 va_start(ap, request);
1430 arg = va_arg(ap, void *);
1431 va_end(ap);
1432
1433 return ioctl(pcm_fd, request, arg);
1434}
1435
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001436int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001437 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001438{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001439 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001440 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +05301441 struct stream_out *out = NULL;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301442 struct stream_in *in = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001443 struct listnode out_devices;
Soumya Managoli6993b762018-06-28 16:04:57 +05301444 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001445
1446 if (usecase == NULL)
1447 return -EINVAL;
1448
1449 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
1450
Carter Hsu2e429db2019-05-14 18:50:52 +08001451 if (usecase->type == PCM_CAPTURE) {
1452 struct stream_in *in = usecase->stream.in;
1453 struct audio_usecase *uinfo;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001454 snd_device = usecase->in_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001455
1456 if (in) {
1457 if (in->enable_aec || in->enable_ec_port) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001458 list_init(&out_devices);
1459 update_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "", true);
Carter Hsu2e429db2019-05-14 18:50:52 +08001460 struct listnode *node;
1461 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1462 USECASE_AUDIO_PLAYBACK_VOIP);
1463 if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001464 assign_devices(&out_devices,
1465 &voip_usecase->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001466 } else if (adev->primary_output &&
1467 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001468 assign_devices(&out_devices,
1469 &adev->primary_output->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001470 } else {
1471 list_for_each(node, &adev->usecase_list) {
1472 uinfo = node_to_item(node, struct audio_usecase, list);
1473 if (uinfo->type != PCM_CAPTURE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001474 assign_devices(&out_devices,
1475 &uinfo->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001476 break;
1477 }
1478 }
1479 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001480
1481 platform_set_echo_reference(adev, true, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001482 in->ec_opened = true;
Zhenlin Lian4f947842022-05-14 15:50:52 +05301483 clear_devices(&out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001484 }
1485 }
Guodong Huf5e614d2019-06-24 18:42:03 +08001486 } else if ((usecase->type == TRANSCODE_LOOPBACK_TX) || ((usecase->type == PCM_HFP_CALL) &&
1487 ((usecase->id == USECASE_AUDIO_HFP_SCO) || (usecase->id == USECASE_AUDIO_HFP_SCO_WB)) &&
1488 (usecase->in_snd_device == SND_DEVICE_IN_VOICE_SPEAKER_MIC_HFP_MMSECNS))) {
Carter Hsu2e429db2019-05-14 18:50:52 +08001489 snd_device = usecase->in_snd_device;
1490 } else {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001491 snd_device = usecase->out_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001492 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001493
Kunlei Zhanga3c4cb02021-03-05 16:03:54 +08001494 if (usecase->type == PCM_CAPTURE) {
1495 if (platform_get_fluence_nn_state(adev->platform) == 0) {
1496 platform_set_fluence_nn_state(adev->platform, true);
1497 ALOGD("%s: set fluence nn capture state", __func__);
1498 }
1499 }
1500
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001501#ifdef DS1_DOLBY_DAP_ENABLED
1502 audio_extn_dolby_set_dmid(adev);
1503 audio_extn_dolby_set_endpoint(adev);
1504#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001505 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001506 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301507 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001508 audio_extn_utils_send_app_type_cfg(adev, usecase);
Jasmine Cha4dcc1092019-03-04 18:12:47 +08001509 if (audio_extn_is_maxx_audio_enabled())
1510 audio_extn_ma_set_device(usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301511 audio_extn_utils_send_audio_calibration(adev, usecase);
Zhou Songbaddf9f2020-11-20 13:57:39 +08001512 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1513 out = usecase->stream.out;
1514 if (out && out->compr)
Manish Dewangan58229382017-02-02 15:48:41 +05301515 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1516 }
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301517
1518 if (usecase->type == PCM_CAPTURE) {
Kunlei Zhanga3c4cb02021-03-05 16:03:54 +08001519 if (platform_get_fluence_nn_state(adev->platform) == 1 &&
1520 adev->fluence_nn_usecase_id == USECASE_INVALID ) {
1521 adev->fluence_nn_usecase_id = usecase->id;
1522 ALOGD("%s: assign fluence nn usecase %d", __func__, usecase->id);
1523 }
1524 }
1525
1526 if (usecase->type == PCM_CAPTURE) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301527 in = usecase->stream.in;
Avinash Chandrad7296d42021-08-04 15:07:47 +05301528 if ((in && is_loopback_input_device(get_device_types(&in->device_list))) ||
1529 (in && is_combo_audio_input_device(&in->device_list)) ||
1530 (in && ((compare_device_type(&in->device_list, AUDIO_DEVICE_IN_BUILTIN_MIC) ||
1531 compare_device_type(&in->device_list, AUDIO_DEVICE_IN_LINE)) &&
1532 (snd_device == SND_DEVICE_IN_HANDSET_GENERIC_6MIC)))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301533 ALOGD("%s: set custom mtmx params v1", __func__);
1534 audio_extn_set_custom_mtmx_params_v1(adev, usecase, true);
1535 }
1536 } else {
1537 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
1538 }
Manish Dewangan58229382017-02-02 15:48:41 +05301539
Andy Hung756ecc12018-10-19 17:47:12 -07001540 // we shouldn't truncate mixer_path
1541 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1542 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1543 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001544 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001545 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301546 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1547 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1548 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1549 if (parms) {
1550 audio_extn_fm_set_parameters(adev, parms);
1551 str_parms_destroy(parms);
1552 }
1553 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001554 ALOGV("%s: exit", __func__);
1555 return 0;
1556}
1557
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001558int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001559 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001560{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001561 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001562 char mixer_path[MIXER_PATH_MAX_LENGTH];
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301563 struct stream_in *in = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001564
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301565 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001566 return -EINVAL;
1567
1568 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301569 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001570 snd_device = usecase->in_snd_device;
1571 else
1572 snd_device = usecase->out_snd_device;
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001573
1574 /* disable island and power mode on supported device for voice call */
1575 if (usecase->type == VOICE_CALL) {
1576 if (usecase->in_snd_device != SND_DEVICE_NONE) {
1577 if (platform_get_island_cfg_on_device(adev->platform, usecase->in_snd_device) &&
1578 platform_get_power_mode_on_device(adev->platform, usecase->in_snd_device)) {
1579 platform_set_island_cfg_on_device(adev, usecase->in_snd_device, false);
1580 platform_set_power_mode_on_device(adev, usecase->in_snd_device, false);
1581 platform_reset_island_power_status(adev->platform, usecase->in_snd_device);
Kunlei Zhang91c4b332020-07-20 17:53:14 +08001582 if (voice_is_lte_call_active(adev))
1583 platform_set_tx_lpi_mode(adev->platform, false);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001584 ALOGD("%s: disable island cfg and power mode in voice tx path",
1585 __func__);
1586 }
1587 }
1588 if (usecase->out_snd_device != SND_DEVICE_NONE) {
1589 if (platform_get_island_cfg_on_device(adev->platform, usecase->out_snd_device) &&
1590 platform_get_power_mode_on_device(adev->platform, usecase->out_snd_device)) {
1591 platform_set_island_cfg_on_device(adev, usecase->out_snd_device, false);
1592 platform_set_power_mode_on_device(adev, usecase->out_snd_device, false);
1593 platform_reset_island_power_status(adev->platform, usecase->out_snd_device);
1594 ALOGD("%s: disable island cfg and power mode in voice rx path",
1595 __func__);
1596 }
1597 }
1598 }
1599
Andy Hung756ecc12018-10-19 17:47:12 -07001600 // we shouldn't truncate mixer_path
1601 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1602 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1603 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001604 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001605 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001606 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Carter Hsu2e429db2019-05-14 18:50:52 +08001607 if (usecase->type == PCM_CAPTURE) {
1608 struct stream_in *in = usecase->stream.in;
1609 if (in && in->ec_opened) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001610 struct listnode out_devices;
1611 list_init(&out_devices);
1612 platform_set_echo_reference(in->dev, false, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001613 in->ec_opened = false;
Zhenlin Lian4f947842022-05-14 15:50:52 +05301614 clear_devices(&out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001615 }
1616 }
Kunlei Zhanga3c4cb02021-03-05 16:03:54 +08001617 if (usecase->id == adev->fluence_nn_usecase_id) {
1618 platform_set_fluence_nn_state(adev->platform, false);
1619 adev->fluence_nn_usecase_id = USECASE_INVALID;
1620 ALOGD("%s: reset fluence nn capture state", __func__);
1621 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001622 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301623 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301624
1625 if (usecase->type == PCM_CAPTURE) {
1626 in = usecase->stream.in;
Avinash Chandrad7296d42021-08-04 15:07:47 +05301627 if ((in && is_loopback_input_device(get_device_types(&in->device_list))) ||
1628 (in && is_combo_audio_input_device(&in->device_list)) ||
1629 (in && ((compare_device_type(&in->device_list, AUDIO_DEVICE_IN_BUILTIN_MIC) ||
1630 compare_device_type(&in->device_list, AUDIO_DEVICE_IN_LINE)) &&
1631 (snd_device == SND_DEVICE_IN_HANDSET_GENERIC_6MIC)))){
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301632 ALOGD("%s: reset custom mtmx params v1", __func__);
1633 audio_extn_set_custom_mtmx_params_v1(adev, usecase, false);
1634 }
1635 } else {
1636 audio_extn_set_custom_mtmx_params_v2(adev, usecase, false);
1637 }
1638
Weiyin Jiang298ffd92019-06-03 14:29:30 +08001639 if ((usecase->type == PCM_PLAYBACK) &&
1640 (usecase->stream.out != NULL))
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05301641 usecase->stream.out->pspd_coeff_sent = false;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301642
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001643 ALOGV("%s: exit", __func__);
1644 return 0;
1645}
1646
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001647int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001648 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001649{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301650 int i, num_devices = 0;
1651 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001652 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1653
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001654 if (snd_device < SND_DEVICE_MIN ||
1655 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001656 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001657 return -EINVAL;
1658 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001659
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001660 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001661 ALOGE("%s: Invalid sound device returned", __func__);
1662 return -EINVAL;
1663 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001664
1665 adev->snd_dev_ref_cnt[snd_device]++;
1666
1667 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1668 (platform_split_snd_device(adev->platform,
1669 snd_device,
1670 &num_devices,
1671 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001672 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001673 __func__, snd_device, device_name);
Aniket Kumar Lata990de552019-07-11 14:20:23 -07001674 /* Set backend config for A2DP to ensure slimbus configuration
1675 is correct if A2DP is already active and backend is closed
1676 and re-opened */
1677 if (snd_device == SND_DEVICE_OUT_BT_A2DP)
1678 audio_extn_a2dp_set_source_backend_cfg();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001679 return 0;
1680 }
1681
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001682 if (audio_extn_spkr_prot_is_enabled())
1683 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001684
Aalique Grahame22e49102018-12-18 14:23:57 -08001685 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1686
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001687 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1688 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001689 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1690 goto err;
1691 }
1692 audio_extn_dev_arbi_acquire(snd_device);
1693 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001694 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001695 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001696 goto err;
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001697 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001698 } else if (platform_split_snd_device(adev->platform,
1699 snd_device,
1700 &num_devices,
1701 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301702 for (i = 0; i < num_devices; i++) {
1703 enable_snd_device(adev, new_snd_devices[i]);
1704 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001705 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001706 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001707 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301708
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001709 /* enable island and power mode on supported device */
1710 if (platform_get_island_cfg_on_device(adev->platform, snd_device) &&
1711 platform_get_power_mode_on_device(adev->platform, snd_device)) {
1712 platform_set_island_cfg_on_device(adev, snd_device, true);
1713 platform_set_power_mode_on_device(adev, snd_device, true);
Kunlei Zhang91c4b332020-07-20 17:53:14 +08001714 if (voice_is_lte_call_active(adev) &&
1715 (snd_device >= SND_DEVICE_IN_BEGIN &&
1716 snd_device < SND_DEVICE_IN_END))
1717 platform_set_tx_lpi_mode(adev->platform, true);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001718 ALOGD("%s: enable island cfg and power mode on: %s",
1719 __func__, device_name);
1720 }
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301721
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301722 if (SND_DEVICE_OUT_BT_A2DP == snd_device) {
Ramjee Singh2d2944a2021-12-14 14:13:41 +05301723
1724 struct audio_usecase *usecase;
1725 struct listnode *node;
1726 /* Disable SCO Devices and enable handset mic for active input stream */
1727 list_for_each(node, &adev->usecase_list) {
1728 usecase = node_to_item(node, struct audio_usecase, list);
1729 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
1730 is_sco_in_device_type(&usecase->stream.in->device_list)) {
1731 ALOGD("a2dp resumed, switch bt sco mic to handset mic");
1732 reassign_device_list(&usecase->stream.in->device_list,
1733 AUDIO_DEVICE_IN_BUILTIN_MIC, "");
1734 select_devices(adev, usecase->id);
1735 }
1736 }
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301737 if (audio_extn_a2dp_start_playback() < 0) {
1738 ALOGE(" fail to configure A2dp Source control path ");
1739 goto err;
1740 } else {
1741 adev->a2dp_started = true;
1742 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001743 }
Florian Pfister1a84f312018-07-19 14:38:18 +02001744
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001745 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1746 (audio_extn_a2dp_start_capture() < 0)) {
1747 ALOGE(" fail to configure A2dp Sink control path ");
1748 goto err;
1749 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301750
Mingshu Pang7be5b1d2020-03-04 15:24:38 +08001751 if ((SND_DEVICE_OUT_BT_SCO_SWB == snd_device) ||
1752 (SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC == snd_device) ||
1753 (SND_DEVICE_IN_BT_SCO_MIC_SWB == snd_device)) {
1754 if (!adev->bt_sco_on || (audio_extn_sco_start_configuration() < 0)) {
1755 ALOGE(" fail to configure sco control path ");
1756 goto err;
1757 }
Zhou Song12c29502019-03-16 10:37:18 +08001758 }
1759
Zhou Song331c8e52019-08-26 14:16:12 +08001760 configure_btsco_sample_rate(snd_device);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001761 /* due to the possibility of calibration overwrite between listen
1762 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001763 audio_extn_sound_trigger_update_device_status(snd_device,
1764 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301765 audio_extn_listen_update_device_status(snd_device,
1766 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001767 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001768 audio_extn_sound_trigger_update_device_status(snd_device,
1769 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301770 audio_extn_listen_update_device_status(snd_device,
1771 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001772 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001773 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001774 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001775 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301776
1777 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1778 !adev->native_playback_enabled &&
1779 audio_is_true_native_stream_active(adev)) {
1780 ALOGD("%s: %d: napb: enabling native mode in hardware",
1781 __func__, __LINE__);
1782 audio_route_apply_and_update_path(adev->audio_route,
1783 "true-native-mode");
1784 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301785 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301786 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1787 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001788 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001789 ALOGD("%s: init ec ref loopback", __func__);
1790 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1791 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001792 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001793 return 0;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001794err:
1795 adev->snd_dev_ref_cnt[snd_device]--;
1796 return -EINVAL;;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001797}
1798
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001799int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001800 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001801{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301802 int i, num_devices = 0;
1803 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001804 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1805
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001806 if (snd_device < SND_DEVICE_MIN ||
1807 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001808 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001809 return -EINVAL;
1810 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001811
1812 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1813 ALOGE("%s: Invalid sound device returned", __func__);
1814 return -EINVAL;
1815 }
1816
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001817 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1818 ALOGE("%s: device ref cnt is already 0", __func__);
1819 return -EINVAL;
1820 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001821
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001822 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001823
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001824
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001825 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001826 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301827
Aalique Grahame22e49102018-12-18 14:23:57 -08001828 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1829
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001830 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1831 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001832 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001833
1834 // when speaker device is disabled, reset swap.
1835 // will be renabled on usecase start
1836 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001837 } else if (platform_split_snd_device(adev->platform,
1838 snd_device,
1839 &num_devices,
1840 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301841 for (i = 0; i < num_devices; i++) {
1842 disable_snd_device(adev, new_snd_devices[i]);
1843 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001844 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001845 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001846 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001847 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001848
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301849 if (snd_device == SND_DEVICE_OUT_BT_A2DP) {
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301850 audio_extn_a2dp_stop_playback();
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301851 adev->a2dp_started = false;
1852 } else if (snd_device == SND_DEVICE_IN_BT_A2DP)
Florian Pfister1a84f312018-07-19 14:38:18 +02001853 audio_extn_a2dp_stop_capture();
Zhou Songd6d71752019-05-21 18:08:51 +08001854 else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001855 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
Ashish Jain81eb2a82015-05-13 10:52:34 +05301856 adev->is_channel_status_set = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001857 else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301858 adev->native_playback_enabled) {
1859 ALOGD("%s: %d: napb: disabling native mode in hardware",
1860 __func__, __LINE__);
1861 audio_route_reset_and_update_path(adev->audio_route,
1862 "true-native-mode");
1863 adev->native_playback_enabled = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001864 } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301865 adev->asrc_mode_enabled) {
1866 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301867 disable_asrc_mode(adev);
1868 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001869 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301870 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001871 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001872 ALOGD("%s: deinit ec ref loopback", __func__);
1873 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1874 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001875
1876 audio_extn_utils_release_snd_device(snd_device);
1877 } else {
1878 if (platform_split_snd_device(adev->platform,
1879 snd_device,
1880 &num_devices,
1881 new_snd_devices) == 0) {
1882 for (i = 0; i < num_devices; i++) {
1883 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1884 }
1885 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001886 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001887
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001888 return 0;
1889}
1890
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001891/*
1892 legend:
1893 uc - existing usecase
1894 new_uc - new usecase
1895 d1, d11, d2 - SND_DEVICE enums
1896 a1, a2 - corresponding ANDROID device enums
1897 B1, B2 - backend strings
1898
1899case 1
1900 uc->dev d1 (a1) B1
1901 new_uc->dev d1 (a1), d2 (a2) B1, B2
1902
1903 resolution: disable and enable uc->dev on d1
1904
1905case 2
1906 uc->dev d1 (a1) B1
1907 new_uc->dev d11 (a1) B1
1908
1909 resolution: need to switch uc since d1 and d11 are related
1910 (e.g. speaker and voice-speaker)
1911 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1912
1913case 3
1914 uc->dev d1 (a1) B1
1915 new_uc->dev d2 (a2) B2
1916
1917 resolution: no need to switch uc
1918
1919case 4
1920 uc->dev d1 (a1) B1
1921 new_uc->dev d2 (a2) B1
1922
1923 resolution: disable enable uc-dev on d2 since backends match
1924 we cannot enable two streams on two different devices if they
1925 share the same backend. e.g. if offload is on speaker device using
1926 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1927 using the same backend, offload must also be switched to voice-handset.
1928
1929case 5
1930 uc->dev d1 (a1) B1
1931 new_uc->dev d1 (a1), d2 (a2) B1
1932
1933 resolution: disable enable uc-dev on d2 since backends match
1934 we cannot enable two streams on two different devices if they
1935 share the same backend.
1936
1937case 6
1938 uc->dev d1 (a1) B1
1939 new_uc->dev d2 (a1) B2
1940
1941 resolution: no need to switch
1942
1943case 7
1944 uc->dev d1 (a1), d2 (a2) B1, B2
1945 new_uc->dev d1 (a1) B1
1946
1947 resolution: no need to switch
1948
Zhou Song4ba65882018-07-09 14:48:07 +08001949case 8
1950 uc->dev d1 (a1) B1
1951 new_uc->dev d11 (a1), d2 (a2) B1, B2
1952 resolution: compared to case 1, for this case, d1 and d11 are related
1953 then need to do the same as case 2 to siwtch to new uc
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301954
1955case 9
1956 uc->dev d1 (a1), d2(a2) B1 B2
1957 new_uc->dev d1 (a1), d22 (a2) B1, B2
1958 resolution: disable enable uc-dev on d2 since backends match
1959 we cannot enable two streams on two different devices if they
1960 share the same backend. This is special case for combo use case
1961 with a2dp and sco devices which uses same backend.
1962 e.g. speaker-a2dp and speaker-btsco
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001963*/
1964static snd_device_t derive_playback_snd_device(void * platform,
1965 struct audio_usecase *uc,
1966 struct audio_usecase *new_uc,
1967 snd_device_t new_snd_device)
1968{
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001969 struct listnode a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001970
1971 snd_device_t d1 = uc->out_snd_device;
1972 snd_device_t d2 = new_snd_device;
Sandhya Mutha Naga Venkataa597a962023-02-07 11:35:51 +05301973 int ret = 0;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001974
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001975 list_init(&a1);
1976 list_init(&a2);
1977
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301978 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301979 case TRANSCODE_LOOPBACK_RX :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001980 assign_devices(&a1, &uc->stream.inout->out_config.device_list);
1981 assign_devices(&a2, &new_uc->stream.inout->out_config.device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301982 break;
1983 default :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001984 assign_devices(&a1, &uc->stream.out->device_list);
1985 assign_devices(&a2, &new_uc->stream.out->device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301986 break;
1987 }
1988
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001989 // Treat as a special case when a1 and a2 are not disjoint
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001990 if (!compare_devices(&a1, &a2) &&
1991 compare_devices_for_any_match(&a1 ,&a2)) {
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001992 snd_device_t d3[2];
1993 int num_devices = 0;
Sandhya Mutha Naga Venkataa597a962023-02-07 11:35:51 +05301994 ret = platform_split_snd_device(platform,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001995 list_length(&a1) > 1 ? d1 : d2,
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001996 &num_devices,
1997 d3);
1998 if (ret < 0) {
1999 if (ret != -ENOSYS) {
2000 ALOGW("%s failed to split snd_device %d",
2001 __func__,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002002 list_length(&a1) > 1 ? d1 : d2);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07002003 }
Sandhya Mutha Naga Venkata4c6fc9f2022-10-14 19:38:02 +05302004 ret = d2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07002005 goto end;
2006 }
2007
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07002008 if (platform_check_backends_match(d3[0], d3[1])) {
Sandhya Mutha Naga Venkata4c6fc9f2022-10-14 19:38:02 +05302009 ret = d2;
2010 goto end; // case 5
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07002011 } else {
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05302012 if ((list_length(&a1) > 1) && (list_length(&a2) > 1) &&
Sandhya Mutha Naga Venkata4c6fc9f2022-10-14 19:38:02 +05302013 platform_check_backends_match(d1, d2)) {
2014 ret = d2;
2015 goto end; //case 9
2016 }
2017 if (list_length(&a1) > 1) {
2018 ret = d1;
2019 goto end; //case 7
2020 }
Garmond Leungb9eeba42018-09-18 11:10:41 -07002021 // check if d1 is related to any of d3's
Sandhya Mutha Naga Venkata4c6fc9f2022-10-14 19:38:02 +05302022 if (d1 == d3[0] || d1 == d3[1]) {
2023 ret = d1;
2024 goto end; // case 1
2025 } else {
2026 ret = d3[1];
2027 goto end; // case 8
2028 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07002029 }
2030 } else {
2031 if (platform_check_backends_match(d1, d2)) {
Sandhya Mutha Naga Venkata4c6fc9f2022-10-14 19:38:02 +05302032 ret = d2;
2033 goto end; // case 2, 4
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07002034 } else {
Sandhya Mutha Naga Venkata4c6fc9f2022-10-14 19:38:02 +05302035 ret = d1;
2036 goto end; // case 6, 3
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07002037 }
2038 }
2039
2040end:
Sandhya Mutha Naga Venkata4c6fc9f2022-10-14 19:38:02 +05302041 clear_devices(&a1);
2042 clear_devices(&a2);
2043 return ret; // return whatever was calculated before.
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07002044}
2045
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002046static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05302047 struct audio_usecase *uc_info,
2048 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002049{
2050 struct listnode *node;
2051 struct audio_usecase *usecase;
2052 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05302053 snd_device_t uc_derive_snd_device;
2054 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08002055 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
2056 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08002057 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302058 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002059 /*
2060 * This function is to make sure that all the usecases that are active on
2061 * the hardware codec backend are always routed to any one device that is
2062 * handled by the hardware codec.
2063 * For example, if low-latency and deep-buffer usecases are currently active
2064 * on speaker and out_set_parameters(headset) is received on low-latency
2065 * output, then we have to make sure deep-buffer is also switched to headset,
2066 * because of the limitation that both the devices cannot be enabled
2067 * at the same time as they share the same backend.
2068 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07002069 /*
2070 * This call is to check if we need to force routing for a particular stream
2071 * If there is a backend configuration change for the device when a
2072 * new stream starts, then ADM needs to be closed and re-opened with the new
2073 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08002074 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07002075 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08002076 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
2077 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302078 /* For a2dp device reconfigure all active sessions
2079 * with new AFE encoder format based on a2dp state
2080 */
2081 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05302082 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device ||
2083 SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP == snd_device) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302084 audio_extn_a2dp_is_force_device_switch()) {
2085 force_routing = true;
2086 force_restart_session = true;
2087 }
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08002088
2089 /*
2090 * Island cfg and power mode config needs to set before AFE port start.
2091 * Set force routing in case of voice device was enable before.
2092 */
2093 if (uc_info->type == VOICE_CALL &&
2094 voice_extn_is_voice_power_mode_supported() &&
Kunlei Zhang67cc7072020-12-18 17:16:49 +08002095 is_supported_conc_usecase_for_power_mode_call(adev) &&
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08002096 platform_check_and_update_island_power_status(adev->platform,
2097 uc_info,
2098 snd_device)) {
2099 force_routing = true;
2100 ALOGD("%s:becf: force routing %d for power mode supported device",
2101 __func__, force_routing);
2102 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302103 ALOGD("%s:becf: force routing %d", __func__, force_routing);
2104
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002105 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002106 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002107 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002108 for (i = 0; i < AUDIO_USECASE_MAX; i++)
2109 switch_device[i] = false;
2110
2111 list_for_each(node, &adev->usecase_list) {
2112 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08002113
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05302114 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
2115 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302116 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05302117 platform_get_snd_device_name(usecase->out_snd_device),
2118 platform_check_backends_match(snd_device, usecase->out_snd_device));
Rahul Sharma99770982019-03-06 17:05:26 +05302119 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
2120 (usecase->type != PCM_PASSTHROUGH)) {
Ashish Jain6a65b352017-03-21 17:24:40 +05302121 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
2122 usecase, uc_info, snd_device);
2123 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002124 (is_codec_backend_out_device_type(&usecase->device_list) ||
2125 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
2126 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_DEVICE) ||
2127 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_HEADSET) ||
2128 is_a2dp_out_device_type(&usecase->device_list) ||
2129 is_sco_out_device_type(&usecase->device_list)) &&
Ashish Jain6a65b352017-03-21 17:24:40 +05302130 ((force_restart_session) ||
2131 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05302132 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
2133 __func__, use_case_table[usecase->id],
2134 platform_get_snd_device_name(usecase->out_snd_device));
2135 disable_audio_route(adev, usecase);
2136 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05302137 /* Enable existing usecase on derived playback device */
2138 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05302139 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05302140 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002141 }
2142 }
2143
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302144 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
2145 num_uc_to_switch);
2146
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002147 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07002148 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002149
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05302150 /* Make sure the previous devices to be disabled first and then enable the
2151 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002152 list_for_each(node, &adev->usecase_list) {
2153 usecase = node_to_item(node, struct audio_usecase, list);
2154 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08002155 /* Check if output sound device to be switched can be split and if any
2156 of the split devices match with derived sound device */
2157 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
2158 &num_devices, split_snd_devices) == 0) {
2159 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
2160 for (i = 0; i < num_devices; i++) {
2161 /* Disable devices that do not match with derived sound device */
2162 if (split_snd_devices[i] != derive_snd_device[usecase->id])
2163 disable_snd_device(adev, split_snd_devices[i]);
2164 }
2165 } else {
2166 disable_snd_device(adev, usecase->out_snd_device);
2167 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002168 }
2169 }
2170
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07002171 list_for_each(node, &adev->usecase_list) {
2172 usecase = node_to_item(node, struct audio_usecase, list);
2173 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08002174 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
2175 &num_devices, split_snd_devices) == 0) {
2176 /* Enable derived sound device only if it does not match with
2177 one of the split sound devices. This is because the matching
2178 sound device was not disabled */
2179 bool should_enable = true;
2180 for (i = 0; i < num_devices; i++) {
2181 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
2182 should_enable = false;
2183 break;
2184 }
2185 }
2186 if (should_enable)
2187 enable_snd_device(adev, derive_snd_device[usecase->id]);
2188 } else {
2189 enable_snd_device(adev, derive_snd_device[usecase->id]);
2190 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07002191 }
2192 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002193
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002194 /* Re-route all the usecases on the shared backend other than the
2195 specified usecase to new snd devices */
2196 list_for_each(node, &adev->usecase_list) {
2197 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05302198 /* Update the out_snd_device only before enabling the audio route */
2199 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05302200 usecase->out_snd_device = derive_snd_device[usecase->id];
Lakshman Chaluvarajuab7e5572020-10-28 19:29:23 +05302201 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
2202 use_case_table[usecase->id],
2203 platform_get_snd_device_name(usecase->out_snd_device));
2204 /* Update voc calibration before enabling Voice/VoIP route */
2205 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL)
2206 status = platform_switch_voice_call_device_post(adev->platform,
2207 usecase->out_snd_device,
2208 platform_get_input_snd_device(
2209 adev->platform, NULL,
2210 &uc_info->device_list,
2211 usecase->type));
2212 enable_audio_route(adev, usecase);
2213 if (usecase->stream.out && usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
2214 out_set_voip_volume(&usecase->stream.out->stream,
2215 usecase->stream.out->volume_l,
2216 usecase->stream.out->volume_r);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05302217 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002218 }
2219 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002220 }
2221}
2222
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302223static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002224 struct audio_usecase *uc_info,
2225 snd_device_t snd_device)
2226{
2227 struct listnode *node;
2228 struct audio_usecase *usecase;
2229 bool switch_device[AUDIO_USECASE_MAX];
2230 int i, num_uc_to_switch = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002231 int backend_check_cond = is_codec_backend_out_device_type(&uc_info->device_list);
kunleiz5cd52b82016-11-07 17:22:52 +08002232 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002233
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302234 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
2235 snd_device);
2236 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05302237
2238 /*
2239 * Make sure out devices is checked against out codec backend device and
2240 * also in devices against in codec backend. Checking out device against in
2241 * codec backend or vice versa causes issues.
2242 */
2243 if (uc_info->type == PCM_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002244 backend_check_cond = is_codec_backend_in_device_type(&uc_info->device_list);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08002245
2246 /*
2247 * Island cfg and power mode config needs to set before AFE port start.
2248 * Set force routing in case of voice device was enable before.
2249 */
2250
2251 if (uc_info->type == VOICE_CALL &&
2252 voice_extn_is_voice_power_mode_supported() &&
Kunlei Zhang67cc7072020-12-18 17:16:49 +08002253 is_supported_conc_usecase_for_power_mode_call(adev) &&
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08002254 platform_check_and_update_island_power_status(adev->platform,
2255 uc_info,
2256 snd_device)) {
2257 force_routing = true;
2258 ALOGD("%s:becf: force routing %d for power mode supported device",
2259 __func__, force_routing);
2260 }
2261
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002262 /*
2263 * This function is to make sure that all the active capture usecases
2264 * are always routed to the same input sound device.
2265 * For example, if audio-record and voice-call usecases are currently
2266 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
2267 * is received for voice call then we have to make sure that audio-record
2268 * usecase is also switched to earpiece i.e. voice-dmic-ef,
2269 * because of the limitation that two devices cannot be enabled
2270 * at the same time if they share the same backend.
2271 */
2272 for (i = 0; i < AUDIO_USECASE_MAX; i++)
2273 switch_device[i] = false;
2274
2275 list_for_each(node, &adev->usecase_list) {
2276 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05302277 /*
2278 * TODO: Enhance below condition to handle BT sco/USB multi recording
2279 */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302280
2281 bool capture_uc_needs_routing = usecase->type != PCM_PLAYBACK && (usecase != uc_info &&
2282 (usecase->in_snd_device != snd_device || force_routing));
2283 bool call_proxy_snd_device = platform_is_call_proxy_snd_device(snd_device) ||
2284 platform_is_call_proxy_snd_device(usecase->in_snd_device);
2285 if (capture_uc_needs_routing && !call_proxy_snd_device &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002286 ((backend_check_cond &&
2287 (is_codec_backend_in_device_type(&usecase->device_list) ||
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08002288 (usecase->type == VOIP_CALL))) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08002289 ((uc_info->type == VOICE_CALL &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002290 is_single_device_type_equal(&usecase->device_list,
2291 AUDIO_DEVICE_IN_VOICE_CALL)) ||
Anver sadhique4fdc6992022-01-21 12:26:28 +05302292 platform_check_all_backends_match(snd_device,\
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002293 usecase->in_snd_device))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07002294 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05302295 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..",
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002296 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07002297 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002298 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002299 switch_device[usecase->id] = true;
2300 num_uc_to_switch++;
2301 }
2302 }
2303
2304 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07002305 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002306
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05302307 /* Make sure the previous devices to be disabled first and then enable the
2308 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002309 list_for_each(node, &adev->usecase_list) {
2310 usecase = node_to_item(node, struct audio_usecase, list);
2311 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002312 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08002313 }
2314 }
2315
2316 list_for_each(node, &adev->usecase_list) {
2317 usecase = node_to_item(node, struct audio_usecase, list);
2318 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002319 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002320 }
2321 }
2322
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002323 /* Re-route all the usecases on the shared backend other than the
2324 specified usecase to new snd devices */
2325 list_for_each(node, &adev->usecase_list) {
2326 usecase = node_to_item(node, struct audio_usecase, list);
2327 /* Update the in_snd_device only before enabling the audio route */
2328 if (switch_device[usecase->id] ) {
2329 usecase->in_snd_device = snd_device;
Lakshman Chaluvarajuab7e5572020-10-28 19:29:23 +05302330 /* Update voc calibration before enabling Voice/VoIP route */
2331 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
2332 snd_device_t voip_snd_device;
2333 voip_snd_device = platform_get_output_snd_device(adev->platform,
2334 usecase->stream.out,
2335 usecase->type);
2336 status = platform_switch_voice_call_device_post(adev->platform,
2337 voip_snd_device,
2338 usecase->in_snd_device);
kunleiz5cd52b82016-11-07 17:22:52 +08002339 }
Lakshman Chaluvarajuab7e5572020-10-28 19:29:23 +05302340 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002341 }
2342 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002343 }
2344}
2345
Mingming Yin3a941d42016-02-17 18:08:05 -08002346static void reset_hdmi_sink_caps(struct stream_out *out) {
2347 int i = 0;
2348
2349 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
2350 out->supported_channel_masks[i] = 0;
2351 }
2352 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
2353 out->supported_formats[i] = 0;
2354 }
2355 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
2356 out->supported_sample_rates[i] = 0;
2357 }
2358}
2359
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002360/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08002361static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002362{
Mingming Yin3a941d42016-02-17 18:08:05 -08002363 int ret = 0, i = 0, j = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002364 int channels = platform_edid_get_max_channels_v2(out->dev->platform,
2365 out->extconn.cs.controller,
2366 out->extconn.cs.stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002367
Mingming Yin3a941d42016-02-17 18:08:05 -08002368 reset_hdmi_sink_caps(out);
2369
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002370 /* Cache ext disp type */
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002371 ret = platform_get_ext_disp_type_v2(adev->platform,
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002372 out->extconn.cs.controller,
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002373 out->extconn.cs.stream);
2374 if(ret < 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002375 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07002376 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002377 }
2378
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002379 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002380 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08002381 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002382 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08002383 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
2384 case 6:
2385 ALOGV("%s: HDMI supports 5.1 channels", __func__);
2386 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
2387 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
2388 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
2389 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
2390 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002391 break;
2392 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08002393 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002394 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002395 break;
2396 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002397
2398 // check channel format caps
2399 i = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002400 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_AC3,
2401 out->extconn.cs.controller,
2402 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002403 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
2404 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
2405 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
2406 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
2407 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
2408 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
2409 }
2410
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002411 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD,
2412 out->extconn.cs.controller,
2413 out->extconn.cs.stream)) {
Ben Romberger1aaaf862017-04-06 17:49:46 -07002414 ALOGV(":%s HDMI supports TRUE HD format", __func__);
2415 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
2416 }
2417
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002418 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS,
2419 out->extconn.cs.controller,
2420 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002421 ALOGV(":%s HDMI supports DTS format", __func__);
2422 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
2423 }
2424
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002425 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS_HD,
2426 out->extconn.cs.controller,
2427 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002428 ALOGV(":%s HDMI supports DTS HD format", __func__);
2429 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
2430 }
2431
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002432 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_IEC61937,
2433 out->extconn.cs.controller,
2434 out->extconn.cs.stream)) {
Naresh Tanniru928f0862017-04-07 16:44:23 -07002435 ALOGV(":%s HDMI supports IEC61937 format", __func__);
2436 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
2437 }
2438
Mingming Yin3a941d42016-02-17 18:08:05 -08002439
2440 // check sample rate caps
2441 i = 0;
2442 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002443 if (platform_is_edid_supported_sample_rate_v2(out->dev->platform, out_hdmi_sample_rates[j],
2444 out->extconn.cs.controller,
2445 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002446 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
2447 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
2448 }
2449 }
2450
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002451 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002452}
2453
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002454static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
2455 uint32_t *supported_sample_rates __unused,
2456 uint32_t max_rates __unused)
2457{
2458 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
2459 supported_sample_rates,
2460 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05302461 ssize_t i = 0;
2462
2463 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002464 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
2465 supported_sample_rates[i]);
2466 }
2467 return count;
2468}
2469
2470static inline int read_usb_sup_channel_masks(bool is_playback,
2471 audio_channel_mask_t *supported_channel_masks,
2472 uint32_t max_masks)
2473{
2474 int channels = audio_extn_usb_get_max_channels(is_playback);
2475 int channel_count;
2476 uint32_t num_masks = 0;
2477 if (channels > MAX_HIFI_CHANNEL_COUNT)
2478 channels = MAX_HIFI_CHANNEL_COUNT;
2479
2480 if (is_playback) {
Eric Laurent68a87112019-05-01 18:07:29 -07002481 // start from 2 channels as framework currently doesn't support mono.
2482 if (channels >= FCC_2) {
2483 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(FCC_2);
2484 }
2485 for (channel_count = FCC_2;
2486 channel_count <= channels && num_masks < max_masks;
2487 ++channel_count) {
2488 supported_channel_masks[num_masks++] =
2489 audio_channel_mask_for_index_assignment_from_count(channel_count);
2490 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002491 } else {
vincenttewf51c94e2019-05-07 10:28:53 +08002492 // For capture we report all supported channel masks from 1 channel up.
2493 channel_count = MIN_CHANNEL_COUNT;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002494 // audio_channel_in_mask_from_count() does the right conversion to either positional or
2495 // indexed mask
Eric Laurent68a87112019-05-01 18:07:29 -07002496 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
2497 audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
2498 if (channel_count <= FCC_2) {
2499 mask = audio_channel_in_mask_from_count(channel_count);
2500 supported_channel_masks[num_masks++] = mask;
2501 }
2502 const audio_channel_mask_t index_mask =
2503 audio_channel_mask_for_index_assignment_from_count(channel_count);
2504 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
2505 supported_channel_masks[num_masks++] = index_mask;
2506 }
2507 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002508 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302509
vincenttewf51c94e2019-05-07 10:28:53 +08002510 for (size_t i = 0; i < num_masks; ++i) {
2511 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
2512 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302513 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002514 return num_masks;
2515}
2516
2517static inline int read_usb_sup_formats(bool is_playback __unused,
2518 audio_format_t *supported_formats,
2519 uint32_t max_formats __unused)
2520{
2521 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
2522 switch (bitwidth) {
2523 case 24:
2524 // XXX : usb.c returns 24 for s24 and s24_le?
2525 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
2526 break;
2527 case 32:
2528 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
2529 break;
2530 case 16:
2531 default :
2532 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
2533 break;
2534 }
2535 ALOGV("%s: %s supported format %d", __func__,
2536 is_playback ? "P" : "C", bitwidth);
2537 return 1;
2538}
2539
2540static inline int read_usb_sup_params_and_compare(bool is_playback,
2541 audio_format_t *format,
2542 audio_format_t *supported_formats,
2543 uint32_t max_formats,
2544 audio_channel_mask_t *mask,
2545 audio_channel_mask_t *supported_channel_masks,
2546 uint32_t max_masks,
2547 uint32_t *rate,
2548 uint32_t *supported_sample_rates,
2549 uint32_t max_rates) {
2550 int ret = 0;
2551 int num_formats;
2552 int num_masks;
2553 int num_rates;
2554 int i;
2555
2556 num_formats = read_usb_sup_formats(is_playback, supported_formats,
2557 max_formats);
2558 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
2559 max_masks);
2560
2561 num_rates = read_usb_sup_sample_rates(is_playback,
2562 supported_sample_rates, max_rates);
2563
2564#define LUT(table, len, what, dflt) \
2565 for (i=0; i<len && (table[i] != what); i++); \
2566 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
2567
2568 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
2569 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
2570 LUT(supported_sample_rates, num_rates, *rate, 0);
2571
2572#undef LUT
2573 return ret < 0 ? -EINVAL : 0; // HACK TBD
2574}
2575
Alexy Josephb1379942016-01-29 15:49:38 -08002576audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002577 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002578{
2579 struct audio_usecase *usecase;
2580 struct listnode *node;
2581
2582 list_for_each(node, &adev->usecase_list) {
2583 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002584 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002585 ALOGV("%s: usecase id %d", __func__, usecase->id);
2586 return usecase->id;
2587 }
2588 }
2589 return USECASE_INVALID;
2590}
2591
Alexy Josephb1379942016-01-29 15:49:38 -08002592struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002593 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002594{
2595 struct audio_usecase *usecase;
2596 struct listnode *node;
2597
2598 list_for_each(node, &adev->usecase_list) {
2599 usecase = node_to_item(node, struct audio_usecase, list);
2600 if (usecase->id == uc_id)
2601 return usecase;
2602 }
2603 return NULL;
2604}
2605
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302606/*
2607 * is a true native playback active
2608 */
2609bool audio_is_true_native_stream_active(struct audio_device *adev)
2610{
2611 bool active = false;
2612 int i = 0;
2613 struct listnode *node;
2614
2615 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
2616 ALOGV("%s:napb: not in true mode or non hdphones device",
2617 __func__);
2618 active = false;
2619 goto exit;
2620 }
2621
2622 list_for_each(node, &adev->usecase_list) {
2623 struct audio_usecase *uc;
2624 uc = node_to_item(node, struct audio_usecase, list);
2625 struct stream_out *curr_out =
2626 (struct stream_out*) uc->stream.out;
2627
2628 if (curr_out && PCM_PLAYBACK == uc->type) {
2629 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
2630 "(%d) device %s", __func__, i++, use_case_table[uc->id],
2631 uc->id, curr_out->sample_rate,
2632 curr_out->bit_width,
2633 platform_get_snd_device_name(uc->out_snd_device));
2634
2635 if (is_offload_usecase(uc->id) &&
2636 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
2637 active = true;
2638 ALOGD("%s:napb:native stream detected", __func__);
2639 }
2640 }
2641 }
2642exit:
2643 return active;
2644}
2645
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002646uint32_t adev_get_dsp_bit_width_enforce_mode()
2647{
2648 if (adev == NULL) {
2649 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
2650 return 0;
2651 }
2652 return adev->dsp_bit_width_enforce_mode;
2653}
2654
2655static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
2656{
2657 char value[PROPERTY_VALUE_MAX];
2658 int trial;
2659 uint32_t dsp_bit_width_enforce_mode = 0;
2660
2661 if (!mixer) {
2662 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
2663 __func__);
2664 return 0;
2665 }
2666
2667 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
2668 value, NULL) > 0) {
2669 trial = atoi(value);
2670 switch (trial) {
2671 case 16:
2672 dsp_bit_width_enforce_mode = 16;
2673 break;
2674 case 24:
2675 dsp_bit_width_enforce_mode = 24;
2676 break;
2677 case 32:
2678 dsp_bit_width_enforce_mode = 32;
2679 break;
2680 default:
2681 dsp_bit_width_enforce_mode = 0;
2682 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
2683 break;
2684 }
2685 }
2686
2687 return dsp_bit_width_enforce_mode;
2688}
2689
2690static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
2691 uint32_t enforce_mode,
2692 bool enable)
2693{
2694 struct mixer_ctl *ctl = NULL;
2695 const char *mixer_ctl_name = "ASM Bit Width";
2696 uint32_t asm_bit_width_mode = 0;
2697
2698 if (enforce_mode == 0) {
2699 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
2700 return;
2701 }
2702
2703 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
2704 if (!ctl) {
2705 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2706 __func__, mixer_ctl_name);
2707 return;
2708 }
2709
2710 if (enable)
2711 asm_bit_width_mode = enforce_mode;
2712 else
2713 asm_bit_width_mode = 0;
2714
2715 ALOGV("%s DSP bit width feature status is %d width=%d",
2716 __func__, enable, asm_bit_width_mode);
2717 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2718 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2719 asm_bit_width_mode);
2720
2721 return;
2722}
2723
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302724/*
2725 * if native DSD playback active
2726 */
2727bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2728{
2729 bool active = false;
2730 struct listnode *node = NULL;
2731 struct audio_usecase *uc = NULL;
2732 struct stream_out *curr_out = NULL;
2733
2734 list_for_each(node, &adev->usecase_list) {
2735 uc = node_to_item(node, struct audio_usecase, list);
2736 curr_out = (struct stream_out*) uc->stream.out;
2737
2738 if (curr_out && PCM_PLAYBACK == uc->type &&
2739 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2740 active = true;
2741 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302742 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302743 }
2744 }
2745 return active;
2746}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302747
2748static bool force_device_switch(struct audio_usecase *usecase)
2749{
2750 bool ret = false;
2751 bool is_it_true_mode = false;
2752
Zhou Song30f2c3e2018-02-08 14:02:15 +08002753 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302754 usecase->type == TRANSCODE_LOOPBACK_RX ||
2755 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002756 return false;
2757 }
2758
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002759 if(usecase->stream.out == NULL) {
2760 ALOGE("%s: stream.out is NULL", __func__);
2761 return false;
2762 }
2763
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302764 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002765 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002766 (compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADSET) ||
2767 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADPHONE))) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302768 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2769 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2770 (!is_it_true_mode && adev->native_playback_enabled)){
2771 ret = true;
2772 ALOGD("napb: time to toggle native mode");
2773 }
2774 }
2775
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302776 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302777 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2778 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002779 if(is_a2dp_out_device_type(&usecase->stream.out->device_list) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302780 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302781 ALOGD("Force a2dp device switch to update new encoder config");
2782 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002783 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302784
Florian Pfister1a84f312018-07-19 14:38:18 +02002785 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302786 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2787 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002788 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302789 return ret;
2790}
2791
Aalique Grahame22e49102018-12-18 14:23:57 -08002792static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2793{
2794 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2795}
2796
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302797bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2798{
2799 bool ret=false;
2800 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
Zhou Song5657f492019-08-07 11:30:39 +08002801 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
2802 out_snd_device == SND_DEVICE_OUT_BT_SCO_SWB) ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302803 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2804 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
Zhou Song5657f492019-08-07 11:30:39 +08002805 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302806 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
Mingshu Pang16093502020-04-20 11:21:16 +08002807 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC ||
2808 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC)
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302809 ret = true;
2810
2811 return ret;
2812}
2813
2814bool is_a2dp_device(snd_device_t out_snd_device)
2815{
2816 bool ret=false;
2817 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2818 ret = true;
2819
2820 return ret;
2821}
2822
2823bool is_bt_soc_on(struct audio_device *adev)
2824{
2825 struct mixer_ctl *ctl;
2826 char *mixer_ctl_name = "BT SOC status";
2827 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2828 bool bt_soc_status = true;
2829 if (!ctl) {
2830 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2831 __func__, mixer_ctl_name);
2832 /*This is to ensure we dont break targets which dont have the kernel change*/
2833 return true;
2834 }
2835 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2836 ALOGD("BT SOC status: %d",bt_soc_status);
2837 return bt_soc_status;
2838}
2839
Zhou Song331c8e52019-08-26 14:16:12 +08002840static int configure_btsco_sample_rate(snd_device_t snd_device)
2841{
2842 struct mixer_ctl *ctl = NULL;
2843 struct mixer_ctl *ctl_sr_rx = NULL, *ctl_sr_tx = NULL, *ctl_sr = NULL;
2844 char *rate_str = NULL;
2845 bool is_rx_dev = true;
2846
2847 if (is_btsco_device(snd_device, snd_device)) {
2848 ctl_sr_tx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate TX");
2849 ctl_sr_rx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate RX");
2850 if (!ctl_sr_tx || !ctl_sr_rx) {
2851 ctl_sr = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate");
2852 if (!ctl_sr)
2853 return -ENOSYS;
2854 }
2855
2856 switch (snd_device) {
2857 case SND_DEVICE_OUT_BT_SCO:
2858 rate_str = "KHZ_8";
2859 break;
2860 case SND_DEVICE_IN_BT_SCO_MIC_NREC:
2861 case SND_DEVICE_IN_BT_SCO_MIC:
2862 rate_str = "KHZ_8";
2863 is_rx_dev = false;
2864 break;
2865 case SND_DEVICE_OUT_BT_SCO_WB:
2866 rate_str = "KHZ_16";
2867 break;
2868 case SND_DEVICE_IN_BT_SCO_MIC_WB_NREC:
2869 case SND_DEVICE_IN_BT_SCO_MIC_WB:
2870 rate_str = "KHZ_16";
2871 is_rx_dev = false;
2872 break;
2873 default:
2874 return 0;
2875 }
2876
2877 ctl = (ctl_sr == NULL) ? (is_rx_dev ? ctl_sr_rx : ctl_sr_tx) : ctl_sr;
2878 if (mixer_ctl_set_enum_by_string(ctl, rate_str) != 0)
2879 return -ENOSYS;
2880 }
2881 return 0;
2882}
2883
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302884int out_standby_l(struct audio_stream *stream);
2885
Eric Laurent637e2d42018-11-15 12:24:31 -08002886struct stream_in *adev_get_active_input(const struct audio_device *adev)
2887{
2888 struct listnode *node;
2889 struct stream_in *last_active_in = NULL;
2890
2891 /* Get last added active input.
2892 * TODO: We may use a priority mechanism to pick highest priority active source */
2893 list_for_each(node, &adev->usecase_list)
2894 {
2895 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2896 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL)
2897 last_active_in = usecase->stream.in;
2898 }
2899
2900 return last_active_in;
2901}
2902
2903struct stream_in *get_voice_communication_input(const struct audio_device *adev)
2904{
2905 struct listnode *node;
2906
2907 /* First check active inputs with voice communication source and then
2908 * any input if audio mode is in communication */
2909 list_for_each(node, &adev->usecase_list)
2910 {
2911 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2912 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
2913 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
2914 return usecase->stream.in;
2915 }
2916 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION)
2917 return adev_get_active_input(adev);
2918
2919 return NULL;
2920}
2921
Carter Hsu2e429db2019-05-14 18:50:52 +08002922/*
2923 * Aligned with policy.h
2924 */
2925static inline int source_priority(int inputSource)
2926{
2927 switch (inputSource) {
2928 case AUDIO_SOURCE_VOICE_COMMUNICATION:
2929 return 9;
2930 case AUDIO_SOURCE_CAMCORDER:
2931 return 8;
2932 case AUDIO_SOURCE_VOICE_PERFORMANCE:
2933 return 7;
2934 case AUDIO_SOURCE_UNPROCESSED:
2935 return 6;
2936 case AUDIO_SOURCE_MIC:
2937 return 5;
2938 case AUDIO_SOURCE_ECHO_REFERENCE:
2939 return 4;
2940 case AUDIO_SOURCE_FM_TUNER:
2941 return 3;
2942 case AUDIO_SOURCE_VOICE_RECOGNITION:
2943 return 2;
2944 case AUDIO_SOURCE_HOTWORD:
2945 return 1;
2946 default:
2947 break;
2948 }
2949 return 0;
2950}
2951
2952static struct stream_in *get_priority_input(struct audio_device *adev)
2953{
2954 struct listnode *node;
2955 struct audio_usecase *usecase;
2956 int last_priority = 0, priority;
2957 struct stream_in *priority_in = NULL;
2958 struct stream_in *in;
2959
2960 list_for_each(node, &adev->usecase_list) {
2961 usecase = node_to_item(node, struct audio_usecase, list);
2962 if (usecase->type == PCM_CAPTURE) {
2963 in = usecase->stream.in;
2964 if (!in)
2965 continue;
Krishna Kishor Jha0b7175d2022-07-28 22:33:46 +05302966
2967 if (USECASE_AUDIO_RECORD_FM_VIRTUAL == usecase->id)
2968 continue;
Krishna Kishor Jhaaf83fd82022-11-15 17:54:07 +05302969#ifdef SKIP_INPUT_SOURCE_PRIORITY
2970 // temporary fix to resolve issue when accessing Google Assistant while FM is active.
2971 if (USECASE_AUDIO_RECORD_ECHO_REF_EXT == usecase->id) {
2972 continue;
2973 }
2974#endif
Carter Hsu2e429db2019-05-14 18:50:52 +08002975 priority = source_priority(in->source);
2976
2977 if (priority > last_priority) {
2978 last_priority = priority;
2979 priority_in = in;
2980 }
2981 }
2982 }
2983 return priority_in;
2984}
2985
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002986int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002987{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002988 snd_device_t out_snd_device = SND_DEVICE_NONE;
2989 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002990 struct audio_usecase *usecase = NULL;
2991 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002992 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002993 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302994 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002995 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002996 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002997
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302998 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2999
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003000 usecase = get_usecase_from_list(adev, uc_id);
3001 if (usecase == NULL) {
3002 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
3003 return -EINVAL;
3004 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003005
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003006 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08003007 (usecase->type == VOIP_CALL) ||
Derek Chena30a5f42019-12-03 11:17:09 -05003008 (usecase->type == PCM_HFP_CALL)||
Fei Tongaffdf732020-02-20 20:39:05 +08003009 (usecase->type == ICC_CALL) ||
3010 (usecase->type == SYNTH_LOOPBACK)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05303011 if(usecase->stream.out == NULL) {
3012 ALOGE("%s: stream.out is NULL", __func__);
3013 return -EINVAL;
3014 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003015 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS)) {
Guodong Hu267bdf82019-08-12 19:22:32 +08003016 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev,
3017 uc_id);
3018 in_snd_device = audio_extn_auto_hal_get_input_snd_device(adev,
3019 uc_id);
3020 } else {
3021 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05303022 usecase->stream.out, usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08003023 in_snd_device = platform_get_input_snd_device(adev->platform,
3024 NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05303025 &usecase->stream.out->device_list,
3026 usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08003027 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003028 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05303029 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05303030 if (usecase->stream.inout == NULL) {
3031 ALOGE("%s: stream.inout is NULL", __func__);
3032 return -EINVAL;
3033 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003034 assign_devices(&stream_out.device_list, &usecase->stream.inout->out_config.device_list);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05303035 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
3036 stream_out.format = usecase->stream.inout->out_config.format;
3037 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
Jaideep Sharma477917f2020-03-13 18:13:33 +05303038 out_snd_device = platform_get_output_snd_device(adev->platform, &stream_out, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003039 assign_devices(&usecase->device_list,
3040 &usecase->stream.inout->out_config.device_list);
Zhenlin Lian4f947842022-05-14 15:50:52 +05303041 clear_devices(&stream_out.device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05303042 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
3043 if (usecase->stream.inout == NULL) {
3044 ALOGE("%s: stream.inout is NULL", __func__);
3045 return -EINVAL;
3046 }
Manisha Agarwal03297972020-04-17 15:36:55 +05303047 struct listnode out_devices;
3048 list_init(&out_devices);
3049 in_snd_device = platform_get_input_snd_device(adev->platform, NULL,
3050 &out_devices, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003051 assign_devices(&usecase->device_list,
3052 &usecase->stream.inout->in_config.device_list);
Zhenlin Lian4f947842022-05-14 15:50:52 +05303053 clear_devices(&out_devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003054 } else {
3055 /*
3056 * If the voice call is active, use the sound devices of voice call usecase
3057 * so that it would not result any device switch. All the usecases will
3058 * be switched to new device when select_devices() is called for voice call
3059 * usecase. This is to avoid switching devices for voice call when
3060 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07003061 * choose voice call device only if the use case device is
3062 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003063 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08003064 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003065 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08003066 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003067 if ((vc_usecase) && ((is_codec_backend_out_device_type(&vc_usecase->device_list) &&
3068 is_codec_backend_out_device_type(&usecase->device_list)) ||
3069 (is_codec_backend_out_device_type(&vc_usecase->device_list) &&
3070 is_codec_backend_in_device_type(&usecase->device_list)) ||
3071 is_single_device_type_equal(&vc_usecase->device_list,
3072 AUDIO_DEVICE_OUT_HEARING_AID) ||
3073 is_single_device_type_equal(&usecase->device_list,
Robert Lee8a6aaf32019-09-20 16:40:19 +08003074 AUDIO_DEVICE_IN_VOICE_CALL) ||
3075 (is_single_device_type_equal(&usecase->device_list,
Gautam Manam8fa06162021-09-24 10:41:29 +05303076 AUDIO_DEVICE_IN_BUILTIN_MIC) &&
3077 is_single_device_type_equal(&vc_usecase->device_list,
3078 AUDIO_DEVICE_OUT_USB_HEADSET)) ||
3079 (is_single_device_type_equal(&usecase->device_list,
Robert Lee8a6aaf32019-09-20 16:40:19 +08003080 AUDIO_DEVICE_IN_USB_HEADSET) &&
3081 is_single_device_type_equal(&vc_usecase->device_list,
Kamalakar Yalasiri5edba852021-01-28 14:52:38 +05303082 AUDIO_DEVICE_OUT_USB_HEADSET))||
Gautam Manamf4002142021-09-13 22:05:56 +05303083 (is_single_device_type_equal(&usecase->device_list,
3084 AUDIO_DEVICE_IN_USB_HEADSET) &&
3085 is_codec_backend_out_device_type(&vc_usecase->device_list)) ||
Kamalakar Yalasiri5edba852021-01-28 14:52:38 +05303086 (is_single_device_type_equal(&usecase->device_list,
3087 AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) &&
3088 is_codec_backend_out_device_type(&vc_usecase->device_list)))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003089 in_snd_device = vc_usecase->in_snd_device;
3090 out_snd_device = vc_usecase->out_snd_device;
3091 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003092 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08003093 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08003094 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08003095 if ((voip_usecase != NULL) &&
3096 (usecase->type == PCM_PLAYBACK) &&
3097 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08003098 out_snd_device_backend_match = platform_check_backends_match(
3099 voip_usecase->out_snd_device,
3100 platform_get_output_snd_device(
3101 adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05303102 usecase->stream.out, usecase->type));
yidongh02ef86f2017-04-21 15:36:04 +08003103 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003104 if ((voip_usecase) && (is_codec_backend_out_device_type(&voip_usecase->device_list) &&
3105 (is_codec_backend_out_device_type(&usecase->device_list) ||
3106 is_codec_backend_in_device_type(&usecase->device_list)) &&
yidongh02ef86f2017-04-21 15:36:04 +08003107 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07003108 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003109 in_snd_device = voip_usecase->in_snd_device;
3110 out_snd_device = voip_usecase->out_snd_device;
3111 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08003112 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08003113 hfp_ucid = audio_extn_hfp_get_usecase();
3114 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003115 if ((hfp_usecase) && is_codec_backend_out_device_type(&hfp_usecase->device_list)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08003116 in_snd_device = hfp_usecase->in_snd_device;
3117 out_snd_device = hfp_usecase->out_snd_device;
3118 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003119 }
3120 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05303121 if (usecase->stream.out == NULL) {
3122 ALOGE("%s: stream.out is NULL", __func__);
3123 return -EINVAL;
3124 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003125 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003126 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003127 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003128 struct stream_out *voip_out = adev->primary_output;
3129 struct stream_in *voip_in = get_voice_communication_input(adev);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003130 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS))
Guodong Hu267bdf82019-08-12 19:22:32 +08003131 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev, uc_id);
3132 else
3133 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05303134 usecase->stream.out,
3135 usecase->type);
kunleizdcf967a2018-08-07 17:09:11 +08003136 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizdcf967a2018-08-07 17:09:11 +08003137
Eric Laurent637e2d42018-11-15 12:24:31 -08003138 if (voip_usecase)
3139 voip_out = voip_usecase->stream.out;
3140
3141 if (usecase->stream.out == voip_out && voip_in != NULL)
3142 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003143 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003144 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05303145 if (usecase->stream.in == NULL) {
3146 ALOGE("%s: stream.in is NULL", __func__);
3147 return -EINVAL;
3148 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003149 assign_devices(&usecase->device_list, &usecase->stream.in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003150 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003151 if (in_snd_device == SND_DEVICE_NONE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003152 struct listnode out_devices;
Eric Laurent637e2d42018-11-15 12:24:31 -08003153 struct stream_in *voip_in = get_voice_communication_input(adev);
Carter Hsu2e429db2019-05-14 18:50:52 +08003154 struct stream_in *priority_in = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08003155
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003156 list_init(&out_devices);
Eric Laurent637e2d42018-11-15 12:24:31 -08003157 if (voip_in != NULL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003158 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
3159 USECASE_AUDIO_PLAYBACK_VOIP);
3160
Carter Hsu2e429db2019-05-14 18:50:52 +08003161 usecase->stream.in->enable_ec_port = false;
3162
Zhou Song503196b2021-07-23 17:31:05 +08003163 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY ||
3164 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY2) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003165 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_TELEPHONY_TX, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08003166 } else if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003167 assign_devices(&out_devices, &voip_usecase->stream.out->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08003168 } else if (adev->primary_output &&
3169 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003170 assign_devices(&out_devices, &adev->primary_output->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08003171 } else {
3172 /* forcing speaker o/p device to get matching i/p pair
3173 in case o/p is not routed from same primary HAL */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003174 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08003175 }
Carter Hsu2e429db2019-05-14 18:50:52 +08003176 priority_in = voip_in;
3177 } else {
Krishna Kishor Jhaaf83fd82022-11-15 17:54:07 +05303178#ifdef SKIP_INPUT_SOURCE_PRIORITY
3179
3180 // Precondition: Google Assistant has active use-cases: (1)Echo-ref and (2) Audio-record (with Voice-recognition)
3181 // When fm is requested: audio-rec(VR) use-case is selected due to get-priority-input order.
3182 // To avoid situation skipping use-cases: FM and Echo-Ref from the get-priority-input.
3183 if ((uc_id == USECASE_AUDIO_RECORD_FM_VIRTUAL || uc_id == USECASE_AUDIO_RECORD_ECHO_REF_EXT)){
3184 ALOGD("%s: Skipping get_priority_input for use-case-id:%d(%s).", __func__, uc_id, use_case_table[uc_id]);
3185 } else {
3186 /* get the input with the highest priority source*/
3187 priority_in = get_priority_input(adev);
3188 }
3189#else
Carter Hsu2e429db2019-05-14 18:50:52 +08003190 /* get the input with the highest priority source*/
3191 priority_in = get_priority_input(adev);
Krishna Kishor Jhaaf83fd82022-11-15 17:54:07 +05303192#endif
Carter Hsu2e429db2019-05-14 18:50:52 +08003193
Susan Wang727dd6b2021-03-26 11:28:59 -04003194 if (!priority_in ||
3195 audio_extn_auto_hal_overwrite_priority_for_auto(usecase->stream.in))
Carter Hsu2e429db2019-05-14 18:50:52 +08003196 priority_in = usecase->stream.in;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003197 }
Huicheng Liu1404ba12020-09-11 01:03:25 -04003198 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_IN_BUS)){
3199 in_snd_device = audio_extn_auto_hal_get_snd_device_for_car_audio_stream(priority_in->car_audio_stream);
3200 }
3201 else
3202 in_snd_device = platform_get_input_snd_device(adev->platform,
3203 priority_in,
3204 &out_devices,
3205 usecase->type);
Zhenlin Lian4f947842022-05-14 15:50:52 +05303206 clear_devices(&out_devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003207 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003208 }
3209 }
3210
3211 if (out_snd_device == usecase->out_snd_device &&
3212 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05303213
3214 if (!force_device_switch(usecase))
3215 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003216 }
3217
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003218 if (!compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS) &&
Guodong Hu267bdf82019-08-12 19:22:32 +08003219 ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003220 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready()))) {
Guodong Hu267bdf82019-08-12 19:22:32 +08003221 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
3222 return 0;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303223 }
3224
Aalique Grahame22e49102018-12-18 14:23:57 -08003225 if (out_snd_device != SND_DEVICE_NONE &&
3226 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
3227 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
3228 __func__,
3229 use_case_table[uc_id],
3230 adev->last_logged_snd_device[uc_id][0],
3231 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
3232 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
3233 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
3234 -1,
3235 out_snd_device,
3236 platform_get_snd_device_name(out_snd_device),
3237 platform_get_snd_device_acdb_id(out_snd_device));
3238 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
3239 }
3240 if (in_snd_device != SND_DEVICE_NONE &&
3241 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
3242 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
3243 __func__,
3244 use_case_table[uc_id],
3245 adev->last_logged_snd_device[uc_id][1],
3246 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
3247 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
3248 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
3249 -1,
3250 in_snd_device,
3251 platform_get_snd_device_name(in_snd_device),
3252 platform_get_snd_device_acdb_id(in_snd_device));
3253 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
3254 }
3255
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003256
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003257 /*
3258 * Limitation: While in call, to do a device switch we need to disable
3259 * and enable both RX and TX devices though one of them is same as current
3260 * device.
3261 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07003262 if ((usecase->type == VOICE_CALL) &&
3263 (usecase->in_snd_device != SND_DEVICE_NONE) &&
3264 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07003265 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07003266 }
3267
3268 if (((usecase->type == VOICE_CALL) ||
3269 (usecase->type == VOIP_CALL)) &&
3270 (usecase->out_snd_device != SND_DEVICE_NONE)) {
3271 /* Disable sidetone only if voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303272 if (voice_is_call_state_active_in_call(adev) ||
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07003273 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07003274 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003275
3276 /* Disable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303277 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003278 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08003279 }
3280
Aalique Grahame22e49102018-12-18 14:23:57 -08003281 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
3282 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003283 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303284 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08003285 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
3286 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
3287 else
3288 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303289 }
3290
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003291 /* Disable current sound devices */
3292 if (usecase->out_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->out_snd_device);
Gautam Manam274f4752021-09-24 10:58:49 +05303295 if (usecase->id == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
3296 disable_snd_device(adev, SND_DEVICE_OUT_HAPTICS);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003297 }
3298
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003299 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003300 disable_audio_route(adev, usecase);
3301 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003302 }
3303
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08003304 /* Applicable only on the targets that has external modem.
3305 * New device information should be sent to modem before enabling
3306 * the devices to reduce in-call device switch time.
3307 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07003308 if ((usecase->type == VOICE_CALL) &&
3309 (usecase->in_snd_device != SND_DEVICE_NONE) &&
3310 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08003311 status = platform_switch_voice_call_enable_device_config(adev->platform,
3312 out_snd_device,
3313 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07003314 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08003315
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003316 /* Enable new sound devices */
3317 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08003318 check_usecases_codec_backend(adev, usecase, out_snd_device);
Saurav Kumarc1411662020-10-14 10:50:45 +05303319 check_and_configure_headphone(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05303320 if (platform_check_codec_asrc_support(adev->platform))
3321 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003322 enable_snd_device(adev, out_snd_device);
Zhou Songd9bd9302020-08-04 16:34:45 +08003323 /* Enable haptics device for haptic usecase */
3324 if (usecase->id == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
3325 enable_snd_device(adev, SND_DEVICE_OUT_HAPTICS);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003326 }
3327
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07003328 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303329 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003330 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07003331 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003332
Lakshman Chaluvarajuab7e5572020-10-28 19:29:23 +05303333 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL)
Eric Laurentb23d5282013-05-14 15:27:20 -07003334 status = platform_switch_voice_call_device_post(adev->platform,
3335 out_snd_device,
3336 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08003337
sangwoo170731f2013-06-08 15:36:36 +09003338 usecase->in_snd_device = in_snd_device;
3339 usecase->out_snd_device = out_snd_device;
3340
Dhananjay Kumard6d32152016-10-13 16:11:03 +05303341 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
3342 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05303343 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003344 if ((24 == usecase->stream.out->bit_width) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003345 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_SPEAKER)) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003346 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3347 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
3348 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
3349 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
3350 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
3351 /*
3352 * To best utlize DSP, check if the stream sample rate is supported/multiple of
3353 * configured device sample rate, if not update the COPP rate to be equal to the
3354 * device sample rate, else open COPP at stream sample rate
3355 */
3356 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
3357 usecase->stream.out->sample_rate,
3358 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05303359 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
Preetam Singh Ranawat590d0432019-09-30 14:39:47 +05303360 out_snd_device != SND_DEVICE_OUT_HEADPHONES &&
3361 out_snd_device != SND_DEVICE_OUT_HEADPHONES_HIFI_FILTER &&
Ashish Jain4826f6c2017-02-06 13:33:20 +05303362 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003363 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
3364 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +05303365#ifdef PLATFORM_AUTO
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +05303366 if (!(compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS) && ((usecase->stream.out->flags &
3367 (audio_output_flags_t)AUDIO_OUTPUT_FLAG_SYS_NOTIFICATION) || (usecase->stream.out->flags &
3368 (audio_output_flags_t)AUDIO_OUTPUT_FLAG_PHONE)))) {
3369 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3370 }
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +05303371#else
3372 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3373#endif
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003374 }
Weiyin Jiangcdece202019-07-08 16:13:16 +08003375 }
3376 enable_audio_route(adev, usecase);
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003377
Shalini Manjunatha5e610912020-12-29 13:02:25 +05303378 if (uc_id == USECASE_AUDIO_PLAYBACK_VOIP) {
3379 struct stream_in *voip_in = get_voice_communication_input(adev);
3380 struct audio_usecase *voip_in_usecase = NULL;
3381 voip_in_usecase = get_usecase_from_list(adev, USECASE_AUDIO_RECORD_VOIP);
3382 if (voip_in != NULL &&
3383 voip_in_usecase != NULL &&
3384 !(out_snd_device == AUDIO_DEVICE_OUT_SPEAKER ||
3385 out_snd_device == AUDIO_DEVICE_OUT_SPEAKER_SAFE) &&
3386 (voip_in_usecase->in_snd_device ==
3387 platform_get_input_snd_device(adev->platform, voip_in,
3388 &usecase->stream.out->device_list,usecase->type))) {
3389 /*
3390 * if VOIP TX is enabled before VOIP RX, needs to re-route the TX path
3391 * for enabling echo-reference-voip with correct port
3392 */
3393 ALOGD("%s: VOIP TX is enabled before VOIP RX,needs to re-route the TX path",__func__);
3394 disable_audio_route(adev, voip_in_usecase);
3395 disable_snd_device(adev, voip_in_usecase->in_snd_device);
3396 enable_snd_device(adev, voip_in_usecase->in_snd_device);
3397 enable_audio_route(adev, voip_in_usecase);
3398 }
3399 }
Ramjee Singhcdf67af2021-09-29 14:20:27 +05303400 if (voice_extn_compress_voip_is_active(adev)) {
3401 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
3402 USECASE_COMPRESS_VOIP_CALL);
3403 /*
3404 * If only compress voip input is opened voip out will be primary out.
3405 * Need to consider re-routing to select correct i/p pair
3406 */
3407 if ((voip_usecase != NULL) &&
3408 (usecase->type == PCM_PLAYBACK) &&
3409 (usecase->stream.out == voip_usecase->stream.out)) {
3410 in_snd_device = platform_get_input_snd_device(adev->platform,
3411 NULL,
3412 &usecase->stream.out->device_list,
3413 usecase->type);
3414 if (voip_usecase->in_snd_device != in_snd_device ) {
3415 ALOGD("%s:Re routing compress voip tx snd device matching voip rx pair",
3416 __func__);
3417 disable_audio_route(adev, voip_usecase);
3418 disable_snd_device(adev, voip_usecase->in_snd_device);
3419 voip_usecase->in_snd_device = in_snd_device;
3420 voip_usecase->out_snd_device = usecase->out_snd_device;
3421 /* Route all TX usecase to Compress voip BE */
3422 check_usecases_capture_codec_backend(adev, voip_usecase, in_snd_device);
3423 enable_snd_device(adev, in_snd_device);
3424 /* Send Voice related calibration for RX /TX pair */
3425 status = platform_switch_voice_call_device_post(adev->platform,
3426 out_snd_device,
3427 in_snd_device);
3428 enable_audio_route(adev, voip_usecase);
3429 }
3430 }
3431 }
Shalini Manjunatha5e610912020-12-29 13:02:25 +05303432
3433
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08003434 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08003435
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003436 /* If input stream is already running then effect needs to be
3437 applied on the new input device that's being enabled here. */
Eric Laurent637e2d42018-11-15 12:24:31 -08003438 if (in_snd_device != SND_DEVICE_NONE)
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003439 check_and_enable_effect(adev);
3440
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003441 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003442 /* Enable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303443 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003444 voice_check_and_update_aanc_path(adev, out_snd_device, true);
3445
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003446 /* Enable sidetone only if other voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303447 if (voice_is_call_state_active_in_call(adev) ||
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003448 voice_extn_compress_voip_is_started(adev))
3449 voice_set_sidetone(adev, out_snd_device, true);
3450 }
3451
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003452 /* Applicable only on the targets that has external modem.
3453 * Enable device command should be sent to modem only after
3454 * enabling voice call mixer controls
3455 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07003456 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003457 status = platform_switch_voice_call_usecase_route_post(adev->platform,
3458 out_snd_device,
3459 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303460
3461 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003462 struct stream_in *in = adev_get_active_input(adev);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303463 if (usecase->type == VOIP_CALL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003464 if (in != NULL && !in->standby) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303465 if (is_bt_soc_on(adev) == false){
3466 ALOGD("BT SCO MIC disconnected while in connection");
Eric Laurent637e2d42018-11-15 12:24:31 -08003467 if (in->pcm != NULL)
3468 pcm_stop(in->pcm);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303469 }
3470 }
3471 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
3472 && usecase->stream.out->started) {
3473 if (is_bt_soc_on(adev) == false) {
3474 ALOGD("BT SCO/A2DP disconnected while in connection");
3475 out_standby_l(&usecase->stream.out->stream.common);
3476 }
3477 }
3478 } else if ((usecase->stream.out != NULL) &&
3479 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05303480 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
3481 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Weiyin Jiang0d373242019-07-25 13:18:17 +08003482 (usecase->type != PCM_CAPTURE) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303483 usecase->stream.out->started) {
3484 if (is_bt_soc_on(adev) == false) {
3485 ALOGD("BT SCO/A2dp disconnected while in connection");
3486 out_standby_l(&usecase->stream.out->stream.common);
3487 }
3488 }
3489 }
3490
Yung Ti Su70cb8242018-06-22 17:38:47 +08003491 if (usecase->type != PCM_CAPTURE && usecase == voip_usecase) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003492 struct stream_out *voip_out = voip_usecase->stream.out;
3493 audio_extn_utils_send_app_type_gain(adev,
3494 voip_out->app_type_cfg.app_type,
3495 &voip_out->app_type_cfg.gain[0]);
3496 }
3497
Ajender Reddyb940b832021-07-07 11:51:42 +05303498 ALOGD("%s: done",__func__);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303499
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003500 return status;
3501}
3502
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003503static int stop_input_stream(struct stream_in *in)
3504{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303505 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003506 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05303507
3508 if (in == NULL) {
3509 ALOGE("%s: stream_in ptr is NULL", __func__);
3510 return -EINVAL;
3511 }
3512
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003513 struct audio_device *adev = in->dev;
Carter Hsu2e429db2019-05-14 18:50:52 +08003514 struct stream_in *priority_in = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003515
Eric Laurent994a6932013-07-17 11:51:42 -07003516 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003517 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003518 uc_info = get_usecase_from_list(adev, in->usecase);
3519 if (uc_info == NULL) {
3520 ALOGE("%s: Could not find the usecase (%d) in the list",
3521 __func__, in->usecase);
3522 return -EINVAL;
3523 }
Krishna Kishor Jhaaf83fd82022-11-15 17:54:07 +05303524#ifdef SKIP_INPUT_SOURCE_PRIORITY
3525 // Skip (1)fm-virtual-record and (2)echo-reference-external from get-priority-input logic.
3526 // See comment in function select_devices() before call to get_priority_input()
3527 if ((in->usecase == USECASE_AUDIO_RECORD_FM_VIRTUAL || in->usecase == USECASE_AUDIO_RECORD_ECHO_REF_EXT)){
3528 ALOGD("%s: Skipping get_priority_input for use-case-id:%d/%s.", __func__, in->usecase, use_case_table[in->usecase]);
3529 } else {
3530 priority_in = get_priority_input(adev);
3531 }
3532#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003533
Carter Hsu2e429db2019-05-14 18:50:52 +08003534 priority_in = get_priority_input(adev);
3535
Krishna Kishor Jhaaf83fd82022-11-15 17:54:07 +05303536#endif
3537
Derek Chenea197282019-01-07 17:35:01 -08003538 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3539 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003540
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003541 /* Close in-call recording streams */
3542 voice_check_and_stop_incall_rec_usecase(adev, in);
3543
Eric Laurent150dbfe2013-02-27 14:31:02 -08003544 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003545 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003546
3547 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003548 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003549
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003550 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303551 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_PRIMARY);
3552
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003553 list_remove(&uc_info->list);
Zhenlin Lian4f947842022-05-14 15:50:52 +05303554 clear_devices(&uc_info->device_list);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003555 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003556
Carter Hsu2e429db2019-05-14 18:50:52 +08003557 if (priority_in == in) {
3558 priority_in = get_priority_input(adev);
Sujin Panicker110f7942021-08-26 17:01:22 +05303559 if (priority_in) {
3560 if (is_usb_in_device_type(&priority_in->device_list)) {
3561 if (audio_extn_usb_connected(NULL))
3562 select_devices(adev, priority_in->usecase);
3563 } else {
3564 select_devices(adev, priority_in->usecase);
3565 }
3566 }
Carter Hsu2e429db2019-05-14 18:50:52 +08003567 }
3568
Vatsal Buchac09ae062018-11-14 13:25:08 +05303569 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07003570 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003571 return ret;
3572}
3573
3574int start_input_stream(struct stream_in *in)
3575{
3576 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08003577 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003578 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05303579
3580 if (in == NULL) {
3581 ALOGE("%s: stream_in ptr is NULL", __func__);
3582 return -EINVAL;
3583 }
3584
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003585 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07003586 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07003587 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003588
Mingming Yin2664a5b2015-09-03 10:53:11 -07003589 if (get_usecase_from_list(adev, usecase) == NULL)
3590 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303591 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
3592 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003593
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303594 if (CARD_STATUS_OFFLINE == in->card_status||
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05003595 CARD_STATUS_OFFLINE == adev->card_status ||
3596 POWER_POLICY_STATUS_OFFLINE == adev->in_power_policy) {
3597 ALOGW("in->card_status or adev->card_status or adev->input_power offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303598 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303599 goto error_config;
3600 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303601
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003602 if (is_sco_in_device_type(&in->device_list)) {
Lakshman Chaluvaraju87f53aa2021-02-02 15:50:11 +05303603 if (!adev->bt_sco_on || audio_extn_a2dp_source_is_ready()) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303604 ALOGE("%s: SCO profile is not ready, return error", __func__);
3605 ret = -EIO;
3606 goto error_config;
3607 }
3608 }
3609
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003610 /* Check if source matches incall recording usecase criteria */
3611 ret = voice_check_and_set_incall_rec_usecase(adev, in);
3612 if (ret)
3613 goto error_config;
3614 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07003615 ALOGV("%s: usecase(%d)", __func__, in->usecase);
3616
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303617 if (audio_extn_cin_attached_usecase(in))
3618 audio_extn_cin_acquire_usecase(in);
3619
Mingming Yin2664a5b2015-09-03 10:53:11 -07003620 if (get_usecase_from_list(adev, in->usecase) != NULL) {
3621 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
3622 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Weiyin Jiang38c0e612020-09-10 16:10:51 +08003623 ret = -EINVAL;
3624 goto error_config;
Mingming Yin2664a5b2015-09-03 10:53:11 -07003625 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003626
Eric Laurentb23d5282013-05-14 15:27:20 -07003627 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003628 if (in->pcm_device_id < 0) {
3629 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
3630 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08003631 ret = -EINVAL;
3632 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003633 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003634
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003635 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003636
3637 if (!uc_info) {
3638 ret = -ENOMEM;
3639 goto error_config;
3640 }
3641
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003642 uc_info->id = in->usecase;
3643 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003644 uc_info->stream.in = in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003645 list_init(&uc_info->device_list);
3646 assign_devices(&uc_info->device_list, &in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003647 uc_info->in_snd_device = SND_DEVICE_NONE;
3648 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003649
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003650 list_add_tail(&adev->usecase_list, &uc_info->list);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003651 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303652 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3653 adev->perf_lock_opts,
3654 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003655 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003656
Derek Chenea197282019-01-07 17:35:01 -08003657 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3658 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003659
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05303660 android_atomic_acquire_cas(true, false, &(in->capture_stopped));
3661
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303662 if (audio_extn_cin_attached_usecase(in)) {
Manish Dewangan46e07982018-12-13 18:18:59 +05303663 ret = audio_extn_cin_open_input_stream(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303664 if (ret)
3665 goto error_open;
3666 else
3667 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003668 }
3669
Haynes Mathew George16081042017-05-31 17:16:49 -07003670 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003671 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003672 ALOGE("%s: pcm stream not ready", __func__);
3673 goto error_open;
3674 }
3675 ret = pcm_start(in->pcm);
3676 if (ret < 0) {
3677 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3678 goto error_open;
3679 }
3680 } else {
3681 unsigned int flags = PCM_IN | PCM_MONOTONIC;
3682 unsigned int pcm_open_retry_count = 0;
3683
Zhou Song62ea0282020-03-22 19:53:01 +08003684 if ((in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) ||
3685 (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003686 flags |= PCM_MMAP | PCM_NOIRQ;
3687 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
3688 } else if (in->realtime) {
3689 flags |= PCM_MMAP | PCM_NOIRQ;
3690 }
3691
Garmond Leunge2433c32017-09-28 21:51:22 -07003692 if (audio_extn_ffv_get_stream() == in) {
3693 ALOGD("%s: ffv stream, update pcm config", __func__);
3694 audio_extn_ffv_update_pcm_config(&config);
3695 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003696 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3697 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3698
3699 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003700 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07003701 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07003702 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003703 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303704 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303705 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3706 adev->card_status = CARD_STATUS_OFFLINE;
3707 in->card_status = CARD_STATUS_OFFLINE;
3708 ret = -EIO;
3709 goto error_open;
3710 }
3711
Haynes Mathew George16081042017-05-31 17:16:49 -07003712 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3713 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3714 if (in->pcm != NULL) {
3715 pcm_close(in->pcm);
3716 in->pcm = NULL;
3717 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003718 if (pcm_open_retry_count == 0) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003719 ret = -EIO;
3720 goto error_open;
3721 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003722 pcm_open_retry_count--;
Haynes Mathew George16081042017-05-31 17:16:49 -07003723 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3724 continue;
3725 }
3726 break;
3727 }
3728
3729 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003730 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07003731 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003732 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003733 if (ret < 0) {
3734 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3735 pcm_close(in->pcm);
3736 in->pcm = NULL;
3737 goto error_open;
3738 }
Vaibhav Raut5f3bf222023-02-06 17:45:22 +05303739 if (in->flags & (AUDIO_INPUT_FLAG_FAST | AUDIO_INPUT_FLAG_RAW))
Narsinga Rao Chellaa6e1f702021-10-22 13:57:32 +05303740 register_in_stream(in);
Haynes Mathew George16081042017-05-31 17:16:49 -07003741 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003742 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07003743 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003744 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003745 if (ret < 0) {
3746 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003747 pcm_close(in->pcm);
3748 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003749 goto error_open;
3750 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003751 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003752 }
3753
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003754 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07003755 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
3756 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003757
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003758 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303759 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
3760
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303761done_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003762 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303763 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Manisha Agarwal4c2402e2020-10-21 12:02:57 +05303764 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303765 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003766 return ret;
3767
3768error_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003769 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303770 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003771 stop_input_stream(in);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003772
Eric Laurentc8400632013-02-14 19:04:54 -08003773error_config:
Weiyin Jiang38c0e612020-09-10 16:10:51 +08003774 if (audio_extn_cin_attached_usecase(in))
3775 audio_extn_cin_close_input_stream(in);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303776 /*
3777 * sleep 50ms to allow sufficient time for kernel
3778 * drivers to recover incases like SSR.
3779 */
3780 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003781 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303782 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003783 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003784}
3785
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003786void lock_input_stream(struct stream_in *in)
3787{
3788 pthread_mutex_lock(&in->pre_lock);
3789 pthread_mutex_lock(&in->lock);
3790 pthread_mutex_unlock(&in->pre_lock);
3791}
3792
3793void lock_output_stream(struct stream_out *out)
3794{
3795 pthread_mutex_lock(&out->pre_lock);
3796 pthread_mutex_lock(&out->lock);
3797 pthread_mutex_unlock(&out->pre_lock);
3798}
3799
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003800/* must be called with out->lock locked */
3801static int send_offload_cmd_l(struct stream_out* out, int command)
3802{
3803 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
3804
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003805 if (!cmd) {
3806 ALOGE("failed to allocate mem for command 0x%x", command);
3807 return -ENOMEM;
3808 }
3809
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003810 ALOGVV("%s %d", __func__, command);
3811
3812 cmd->cmd = command;
3813 list_add_tail(&out->offload_cmd_list, &cmd->node);
3814 pthread_cond_signal(&out->offload_cond);
3815 return 0;
3816}
3817
Gautam Manam14c198b2020-12-24 14:08:04 +05303818/* must be called with out->lock */
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003819static void stop_compressed_output_l(struct stream_out *out)
3820{
Gautam Manam14c198b2020-12-24 14:08:04 +05303821 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003822 out->offload_state = OFFLOAD_STATE_IDLE;
Gautam Manam14c198b2020-12-24 14:08:04 +05303823 pthread_mutex_unlock(&out->latch_lock);
Weiyin Jiang906db3c2021-03-02 13:17:04 +08003824
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003825 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003826 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003827 if (out->compr != NULL) {
3828 compress_stop(out->compr);
3829 while (out->offload_thread_blocked) {
3830 pthread_cond_wait(&out->cond, &out->lock);
3831 }
3832 }
3833}
3834
Varun Balaraje49253e2017-07-06 19:48:56 +05303835bool is_interactive_usecase(audio_usecase_t uc_id)
3836{
3837 unsigned int i;
3838 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
3839 if (uc_id == interactive_usecases[i])
3840 return true;
3841 }
3842 return false;
3843}
3844
3845static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
3846{
3847 audio_usecase_t ret_uc = USECASE_INVALID;
3848 unsigned int intract_uc_index;
3849 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3850
3851 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
3852 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
3853 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
3854 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
3855 ret_uc = interactive_usecases[intract_uc_index];
3856 break;
3857 }
3858 }
3859
3860 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
3861 return ret_uc;
3862}
3863
3864static void free_interactive_usecase(struct audio_device *adev,
3865 audio_usecase_t uc_id)
3866{
3867 unsigned int interact_uc_index;
3868 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3869
3870 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
3871 if (interactive_usecases[interact_uc_index] == uc_id) {
3872 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
3873 break;
3874 }
3875 }
3876 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
3877}
3878
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003879bool is_offload_usecase(audio_usecase_t uc_id)
3880{
3881 unsigned int i;
3882 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
3883 if (uc_id == offload_usecases[i])
3884 return true;
3885 }
3886 return false;
3887}
3888
Dhananjay Kumarac341582017-02-23 23:42:25 +05303889static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003890{
vivek mehta446c3962015-09-14 10:57:35 -07003891 audio_usecase_t ret_uc = USECASE_INVALID;
3892 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003893 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003894 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05303895 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07003896 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
3897 else
3898 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003899
vivek mehta446c3962015-09-14 10:57:35 -07003900 pthread_mutex_lock(&adev->lock);
3901 if (get_usecase_from_list(adev, ret_uc) != NULL)
3902 ret_uc = USECASE_INVALID;
3903 pthread_mutex_unlock(&adev->lock);
3904
3905 return ret_uc;
3906 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003907
3908 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003909 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3910 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3911 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3912 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003913 break;
3914 }
3915 }
vivek mehta446c3962015-09-14 10:57:35 -07003916
3917 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3918 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003919}
3920
3921static void free_offload_usecase(struct audio_device *adev,
3922 audio_usecase_t uc_id)
3923{
vivek mehta446c3962015-09-14 10:57:35 -07003924 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003925 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003926
3927 if (!adev->multi_offload_enable)
3928 return;
3929
3930 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3931 if (offload_usecases[offload_uc_index] == uc_id) {
3932 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003933 break;
3934 }
3935 }
3936 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3937}
3938
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003939static void *offload_thread_loop(void *context)
3940{
3941 struct stream_out *out = (struct stream_out *) context;
3942 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003943 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003944
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003945 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08003946 set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003947 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3948
3949 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003950 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003951 out->offload_state = OFFLOAD_STATE_IDLE;
3952 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003953 for (;;) {
3954 struct offload_cmd *cmd = NULL;
3955 stream_callback_event_t event;
3956 bool send_callback = false;
3957
3958 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3959 __func__, list_empty(&out->offload_cmd_list),
3960 out->offload_state);
3961 if (list_empty(&out->offload_cmd_list)) {
3962 ALOGV("%s SLEEPING", __func__);
3963 pthread_cond_wait(&out->offload_cond, &out->lock);
3964 ALOGV("%s RUNNING", __func__);
3965 continue;
3966 }
3967
3968 item = list_head(&out->offload_cmd_list);
3969 cmd = node_to_item(item, struct offload_cmd, node);
3970 list_remove(item);
3971
3972 ALOGVV("%s STATE %d CMD %d out->compr %p",
3973 __func__, out->offload_state, cmd->cmd, out->compr);
3974
3975 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3976 free(cmd);
3977 break;
3978 }
3979
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003980 // allow OFFLOAD_CMD_ERROR reporting during standby
3981 // this is needed to handle failures during compress_open
3982 // Note however that on a pause timeout, the stream is closed
3983 // and no offload usecase will be active. Therefore this
3984 // special case is needed for compress_open failures alone
3985 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3986 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003987 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003988 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003989 pthread_cond_signal(&out->cond);
3990 continue;
3991 }
3992 out->offload_thread_blocked = true;
3993 pthread_mutex_unlock(&out->lock);
3994 send_callback = false;
3995 switch(cmd->cmd) {
3996 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003997 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003998 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003999 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004000 send_callback = true;
4001 event = STREAM_CBK_EVENT_WRITE_READY;
4002 break;
4003 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08004004 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05304005 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004006 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05304007 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004008 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05304009 if (ret < 0)
4010 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05304011 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05304012 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08004013 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08004014 else
4015 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08004016 if (-ENETRESET != ret && !(-EINTR == ret &&
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05004017 (CARD_STATUS_OFFLINE == out->card_status ||
4018 POWER_POLICY_STATUS_OFFLINE == adev->out_power_policy))) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05304019 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304020 pthread_mutex_lock(&out->lock);
4021 out->send_new_metadata = 1;
4022 out->send_next_track_params = true;
4023 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05304024 event = STREAM_CBK_EVENT_DRAIN_READY;
4025 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
4026 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304027 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004028 break;
4029 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004030 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08004031 ret = compress_drain(out->compr);
4032 ALOGD("copl(%p):out of compress_drain", out);
4033 // EINTR check avoids drain interruption due to SSR
4034 if (-ENETRESET != ret && !(-EINTR == ret &&
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05004035 (CARD_STATUS_OFFLINE == out->card_status ||
4036 POWER_POLICY_STATUS_OFFLINE == adev->out_power_policy))) {
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08004037 send_callback = true;
4038 event = STREAM_CBK_EVENT_DRAIN_READY;
4039 } else
4040 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004041 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304042 case OFFLOAD_CMD_ERROR:
4043 ALOGD("copl(%p): sending error callback to AF", out);
4044 send_callback = true;
4045 event = STREAM_CBK_EVENT_ERROR;
4046 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004047 default:
4048 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
4049 break;
4050 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004051 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004052 out->offload_thread_blocked = false;
4053 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004054 if (send_callback && out->client_callback) {
4055 ALOGVV("%s: sending client_callback event %d", __func__, event);
4056 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07004057 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004058 free(cmd);
4059 }
4060
4061 pthread_cond_signal(&out->cond);
4062 while (!list_empty(&out->offload_cmd_list)) {
4063 item = list_head(&out->offload_cmd_list);
4064 list_remove(item);
4065 free(node_to_item(item, struct offload_cmd, node));
4066 }
4067 pthread_mutex_unlock(&out->lock);
4068
4069 return NULL;
4070}
4071
4072static int create_offload_callback_thread(struct stream_out *out)
4073{
4074 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
4075 list_init(&out->offload_cmd_list);
4076 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
4077 offload_thread_loop, out);
4078 return 0;
4079}
4080
4081static int destroy_offload_callback_thread(struct stream_out *out)
4082{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004083 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004084 stop_compressed_output_l(out);
4085 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
4086
4087 pthread_mutex_unlock(&out->lock);
4088 pthread_join(out->offload_thread, (void **) NULL);
4089 pthread_cond_destroy(&out->offload_cond);
4090
4091 return 0;
4092}
4093
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004094static int stop_output_stream(struct stream_out *out)
4095{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304096 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004097 struct audio_usecase *uc_info;
4098 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08004099 bool has_voip_usecase =
4100 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004101
Eric Laurent994a6932013-07-17 11:51:42 -07004102 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004103 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004104 uc_info = get_usecase_from_list(adev, out->usecase);
4105 if (uc_info == NULL) {
4106 ALOGE("%s: Could not find the usecase (%d) in the list",
4107 __func__, out->usecase);
4108 return -EINVAL;
4109 }
4110
Zhou Songbaddf9f2020-11-20 13:57:39 +08004111 out->a2dp_muted = false;
4112
Derek Chenea197282019-01-07 17:35:01 -08004113 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
4114 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08004115
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004116 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304117 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004118 if (adev->visualizer_stop_output != NULL)
4119 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004120
4121 audio_extn_dts_remove_state_notifier_node(out->usecase);
4122
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004123 if (adev->offload_effects_stop_output != NULL)
4124 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07004125 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
4126 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4127 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004128 }
Eric Laurentc4aef752013-09-12 17:45:53 -07004129
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004130 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
4131 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07004132 voice_set_device_mute_flag(adev, false);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004133 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07004134
Eric Laurent150dbfe2013-02-27 14:31:02 -08004135 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07004136 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004137
4138 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07004139 disable_snd_device(adev, uc_info->out_snd_device);
Zhou Songd9bd9302020-08-04 16:34:45 +08004140 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
4141 disable_snd_device(adev, SND_DEVICE_OUT_HAPTICS);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004142
Aalique Grahame22e49102018-12-18 14:23:57 -08004143 audio_extn_extspk_update(adev->extspk);
4144
Xiaojun Sang785b5da2017-08-03 15:52:29 +08004145 if (is_offload_usecase(out->usecase)) {
4146 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
4147 adev->dsp_bit_width_enforce_mode,
4148 false);
4149 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004150 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07004151 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
4152 false);
4153
4154 if (ret != 0)
4155 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
4156 /* default service interval was successfully updated,
4157 reopen USB backend with new service interval */
4158 ret = 0;
4159 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08004160
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004161 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304162 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004163 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304164 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004165 ALOGV("Disable passthrough , reset mixer to pcm");
4166 /* NO_PASSTHROUGH */
Meng Wang4c32fb42020-01-16 17:57:11 +08004167#ifdef AUDIO_GKI_ENABLED
4168 /* out->compr_config.codec->reserved[0] is for compr_passthr */
4169 out->compr_config.codec->reserved[0] = 0;
4170#else
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004171 out->compr_config.codec->compr_passthr = 0;
Meng Wang4c32fb42020-01-16 17:57:11 +08004172#endif
Mingming Yin21854652016-04-13 11:54:02 -07004173 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004174 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
4175 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07004176
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304177 /* Must be called after removing the usecase from list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004178 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL))
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05304179 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304180
Manish Dewangan21a850a2017-08-14 12:03:55 +05304181 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07004182 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
4183 if (ret < 0)
4184 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
4185 }
4186
Zhou Song642ec432020-12-23 16:11:10 +08004187 /* trigger voip input to reroute when voip output changes to hearing aid */
Aalique Grahame22e49102018-12-18 14:23:57 -08004188 if (has_voip_usecase ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004189 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08004190 struct listnode *node;
4191 struct audio_usecase *usecase;
4192 list_for_each(node, &adev->usecase_list) {
4193 usecase = node_to_item(node, struct audio_usecase, list);
Zhou Song642ec432020-12-23 16:11:10 +08004194 if (usecase->type == PCM_PLAYBACK || usecase == uc_info ||
4195 (usecase->type == PCM_CAPTURE &&
Revathi Uddarajud9f23d92020-07-27 10:55:06 +05304196 usecase->id != USECASE_AUDIO_RECORD_VOIP &&
Zhou Song642ec432020-12-23 16:11:10 +08004197 usecase->id != USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY))
Aalique Grahame22e49102018-12-18 14:23:57 -08004198 continue;
4199
4200 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
4201 __func__, usecase->id, use_case_table[usecase->id],
4202 out->usecase, use_case_table[out->usecase]);
4203 select_devices(adev, usecase->id);
4204 }
4205 }
4206
Zhenlin Lian4f947842022-05-14 15:50:52 +05304207 clear_devices(&uc_info->device_list);
Garmond Leung5fd0b552018-04-17 11:56:12 -07004208 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07004209 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004210 return ret;
4211}
4212
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004213struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
4214 unsigned int flags, unsigned int pcm_open_retry_count,
4215 struct pcm_config *config)
4216{
4217 struct pcm* pcm = NULL;
4218
4219 while (1) {
4220 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
4221 if (pcm == NULL || !pcm_is_ready(pcm)) {
4222 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
4223 if (pcm != NULL) {
4224 pcm_close(pcm);
4225 pcm = NULL;
4226 }
Weiyin Jiang72197252019-10-09 11:49:32 +08004227 if (pcm_open_retry_count == 0)
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004228 return NULL;
4229
Weiyin Jiang72197252019-10-09 11:49:32 +08004230 pcm_open_retry_count--;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004231 usleep(PROXY_OPEN_WAIT_TIME * 1000);
4232 continue;
4233 }
4234 break;
4235 }
4236
4237 if (pcm_is_ready(pcm)) {
4238 int ret = pcm_prepare(pcm);
4239 if (ret < 0) {
4240 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
4241 pcm_close(pcm);
4242 pcm = NULL;
4243 }
4244 }
4245
4246 return pcm;
4247}
4248
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004249int start_output_stream(struct stream_out *out)
4250{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004251 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004252 struct audio_usecase *uc_info;
4253 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004254 char mixer_ctl_name[128];
4255 struct mixer_ctl *ctl = NULL;
4256 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304257 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004258 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004259
Haynes Mathew George380745d2017-10-04 15:27:45 -07004260 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004261 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
4262 ret = -EINVAL;
4263 goto error_config;
4264 }
4265
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004266 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304267 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004268 get_device_types(&out->device_list), is_haptic_usecase);
4269
4270 bool is_speaker_active = compare_device_type(&out->device_list,
4271 AUDIO_DEVICE_OUT_SPEAKER);
4272 bool is_speaker_safe_active = compare_device_type(&out->device_list,
4273 AUDIO_DEVICE_OUT_SPEAKER_SAFE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304274
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304275 if (CARD_STATUS_OFFLINE == out->card_status ||
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05004276 CARD_STATUS_OFFLINE == adev->card_status ||
4277 POWER_POLICY_STATUS_OFFLINE == adev->out_power_policy) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304278 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05304279 ret = -EIO;
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004280 goto error_fatal;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304281 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05304282
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004283 //Update incall music usecase to reflect correct voice session
4284 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
4285 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
4286 if (ret != 0) {
4287 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
4288 __func__, ret);
4289 goto error_config;
4290 }
4291 }
4292
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004293 if (is_a2dp_out_device_type(&out->device_list)) {
Florian Pfister1a84f312018-07-19 14:38:18 +02004294 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004295 if (is_speaker_active || is_speaker_safe_active) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304296 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304297 } else {
Zhou Songd01e7a22020-09-23 22:49:01 +08004298 if (!is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304299 ALOGE("%s: A2DP profile is not ready, return error", __func__);
4300 ret = -EAGAIN;
4301 goto error_config;
4302 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304303 }
4304 }
4305 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004306 if (is_sco_out_device_type(&out->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304307 if (!adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004308 if (is_speaker_active) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304309 //combo usecase just by pass a2dp
4310 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004311 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304312 } else {
4313 ALOGE("%s: SCO profile is not ready, return error", __func__);
4314 ret = -EAGAIN;
4315 goto error_config;
4316 }
4317 }
4318 }
4319
Eric Laurentb23d5282013-05-14 15:27:20 -07004320 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004321 if (out->pcm_device_id < 0) {
4322 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
4323 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004324 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004325 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004326 }
4327
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004328 if (is_haptic_usecase) {
Meng Wang51d8c2a2020-04-27 15:23:21 +08004329 adev->haptic_pcm_device_id = platform_get_pcm_device_id(
4330 USECASE_AUDIO_PLAYBACK_HAPTICS, PCM_PLAYBACK);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004331 if (adev->haptic_pcm_device_id < 0) {
4332 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
4333 __func__, adev->haptic_pcm_device_id, out->usecase);
4334 ret = -EINVAL;
4335 goto error_config;
4336 }
4337 }
4338
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004339 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004340
4341 if (!uc_info) {
4342 ret = -ENOMEM;
4343 goto error_config;
4344 }
4345
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004346 uc_info->id = out->usecase;
4347 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004348 uc_info->stream.out = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004349 list_init(&uc_info->device_list);
4350 assign_devices(&uc_info->device_list, &out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004351 uc_info->in_snd_device = SND_DEVICE_NONE;
4352 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07004353
4354 /* This must be called before adding this usecase to the list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004355 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07004356 audio_extn_usb_check_and_set_svc_int(uc_info, true);
4357 /* USB backend is not reopened immediately.
4358 This is eventually done as part of select_devices */
4359 }
4360
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004361 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004362
Wei Wangf7ca6c92017-11-21 14:51:20 -08004363 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304364 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4365 adev->perf_lock_opts,
4366 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304367
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004368 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05304369 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304370 if (audio_extn_passthru_is_enabled() &&
4371 audio_extn_passthru_is_passthrough_stream(out)) {
4372 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304373 }
4374 }
4375
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004376 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02004377 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304378 if (!a2dp_combo) {
4379 check_a2dp_restore_l(adev, out, false);
4380 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004381 struct listnode dev;
4382 list_init(&dev);
4383 assign_devices(&dev, &out->device_list);
4384 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4385 reassign_device_list(&out->device_list,
4386 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aalique Grahame22e49102018-12-18 14:23:57 -08004387 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004388 reassign_device_list(&out->device_list,
4389 AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304390 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004391 assign_devices(&out->device_list, &dev);
Zhenlin Lian4f947842022-05-14 15:50:52 +05304392 clear_devices(&dev);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304393 }
4394 } else {
Revathi Uddarajub26e3932020-06-10 14:51:02 +05304395 select_devices(adev, out->usecase);
4396 if (is_a2dp_out_device_type(&out->device_list) &&
4397 !adev->a2dp_started) {
4398 if (is_speaker_active || is_speaker_safe_active) {
4399 struct listnode dev;
4400 list_init(&dev);
4401 assign_devices(&dev, &out->device_list);
4402 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4403 reassign_device_list(&out->device_list,
4404 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
4405 else
4406 reassign_device_list(&out->device_list,
4407 AUDIO_DEVICE_OUT_SPEAKER, "");
4408 select_devices(adev, out->usecase);
4409 assign_devices(&out->device_list, &dev);
Zhenlin Lian4f947842022-05-14 15:50:52 +05304410 clear_devices(&dev);
Revathi Uddarajub26e3932020-06-10 14:51:02 +05304411 } else {
4412 ret = -EINVAL;
4413 goto error_open;
4414 }
4415 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304416 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004417
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004418 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
4419 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07004420 voice_set_device_mute_flag(adev, true);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004421 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07004422
Derek Chenea197282019-01-07 17:35:01 -08004423 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
4424 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08004425
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004426 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
4427 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07004428
4429 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07004430 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07004431 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4432 ALOGE("%s: pcm stream not ready", __func__);
4433 goto error_open;
4434 }
4435 ret = pcm_start(out->pcm);
4436 if (ret < 0) {
4437 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
4438 goto error_open;
4439 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07004440 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07004441 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004442 unsigned int flags = PCM_OUT;
4443 unsigned int pcm_open_retry_count = 0;
4444 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
4445 flags |= PCM_MMAP | PCM_NOIRQ;
4446 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004447 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08004448 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004449 } else
4450 flags |= PCM_MONOTONIC;
4451
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004452 if ((adev->vr_audio_mode_enabled) &&
4453 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
4454 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4455 "PCM_Dev %d Topology", out->pcm_device_id);
4456 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4457 if (!ctl) {
4458 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
4459 __func__, mixer_ctl_name);
4460 } else {
4461 //if success use ULLPP
4462 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
4463 __func__, mixer_ctl_name, out->pcm_device_id);
4464 //There is a still a possibility that some sessions
4465 // that request for FAST|RAW when 3D audio is active
4466 //can go through ULLPP. Ideally we expects apps to
4467 //listen to audio focus and stop concurrent playback
4468 //Also, we will look for mode flag (voice_in_communication)
4469 //before enabling the realtime flag.
4470 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
4471 }
4472 }
4473
Vatsal Bucha3f39f222021-06-29 16:16:55 +05304474 platform_set_stream_channel_map(adev->platform, out->channel_mask,
4475 out->pcm_device_id, -1, &out->channel_map_param.channel_map[0]);
Surendar Karka91fa3682018-07-02 18:12:12 +05304476
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004477 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
4478 flags, pcm_open_retry_count,
4479 &(out->config));
4480 if (out->pcm == NULL) {
4481 ret = -EIO;
4482 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004483 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004484
4485 if (is_haptic_usecase) {
4486 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
4487 adev->haptic_pcm_device_id,
4488 flags, pcm_open_retry_count,
4489 &(adev->haptics_config));
4490 // failure to open haptics pcm shouldnt stop audio,
4491 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07004492
4493 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
4494 ALOGD("%s: enable haptic audio synchronization", __func__);
4495 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
4496 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004497 }
4498
Zhou Song2b8f28f2017-09-11 10:51:38 +08004499 // apply volume for voip playback after path is set up
4500 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
4501 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05304502 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
4503 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304504 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
4505 out->apply_volume = false;
Derek Chenf13dd492018-11-13 14:53:51 -08004506 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
4507 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Krishna Kishor Jha10ad39f2022-02-21 17:02:47 +05304508#ifdef SOFT_VOLUME
4509 out_set_soft_volume_params(&out->stream);
4510#endif
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304511 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004512 } else {
Zhou Song79929fe2020-01-20 17:57:43 +08004513 /*
4514 * set custom channel map if:
4515 * 1. neither mono nor stereo clips i.e. channels > 2 OR
4516 * 2. custom channel map has been set by client
4517 * else default channel map of FC/FR/FL can always be set to DSP
4518 */
4519 if (popcount(out->channel_mask) > 2 || out->channel_map_param.channel_map[0])
4520 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Weiyin Jiang810a80d2021-01-18 16:04:31 +08004521 out->pcm_device_id, -1, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08004522 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
4523 adev->dsp_bit_width_enforce_mode,
4524 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004525 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07004526 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004527 out->compr = compress_open(adev->snd_card,
4528 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004529 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004530 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05304531 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05304532 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
4533 adev->card_status = CARD_STATUS_OFFLINE;
4534 out->card_status = CARD_STATUS_OFFLINE;
4535 ret = -EIO;
4536 goto error_open;
4537 }
4538
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004539 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004540 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004541 compress_close(out->compr);
4542 out->compr = NULL;
4543 ret = -EIO;
4544 goto error_open;
4545 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304546 /* compress_open sends params of the track, so reset the flag here */
4547 out->is_compr_metadata_avail = false;
4548
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004549 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004550 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07004551
Fred Oh3f43e742015-03-04 18:42:34 -08004552 /* Since small bufs uses blocking writes, a write will be blocked
4553 for the default max poll time (20s) in the event of an SSR.
4554 Reduce the poll time to observe and deal with SSR faster.
4555 */
Ashish Jain5106d362016-05-11 19:23:33 +05304556 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08004557 compress_set_max_poll_wait(out->compr, 1000);
4558 }
4559
Manish Dewangan69426c82017-01-30 17:35:36 +05304560 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05304561 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05304562
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004563 audio_extn_dts_create_state_notifier_node(out->usecase);
4564 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4565 popcount(out->channel_mask),
4566 out->playback_started);
4567
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004568#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304569 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004570 audio_extn_dolby_send_ddp_endp_params(adev);
4571#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05304572 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
4573 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004574 if (adev->visualizer_start_output != NULL)
4575 adev->visualizer_start_output(out->handle, out->pcm_device_id);
4576 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05304577 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004578 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004579 }
Derek Chenf13dd492018-11-13 14:53:51 -08004580
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004581 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf13dd492018-11-13 14:53:51 -08004582 /* Update cached volume from media to offload/direct stream */
4583 struct listnode *node = NULL;
4584 list_for_each(node, &adev->active_outputs_list) {
4585 streams_output_ctxt_t *out_ctxt = node_to_item(node,
4586 streams_output_ctxt_t,
4587 list);
4588 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
4589 out->volume_l = out_ctxt->output->volume_l;
4590 out->volume_r = out_ctxt->output->volume_r;
4591 }
4592 }
4593 out_set_compr_volume(&out->stream,
4594 out->volume_l, out->volume_r);
4595 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004596 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004597
4598 if (ret == 0) {
Vaibhav Raut5f3bf222023-02-06 17:45:22 +05304599 if (out->flags & (AUDIO_OUTPUT_FLAG_FAST | AUDIO_OUTPUT_FLAG_RAW))
Narsinga Rao Chellaa6e1f702021-10-22 13:57:32 +05304600 register_out_stream(out);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004601 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07004602 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4603 ALOGE("%s: pcm stream not ready", __func__);
4604 goto error_open;
4605 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004606 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004607 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004608 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004609 if (ret < 0)
4610 goto error_open;
4611 }
4612 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004613 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304614 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Jaideep Sharma0fa53812020-09-17 09:00:11 +05304615 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004616
vivek mehtad15d2bf2019-05-17 13:35:10 -07004617 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
4618 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4619 audio_low_latency_hint_start();
4620 }
4621
Manish Dewangan21a850a2017-08-14 12:03:55 +05304622 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07004623 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07004624 if (ret < 0)
4625 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
4626 }
4627
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004628 // consider a scenario where on pause lower layers are tear down.
4629 // so on resume, swap mixer control need to be sent only when
4630 // backend is active, hence rather than sending from enable device
4631 // sending it from start of streamtream
4632
4633 platform_set_swap_channels(adev, true);
4634
Haynes Mathew George380745d2017-10-04 15:27:45 -07004635 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304636 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004637 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004638error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004639 if (adev->haptic_pcm) {
4640 pcm_close(adev->haptic_pcm);
4641 adev->haptic_pcm = NULL;
4642 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004643 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304644 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004645 stop_output_stream(out);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004646error_fatal:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05304647 /*
4648 * sleep 50ms to allow sufficient time for kernel
4649 * drivers to recover incases like SSR.
4650 */
4651 usleep(50000);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004652error_config:
Haynes Mathew George380745d2017-10-04 15:27:45 -07004653 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304654 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004655 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004656}
4657
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004658static int check_input_parameters(uint32_t sample_rate,
4659 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08004660 int channel_count,
4661 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004662{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004663 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004664
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304665 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
4666 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
4667 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07004668 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02004669 !audio_extn_compr_cap_format_supported(format) &&
4670 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004671 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004672
Aalique Grahame22e49102018-12-18 14:23:57 -08004673 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
4674 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
4675 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
4676 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
4677 return -EINVAL;
4678 }
4679
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004680 switch (channel_count) {
4681 case 1:
4682 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304683 case 3:
4684 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004685 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07004686 case 8:
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05304687 case 10:
4688 case 12:
4689 case 14:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004690 break;
4691 default:
4692 ret = -EINVAL;
4693 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004694
4695 switch (sample_rate) {
4696 case 8000:
4697 case 11025:
4698 case 12000:
4699 case 16000:
4700 case 22050:
4701 case 24000:
4702 case 32000:
4703 case 44100:
4704 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004705 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304706 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004707 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304708 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004709 break;
4710 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004711 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004712 }
4713
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004714 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004715}
4716
Naresh Tanniru04f71882018-06-26 17:46:22 +05304717
4718/** Add a value in a list if not already present.
4719 * @return true if value was successfully inserted or already present,
4720 * false if the list is full and does not contain the value.
4721 */
4722static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
4723 for (size_t i = 0; i < list_length; i++) {
4724 if (list[i] == value) return true; // value is already present
4725 if (list[i] == 0) { // no values in this slot
4726 list[i] = value;
4727 return true; // value inserted
4728 }
4729 }
4730 return false; // could not insert value
4731}
4732
4733/** Add channel_mask in supported_channel_masks if not already present.
4734 * @return true if channel_mask was successfully inserted or already present,
4735 * false if supported_channel_masks is full and does not contain channel_mask.
4736 */
4737static void register_channel_mask(audio_channel_mask_t channel_mask,
4738 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
4739 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
4740 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
4741}
4742
4743/** Add format in supported_formats if not already present.
4744 * @return true if format was successfully inserted or already present,
4745 * false if supported_formats is full and does not contain format.
4746 */
4747static void register_format(audio_format_t format,
4748 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
4749 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
4750 "%s: stream can not declare supporting its format %x", __func__, format);
4751}
4752/** Add sample_rate in supported_sample_rates if not already present.
4753 * @return true if sample_rate was successfully inserted or already present,
4754 * false if supported_sample_rates is full and does not contain sample_rate.
4755 */
4756static void register_sample_rate(uint32_t sample_rate,
4757 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
4758 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
4759 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
4760}
4761
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004762static inline uint32_t lcm(uint32_t num1, uint32_t num2)
4763{
4764 uint32_t high = num1, low = num2, temp = 0;
4765
4766 if (!num1 || !num2)
4767 return 0;
4768
4769 if (num1 < num2) {
4770 high = num2;
4771 low = num1;
4772 }
4773
4774 while (low != 0) {
4775 temp = low;
4776 low = high % low;
4777 high = temp;
4778 }
4779 return (num1 * num2)/high;
4780}
4781
4782static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
4783{
4784 uint32_t remainder = 0;
4785
4786 if (!multiplier)
4787 return num;
4788
4789 remainder = num % multiplier;
4790 if (remainder)
4791 num += (multiplier - remainder);
4792
4793 return num;
4794}
4795
Aalique Grahame22e49102018-12-18 14:23:57 -08004796static size_t get_stream_buffer_size(size_t duration_ms,
4797 uint32_t sample_rate,
4798 audio_format_t format,
4799 int channel_count,
4800 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004801{
4802 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004803 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004804
Aalique Grahame22e49102018-12-18 14:23:57 -08004805 size = (sample_rate * duration_ms) / 1000;
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +05304806 if (is_low_latency){
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +05304807#ifndef PLATFORM_AUTO
4808 size = configured_low_latency_capture_period_size;
4809#else
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +05304810 switch(sample_rate) {
4811 case 48000:
4812 size = 240;
4813 break;
4814 case 32000:
4815 size = 160;
4816 break;
4817 case 24000:
4818 size = 120;
4819 break;
4820 case 16000:
4821 size = 80;
4822 break;
4823 case 8000:
4824 size = 40;
4825 break;
4826 default:
4827 size = 240;
4828 }
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +05304829#endif
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +05304830 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304831
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004832 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08004833 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004834
Ralf Herzbd08d632018-09-28 15:50:49 +02004835 /* make sure the size is multiple of 32 bytes and additionally multiple of
4836 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004837 * At 48 kHz mono 16-bit PCM:
4838 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
4839 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004840 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004841 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004842 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07004843
4844 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004845}
4846
Aalique Grahame22e49102018-12-18 14:23:57 -08004847static size_t get_input_buffer_size(uint32_t sample_rate,
4848 audio_format_t format,
4849 int channel_count,
4850 bool is_low_latency)
4851{
Avinash Chandrad7296d42021-08-04 15:07:47 +05304852 bool is_usb_hifi = IS_USB_HIFI;
Aalique Grahame22e49102018-12-18 14:23:57 -08004853 /* Don't know if USB HIFI in this context so use true to be conservative */
4854 if (check_input_parameters(sample_rate, format, channel_count,
Avinash Chandrad7296d42021-08-04 15:07:47 +05304855 is_usb_hifi) != 0)
Aalique Grahame22e49102018-12-18 14:23:57 -08004856 return 0;
4857
4858 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4859 sample_rate,
4860 format,
4861 channel_count,
4862 is_low_latency);
4863}
4864
Derek Chenf6318be2017-06-12 17:16:24 -04004865size_t get_output_period_size(uint32_t sample_rate,
4866 audio_format_t format,
4867 int channel_count,
4868 int duration /*in millisecs*/)
Ashish Jain058165c2016-09-28 23:18:48 +05304869{
4870 size_t size = 0;
4871 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
4872
4873 if ((duration == 0) || (sample_rate == 0) ||
4874 (bytes_per_sample == 0) || (channel_count == 0)) {
4875 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
4876 bytes_per_sample, channel_count);
4877 return -EINVAL;
4878 }
4879
4880 size = (sample_rate *
4881 duration *
4882 bytes_per_sample *
4883 channel_count) / 1000;
4884 /*
4885 * To have same PCM samples for all channels, the buffer size requires to
4886 * be multiple of (number of channels * bytes per sample)
4887 * For writes to succeed, the buffer must be written at address which is multiple of 32
4888 */
4889 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
4890
4891 return (size/(channel_count * bytes_per_sample));
4892}
4893
Zhou Song48453a02018-01-10 17:50:59 +08004894static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05304895{
4896 uint64_t actual_frames_rendered = 0;
Weiyin Jiang4813da12020-05-28 00:37:28 +08004897 uint64_t written_frames = 0;
4898 uint64_t kernel_frames = 0;
4899 uint64_t dsp_frames = 0;
4900 uint64_t signed_frames = 0;
4901 size_t kernel_buffer_size = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304902
4903 /* This adjustment accounts for buffering after app processor.
4904 * It is based on estimated DSP latency per use case, rather than exact.
4905 */
George Gao9ba8a142020-07-23 14:30:03 -07004906 dsp_frames = platform_render_latency(out) *
Weiyin Jiang4813da12020-05-28 00:37:28 +08004907 out->sample_rate / 1000000LL;
Ashish Jain5106d362016-05-11 19:23:33 +05304908
Zhou Song48453a02018-01-10 17:50:59 +08004909 pthread_mutex_lock(&out->position_query_lock);
Weiyin Jiang4813da12020-05-28 00:37:28 +08004910 written_frames = out->written /
4911 (audio_bytes_per_sample(out->hal_ip_format) * popcount(out->channel_mask));
4912
Ashish Jain5106d362016-05-11 19:23:33 +05304913 /* not querying actual state of buffering in kernel as it would involve an ioctl call
4914 * which then needs protection, this causes delay in TS query for pcm_offload usecase
4915 * hence only estimate.
4916 */
Weiyin Jiang4813da12020-05-28 00:37:28 +08004917 kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
4918 kernel_frames = kernel_buffer_size /
4919 (audio_bytes_per_sample(out->hal_op_format) * popcount(out->channel_mask));
Ashish Jain5106d362016-05-11 19:23:33 +05304920
Weiyin Jiang4813da12020-05-28 00:37:28 +08004921 if (written_frames >= (kernel_frames + dsp_frames))
4922 signed_frames = written_frames - kernel_frames - dsp_frames;
Ashish Jain5106d362016-05-11 19:23:33 +05304923
Zhou Song48453a02018-01-10 17:50:59 +08004924 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05304925 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08004926 if (timestamp != NULL )
4927 *timestamp = out->writeAt;
4928 } else if (timestamp != NULL) {
4929 clock_gettime(CLOCK_MONOTONIC, timestamp);
4930 }
4931 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304932
Weiyin Jiang4813da12020-05-28 00:37:28 +08004933 ALOGVV("%s signed frames %lld written frames %lld kernel frames %lld dsp frames %lld",
4934 __func__, signed_frames, written_frames, kernel_frames, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05304935
4936 return actual_frames_rendered;
4937}
4938
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004939static uint32_t out_get_sample_rate(const struct audio_stream *stream)
4940{
4941 struct stream_out *out = (struct stream_out *)stream;
4942
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004943 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004944}
4945
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004946static int out_set_sample_rate(struct audio_stream *stream __unused,
4947 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004948{
4949 return -ENOSYS;
4950}
4951
4952static size_t out_get_buffer_size(const struct audio_stream *stream)
4953{
4954 struct stream_out *out = (struct stream_out *)stream;
4955
Varun Balaraje49253e2017-07-06 19:48:56 +05304956 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05304957 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05304958 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304959 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4960 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
4961 else
4962 return out->compr_config.fragment_size;
4963 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004964 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304965 else if (is_offload_usecase(out->usecase) &&
4966 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304967 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004968
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004969 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004970 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004971}
4972
4973static uint32_t out_get_channels(const struct audio_stream *stream)
4974{
4975 struct stream_out *out = (struct stream_out *)stream;
4976
4977 return out->channel_mask;
4978}
4979
4980static audio_format_t out_get_format(const struct audio_stream *stream)
4981{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004982 struct stream_out *out = (struct stream_out *)stream;
4983
4984 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004985}
4986
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004987static int out_set_format(struct audio_stream *stream __unused,
4988 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004989{
4990 return -ENOSYS;
4991}
4992
4993static int out_standby(struct audio_stream *stream)
4994{
4995 struct stream_out *out = (struct stream_out *)stream;
4996 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07004997 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004998
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304999 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
5000 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005001
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005002 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005003 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005004 if (adev->adm_deregister_stream)
5005 adev->adm_deregister_stream(adev->adm_data, out->handle);
5006
Weiyin Jiang280ea742020-09-08 20:28:22 +08005007 if (is_offload_usecase(out->usecase)) {
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07005008 stop_compressed_output_l(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08005009 }
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07005010
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08005011 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005012 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08005013 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
5014 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305015 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08005016 pthread_mutex_unlock(&adev->lock);
5017 pthread_mutex_unlock(&out->lock);
5018 ALOGD("VOIP output entered standby");
5019 return 0;
5020 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005021 if (out->pcm) {
5022 pcm_close(out->pcm);
5023 out->pcm = NULL;
5024 }
Meng Wanga09da002020-04-20 12:56:04 +08005025 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
5026 if (adev->haptic_pcm) {
5027 pcm_close(adev->haptic_pcm);
5028 adev->haptic_pcm = NULL;
5029 }
5030
5031 if (adev->haptic_buffer != NULL) {
5032 free(adev->haptic_buffer);
5033 adev->haptic_buffer = NULL;
5034 adev->haptic_buffer_size = 0;
5035 }
5036 adev->haptic_pcm_device_id = 0;
5037 }
5038
Haynes Mathew George16081042017-05-31 17:16:49 -07005039 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5040 do_stop = out->playback_started;
5041 out->playback_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07005042
5043 if (out->mmap_shared_memory_fd >= 0) {
5044 ALOGV("%s: closing mmap_shared_memory_fd = %d",
5045 __func__, out->mmap_shared_memory_fd);
5046 close(out->mmap_shared_memory_fd);
5047 out->mmap_shared_memory_fd = -1;
5048 }
Haynes Mathew George16081042017-05-31 17:16:49 -07005049 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005050 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005051 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305052 out->send_next_track_params = false;
5053 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005054 out->gapless_mdata.encoder_delay = 0;
5055 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005056 if (out->compr != NULL) {
5057 compress_close(out->compr);
5058 out->compr = NULL;
5059 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08005060 }
Haynes Mathew George16081042017-05-31 17:16:49 -07005061 if (do_stop) {
5062 stop_output_stream(out);
5063 }
Lakshman Chaluvaraju06677b42019-06-24 10:04:52 +05305064 // if fm is active route on selected device in UI
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005065 audio_extn_fm_route_on_selected_device(adev, &out->device_list);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005066 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005067 }
5068 pthread_mutex_unlock(&out->lock);
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07005069 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005070 return 0;
5071}
5072
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305073static int out_on_error(struct audio_stream *stream)
5074{
5075 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07005076 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305077
5078 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08005079 // always send CMD_ERROR for offload streams, this
5080 // is needed e.g. when SSR happens within compress_open
5081 // since the stream is active, offload_callback_thread is also active.
5082 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
5083 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07005084 }
5085 pthread_mutex_unlock(&out->lock);
5086
5087 status = out_standby(&out->stream.common);
5088
5089 lock_output_stream(out);
5090 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08005091 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305092 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05305093
5094 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
5095 ALOGD("Setting previous card status if offline");
5096 out->prev_card_status_offline = true;
5097 }
5098
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305099 pthread_mutex_unlock(&out->lock);
5100
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07005101 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305102}
5103
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305104/*
Weiyin Jiang280ea742020-09-08 20:28:22 +08005105 * standby implementation without locks, assumes that the callee already
5106 * has taken adev and out lock.
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305107 */
5108int out_standby_l(struct audio_stream *stream)
5109{
5110 struct stream_out *out = (struct stream_out *)stream;
5111 struct audio_device *adev = out->dev;
5112
5113 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
5114 stream, out->usecase, use_case_table[out->usecase]);
5115
5116 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07005117 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305118 if (adev->adm_deregister_stream)
5119 adev->adm_deregister_stream(adev->adm_data, out->handle);
5120
Weiyin Jiang280ea742020-09-08 20:28:22 +08005121 if (is_offload_usecase(out->usecase)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305122 stop_compressed_output_l(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08005123 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305124
5125 out->standby = true;
5126 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
5127 voice_extn_compress_voip_close_output_stream(stream);
5128 out->started = 0;
5129 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07005130 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305131 return 0;
5132 } else if (!is_offload_usecase(out->usecase)) {
5133 if (out->pcm) {
5134 pcm_close(out->pcm);
5135 out->pcm = NULL;
5136 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005137 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
5138 if (adev->haptic_pcm) {
5139 pcm_close(adev->haptic_pcm);
5140 adev->haptic_pcm = NULL;
5141 }
5142
5143 if (adev->haptic_buffer != NULL) {
5144 free(adev->haptic_buffer);
5145 adev->haptic_buffer = NULL;
5146 adev->haptic_buffer_size = 0;
5147 }
5148 adev->haptic_pcm_device_id = 0;
5149 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305150 } else {
5151 ALOGD("copl(%p):standby", out);
5152 out->send_next_track_params = false;
5153 out->is_compr_metadata_avail = false;
5154 out->gapless_mdata.encoder_delay = 0;
5155 out->gapless_mdata.encoder_padding = 0;
5156 if (out->compr != NULL) {
5157 compress_close(out->compr);
5158 out->compr = NULL;
5159 }
5160 }
5161 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005162 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305163 }
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07005164 ALOGV("%s: exit", __func__);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305165 return 0;
5166}
5167
Aalique Grahame22e49102018-12-18 14:23:57 -08005168static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005169{
Aalique Grahame22e49102018-12-18 14:23:57 -08005170 struct stream_out *out = (struct stream_out *)stream;
5171
5172 // We try to get the lock for consistency,
5173 // but it isn't necessary for these variables.
5174 // If we're not in standby, we may be blocked on a write.
5175 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
5176 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
5177 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
Dechen Chai22768452021-07-30 09:29:16 +05305178#ifndef LINUX_ENABLED
Andy Hunga1f48fa2019-07-01 18:14:53 -07005179 char buffer[256]; // for statistics formatting
5180 if (!is_offload_usecase(out->usecase)) {
5181 simple_stats_to_string(&out->fifo_underruns, buffer, sizeof(buffer));
5182 dprintf(fd, " Fifo frame underruns: %s\n", buffer);
5183 }
5184
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005185 if (out->start_latency_ms.n > 0) {
5186 simple_stats_to_string(&out->start_latency_ms, buffer, sizeof(buffer));
5187 dprintf(fd, " Start latency ms: %s\n", buffer);
5188 }
Dechen Chai22768452021-07-30 09:29:16 +05305189#endif
Aalique Grahame22e49102018-12-18 14:23:57 -08005190 if (locked) {
5191 pthread_mutex_unlock(&out->lock);
5192 }
5193
Dechen Chai22768452021-07-30 09:29:16 +05305194#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -08005195 // dump error info
5196 (void)error_log_dump(
5197 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Dechen Chai22768452021-07-30 09:29:16 +05305198#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005199 return 0;
5200}
5201
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005202static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
5203{
5204 int ret = 0;
5205 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08005206
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005207 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08005208 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005209 return -EINVAL;
5210 }
5211
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05305212 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08005213
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005214 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
5215 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05305216 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005217 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005218 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
5219 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05305220 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005221 }
5222
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005223 ALOGV("%s new encoder delay %u and padding %u", __func__,
5224 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
5225
5226 return 0;
5227}
5228
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005229static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
5230{
5231 return out == adev->primary_output || out == adev->voice_tx_output;
5232}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005233
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305234// note: this call is safe only if the stream_cb is
5235// removed first in close_output_stream (as is done now).
5236static void out_snd_mon_cb(void * stream, struct str_parms * parms)
5237{
5238 if (!stream || !parms)
5239 return;
5240
5241 struct stream_out *out = (struct stream_out *)stream;
5242 struct audio_device *adev = out->dev;
5243
5244 card_status_t status;
5245 int card;
5246 if (parse_snd_card_status(parms, &card, &status) < 0)
5247 return;
5248
5249 pthread_mutex_lock(&adev->lock);
5250 bool valid_cb = (card == adev->snd_card);
5251 pthread_mutex_unlock(&adev->lock);
5252
5253 if (!valid_cb)
5254 return;
5255
5256 lock_output_stream(out);
5257 if (out->card_status != status)
5258 out->card_status = status;
5259 pthread_mutex_unlock(&out->lock);
5260
5261 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
5262 use_case_table[out->usecase],
5263 status == CARD_STATUS_OFFLINE ? "offline" : "online");
5264
Aditya Bavanari59ebed42019-02-05 17:44:57 +05305265 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305266 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05305267 if (voice_is_call_state_active(adev) &&
5268 out == adev->primary_output) {
5269 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
5270 pthread_mutex_lock(&adev->lock);
5271 voice_stop_call(adev);
5272 adev->mode = AUDIO_MODE_NORMAL;
5273 pthread_mutex_unlock(&adev->lock);
5274 }
5275 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305276 return;
5277}
5278
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005279int route_output_stream(struct stream_out *out,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005280 struct listnode *devices)
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005281{
5282 struct audio_device *adev = out->dev;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005283 int ret = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005284 struct listnode new_devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005285 bool bypass_a2dp = false;
5286 bool reconfig = false;
5287 unsigned long service_interval = 0;
5288
5289 ALOGD("%s: enter: usecase(%d: %s) devices %x",
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005290 __func__, out->usecase, use_case_table[out->usecase], get_device_types(devices));
5291
5292 list_init(&new_devices);
5293 assign_devices(&new_devices, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005294
5295 lock_output_stream(out);
5296 pthread_mutex_lock(&adev->lock);
5297
5298 /*
5299 * When HDMI cable is unplugged the music playback is paused and
5300 * the policy manager sends routing=0. But the audioflinger continues
5301 * to write data until standby time (3sec). As the HDMI core is
5302 * turned off, the write gets blocked.
5303 * Avoid this by routing audio to speaker until standby.
5304 */
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08005305 if (is_single_device_type_equal(&out->device_list,
5306 AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005307 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005308 !audio_extn_passthru_is_passthrough_stream(out) &&
5309 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005310 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005311 }
5312 /*
5313 * When A2DP is disconnected the
5314 * music playback is paused and the policy manager sends routing=0
5315 * But the audioflinger continues to write data until standby time
5316 * (3sec). As BT is turned off, the write gets blocked.
5317 * Avoid this by routing audio to speaker until standby.
5318 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005319 if (is_a2dp_out_device_type(&out->device_list) &&
5320 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005321 !audio_extn_a2dp_source_is_ready() &&
5322 !adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005323 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005324 }
5325 /*
Weiyin Jiangabedea32020-12-09 12:49:19 +08005326 * When USB headset is disconnected the music playback paused
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005327 * and the policy manager send routing=0. But if the USB is connected
5328 * back before the standby time, AFE is not closed and opened
5329 * when USB is connected back. So routing to speker will guarantee
5330 * AFE reconfiguration and AFE will be opend once USB is connected again
5331 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005332 if (is_usb_out_device_type(&out->device_list) &&
5333 list_empty(&new_devices) &&
5334 !audio_extn_usb_connected(NULL)) {
Sujin Panicker84d953a2020-11-16 17:39:54 +05305335 if (adev->mode == AUDIO_MODE_IN_CALL || adev->mode == AUDIO_MODE_IN_COMMUNICATION)
5336 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_EARPIECE, "");
5337 else
5338 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005339 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005340 /* To avoid a2dp to sco overlapping / BT device improper state
5341 * check with BT lib about a2dp streaming support before routing
5342 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005343 if (is_a2dp_out_device_type(&new_devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005344 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005345 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER) ||
5346 compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005347 //combo usecase just by pass a2dp
5348 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
5349 bypass_a2dp = true;
5350 } else {
5351 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
5352 /* update device to a2dp and don't route as BT returned error
5353 * However it is still possible a2dp routing called because
5354 * of current active device disconnection (like wired headset)
5355 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005356 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005357 pthread_mutex_unlock(&adev->lock);
5358 pthread_mutex_unlock(&out->lock);
5359 goto error;
5360 }
5361 }
5362 }
5363
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005364 // Workaround: If routing to an non existing usb device, fail gracefully
5365 // The routing request will otherwise block during 10 second
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005366 if (is_usb_out_device_type(&new_devices)) {
5367 struct str_parms *parms =
5368 str_parms_create_str(get_usb_device_address(&new_devices));
5369 if (!parms)
5370 goto error;
Weiyin Jiangabedea32020-12-09 12:49:19 +08005371 if (!audio_extn_usb_connected(NULL)) {
5372 ALOGW("%s: ignoring rerouting to non existing USB card", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005373 pthread_mutex_unlock(&adev->lock);
5374 pthread_mutex_unlock(&out->lock);
5375 str_parms_destroy(parms);
5376 ret = -ENOSYS;
5377 goto error;
5378 }
5379 str_parms_destroy(parms);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005380 }
5381
Weiyin Jiang80c8f9a2020-01-10 20:42:08 +08005382 // Workaround: If routing to an non existing hdmi device, fail gracefully
5383 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
5384 (platform_get_edid_info_v2(adev->platform,
5385 out->extconn.cs.controller,
5386 out->extconn.cs.stream) != 0)) {
5387 ALOGW("out_set_parameters() ignoring rerouting to non existing HDMI/DP");
5388 pthread_mutex_unlock(&adev->lock);
5389 pthread_mutex_unlock(&out->lock);
5390 ret = -ENOSYS;
5391 goto error;
5392 }
5393
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005394 /*
5395 * select_devices() call below switches all the usecases on the same
5396 * backend to the new device. Refer to check_usecases_codec_backend() in
5397 * the select_devices(). But how do we undo this?
5398 *
5399 * For example, music playback is active on headset (deep-buffer usecase)
5400 * and if we go to ringtones and select a ringtone, low-latency usecase
5401 * will be started on headset+speaker. As we can't enable headset+speaker
5402 * and headset devices at the same time, select_devices() switches the music
5403 * playback to headset+speaker while starting low-lateny usecase for ringtone.
5404 * So when the ringtone playback is completed, how do we undo the same?
5405 *
5406 * We are relying on the out_set_parameters() call on deep-buffer output,
5407 * once the ringtone playback is ended.
5408 * NOTE: We should not check if the current devices are same as new devices.
5409 * Because select_devices() must be called to switch back the music
5410 * playback to headset.
5411 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005412 if (!list_empty(&new_devices)) {
5413 bool same_dev = compare_devices(&out->device_list, &new_devices);
5414 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005415
5416 if (output_drives_call(adev, out)) {
5417 if (!voice_is_call_state_active(adev)) {
5418 if (adev->mode == AUDIO_MODE_IN_CALL) {
5419 adev->current_call_output = out;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005420 ret = voice_start_call(adev);
5421 }
5422 } else {
Kunlei Zhang253ad102020-10-14 16:21:28 +08005423 platform_is_volume_boost_supported_device(adev->platform, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005424 adev->current_call_output = out;
5425 voice_update_devices_for_all_voice_usecases(adev);
5426 }
5427 }
5428
Mingshu Pang971ff702020-09-09 15:28:22 +08005429 if (is_usb_out_device_type(&out->device_list)) {
5430 service_interval = audio_extn_usb_find_service_interval(false, true /*playback*/);
5431 audio_extn_usb_set_service_interval(true /*playback*/,
5432 service_interval,
5433 &reconfig);
5434 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
5435 }
5436
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005437 if (!out->standby) {
5438 if (!same_dev) {
5439 ALOGV("update routing change");
5440 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
5441 adev->perf_lock_opts,
5442 adev->perf_lock_opts_size);
5443 if (adev->adm_on_routing_change)
5444 adev->adm_on_routing_change(adev->adm_data,
5445 out->handle);
5446 }
5447 if (!bypass_a2dp) {
5448 select_devices(adev, out->usecase);
5449 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005450 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
5451 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005452 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005453 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005454 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005455 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005456 }
5457
5458 if (!same_dev) {
5459 // on device switch force swap, lower functions will make sure
5460 // to check if swap is allowed or not.
5461 platform_set_swap_channels(adev, true);
5462 audio_extn_perf_lock_release(&adev->perf_lock_handle);
5463 }
Zhou Songbaddf9f2020-11-20 13:57:39 +08005464 pthread_mutex_lock(&out->latch_lock);
5465 if (!is_a2dp_out_device_type(&out->device_list) || audio_extn_a2dp_source_is_ready()) {
5466 if (out->a2dp_muted) {
5467 out->a2dp_muted = false;
5468 if (is_offload_usecase(out->usecase))
5469 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5470 else if (out->usecase != USECASE_AUDIO_PLAYBACK_VOIP)
5471 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Weiyin Jiang280ea742020-09-08 20:28:22 +08005472 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005473 }
Zhou Songbaddf9f2020-11-20 13:57:39 +08005474 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP && !out->a2dp_muted)
5475 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
5476 pthread_mutex_unlock(&out->latch_lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005477 }
5478 }
5479
5480 pthread_mutex_unlock(&adev->lock);
5481 pthread_mutex_unlock(&out->lock);
5482
5483 /*handles device and call state changes*/
5484 audio_extn_extspk_update(adev->extspk);
5485
Revathi Uddaraju4255a632021-12-02 05:11:13 -08005486 clear_devices(&new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005487error:
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005488 ALOGV("%s: exit: code(%d)", __func__, ret);
5489 return ret;
5490}
5491
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005492static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
5493{
5494 struct stream_out *out = (struct stream_out *)stream;
5495 struct audio_device *adev = out->dev;
5496 struct str_parms *parms;
5497 char value[32];
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005498 int ret = 0, err;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005499 int ext_controller = -1;
5500 int ext_stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005501
sangwoobc677242013-08-08 16:53:43 +09005502 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005503 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005504 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305505 if (!parms)
5506 goto error;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005507
5508 err = platform_get_controller_stream_from_params(parms, &ext_controller,
5509 &ext_stream);
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08005510 if (err == 0) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005511 out->extconn.cs.controller = ext_controller;
5512 out->extconn.cs.stream = ext_stream;
5513 ALOGD("%s: usecase(%s) new controller/stream (%d/%d)", __func__,
5514 use_case_table[out->usecase], out->extconn.cs.controller,
5515 out->extconn.cs.stream);
5516 }
5517
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005518 if (out == adev->primary_output) {
5519 pthread_mutex_lock(&adev->lock);
5520 audio_extn_set_parameters(adev, parms);
5521 pthread_mutex_unlock(&adev->lock);
5522 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005523 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005524 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005525 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005526
5527 audio_extn_dts_create_state_notifier_node(out->usecase);
5528 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5529 popcount(out->channel_mask),
5530 out->playback_started);
5531
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08005532 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005533 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005534
Surendar Karkaf51b5842018-04-26 11:28:38 +05305535 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
5536 sizeof(value));
5537 if (err >= 0) {
5538 if (!strncmp("true", value, sizeof("true")) || atoi(value))
5539 audio_extn_send_dual_mono_mixing_coefficients(out);
5540 }
5541
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305542 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5543 if (err >= 0) {
5544 strlcpy(out->profile, value, sizeof(out->profile));
5545 ALOGV("updating stream profile with value '%s'", out->profile);
5546 lock_output_stream(out);
5547 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
5548 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005549 &out->device_list, out->flags,
5550 out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305551 out->sample_rate, out->bit_width,
5552 out->channel_mask, out->profile,
5553 &out->app_type_cfg);
5554 pthread_mutex_unlock(&out->lock);
5555 }
5556
Alexy Joseph98988832017-01-13 14:56:59 -08005557 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005558 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
5559 // and vendor.audio.hal.output.suspend.supported is set to true
5560 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08005561 //check suspend parameter only for low latency and if the property
5562 //is enabled
5563 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
5564 ALOGI("%s: got suspend_playback %s", __func__, value);
5565 lock_output_stream(out);
5566 if (!strncmp(value, "false", 5)) {
5567 //suspend_playback=false is supposed to set QOS value back to 75%
5568 //the mixer control sent with value Enable will achieve that
5569 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5570 } else if (!strncmp (value, "true", 4)) {
5571 //suspend_playback=true is supposed to remove QOS value
5572 //resetting the mixer control will set the default value
5573 //for the mixer control which is Disable and this removes the QOS vote
5574 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5575 } else {
5576 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
5577 " got %s", __func__, value);
5578 ret = -1;
5579 }
5580
5581 if (ret != 0) {
5582 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
5583 __func__, out->pm_qos_mixer_path, ret);
5584 }
5585
5586 pthread_mutex_unlock(&out->lock);
5587 }
5588 }
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005589
Alexy Joseph98988832017-01-13 14:56:59 -08005590 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005591 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305592error:
Eric Laurent994a6932013-07-17 11:51:42 -07005593 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005594 return ret;
5595}
5596
Paul McLeana50b7332018-12-17 08:24:21 -07005597static int in_set_microphone_direction(const struct audio_stream_in *stream,
5598 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07005599 struct stream_in *in = (struct stream_in *)stream;
5600
5601 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
5602
5603 in->direction = dir;
5604
5605 if (in->standby)
5606 return 0;
5607
5608 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07005609}
5610
5611static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07005612 struct stream_in *in = (struct stream_in *)stream;
5613
5614 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
5615
5616 if (zoom > 1.0 || zoom < -1.0)
5617 return -EINVAL;
5618
5619 in->zoom = zoom;
5620
5621 if (in->standby)
5622 return 0;
5623
5624 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07005625}
5626
5627
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005628static bool stream_get_parameter_channels(struct str_parms *query,
5629 struct str_parms *reply,
5630 audio_channel_mask_t *supported_channel_masks) {
5631 int ret = -1;
5632 char value[512];
5633 bool first = true;
5634 size_t i, j;
5635
5636 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
5637 ret = 0;
5638 value[0] = '\0';
5639 i = 0;
5640 while (supported_channel_masks[i] != 0) {
5641 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5642 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
5643 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305644 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005645
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305646 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005647 first = false;
5648 break;
5649 }
5650 }
5651 i++;
5652 }
5653 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5654 }
5655 return ret == 0;
5656}
5657
5658static bool stream_get_parameter_formats(struct str_parms *query,
5659 struct str_parms *reply,
5660 audio_format_t *supported_formats) {
5661 int ret = -1;
5662 char value[256];
5663 size_t i, j;
5664 bool first = true;
5665
5666 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
5667 ret = 0;
5668 value[0] = '\0';
5669 i = 0;
5670 while (supported_formats[i] != 0) {
5671 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5672 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
5673 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305674 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005675 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305676 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005677 first = false;
5678 break;
5679 }
5680 }
5681 i++;
5682 }
5683 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
5684 }
5685 return ret == 0;
5686}
5687
5688static bool stream_get_parameter_rates(struct str_parms *query,
5689 struct str_parms *reply,
5690 uint32_t *supported_sample_rates) {
5691
5692 int i;
5693 char value[256];
5694 int ret = -1;
5695 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
5696 ret = 0;
5697 value[0] = '\0';
5698 i=0;
5699 int cursor = 0;
5700 while (supported_sample_rates[i]) {
5701 int avail = sizeof(value) - cursor;
5702 ret = snprintf(value + cursor, avail, "%s%d",
5703 cursor > 0 ? "|" : "",
5704 supported_sample_rates[i]);
5705 if (ret < 0 || ret >= avail) {
5706 // if cursor is at the last element of the array
5707 // overwrite with \0 is duplicate work as
5708 // snprintf already put a \0 in place.
5709 // else
5710 // we had space to write the '|' at value[cursor]
5711 // (which will be overwritten) or no space to fill
5712 // the first element (=> cursor == 0)
5713 value[cursor] = '\0';
5714 break;
5715 }
5716 cursor += ret;
5717 ++i;
5718 }
5719 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
5720 value);
5721 }
5722 return ret >= 0;
5723}
5724
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005725static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
5726{
5727 struct stream_out *out = (struct stream_out *)stream;
5728 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005729 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005730 char value[256];
5731 struct str_parms *reply = str_parms_create();
5732 size_t i, j;
5733 int ret;
5734 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005735
5736 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005737 if (reply) {
5738 str_parms_destroy(reply);
5739 }
5740 if (query) {
5741 str_parms_destroy(query);
5742 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005743 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
5744 return NULL;
5745 }
5746
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005747 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005748 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
5749 if (ret >= 0) {
5750 value[0] = '\0';
5751 i = 0;
5752 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005753 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5754 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005755 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005756 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005757 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005758 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005759 first = false;
5760 break;
5761 }
5762 }
5763 i++;
5764 }
5765 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5766 str = str_parms_to_str(reply);
5767 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005768 voice_extn_out_get_parameters(out, query, reply);
5769 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005770 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005771
Alexy Joseph62142aa2015-11-16 15:10:34 -08005772
5773 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
5774 if (ret >= 0) {
5775 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05305776 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
5777 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08005778 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305779 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005780 } else {
5781 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05305782 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005783 }
5784 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005785 if (str)
5786 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08005787 str = str_parms_to_str(reply);
5788 }
5789
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005790 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
5791 if (ret >= 0) {
5792 value[0] = '\0';
5793 i = 0;
5794 first = true;
5795 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005796 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5797 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005798 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005799 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005800 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005801 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005802 first = false;
5803 break;
5804 }
5805 }
5806 i++;
5807 }
5808 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005809 if (str)
5810 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005811 str = str_parms_to_str(reply);
5812 }
Mingming Yin3a941d42016-02-17 18:08:05 -08005813
5814 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
5815 if (ret >= 0) {
5816 value[0] = '\0';
5817 i = 0;
5818 first = true;
5819 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005820 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
5821 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005822 if (!first) {
5823 strlcat(value, "|", sizeof(value));
5824 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005825 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08005826 first = false;
5827 break;
5828 }
5829 }
5830 i++;
5831 }
5832 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
5833 if (str)
5834 free(str);
5835 str = str_parms_to_str(reply);
5836 }
5837
Alexy Joseph98988832017-01-13 14:56:59 -08005838 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
5839 //only low latency track supports suspend_resume
5840 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005841 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08005842 if (str)
5843 free(str);
5844 str = str_parms_to_str(reply);
5845 }
5846
5847
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005848 str_parms_destroy(query);
5849 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07005850 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005851 return str;
5852}
5853
5854static uint32_t out_get_latency(const struct audio_stream_out *stream)
5855{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005856 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005857 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08005858 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005859
Alexy Josephaa54c872014-12-03 02:46:47 -08005860 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05305861 lock_output_stream(out);
5862 latency = audio_extn_utils_compress_get_dsp_latency(out);
5863 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005864 } else if ((out->realtime) ||
5865 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005866 // since the buffer won't be filled up faster than realtime,
5867 // return a smaller number
5868 if (out->config.rate)
5869 period_ms = (out->af_period_multiplier * out->config.period_size *
5870 1000) / (out->config.rate);
5871 else
5872 period_ms = 0;
George Gao9ba8a142020-07-23 14:30:03 -07005873 latency = period_ms + platform_render_latency(out) / 1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005874 } else {
5875 latency = (out->config.period_count * out->config.period_size * 1000) /
Mingshu Pangf69a88d2021-04-30 16:14:39 +08005876 (out->config.rate);
pavanisra2d95d82022-02-09 18:55:58 +05305877 if (out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5878 out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY)
Mingshu Pangf69a88d2021-04-30 16:14:39 +08005879 latency += platform_render_latency(out)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005880 }
5881
Zhou Songd2537a02020-06-11 22:04:46 +08005882 if (!out->standby && is_a2dp_out_device_type(&out->device_list))
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08005883 latency += audio_extn_a2dp_get_encoder_latency();
5884
Anish Kumar50ebcbf2014-12-09 04:01:39 +05305885 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08005886 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005887}
5888
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305889static float AmpToDb(float amplification)
5890{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305891 float db = DSD_VOLUME_MIN_DB;
5892 if (amplification > 0) {
5893 db = 20 * log10(amplification);
5894 if(db < DSD_VOLUME_MIN_DB)
5895 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305896 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305897 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305898}
5899
Krishna Kishor Jha10ad39f2022-02-21 17:02:47 +05305900#ifdef SOFT_VOLUME
5901static int out_set_soft_volume_params(struct audio_stream_out *stream)
5902{
5903 struct stream_out *out = (struct stream_out *)stream;
5904 int ret = 0;
5905 char mixer_ctl_name[128];
5906 struct audio_device *adev = out->dev;
5907 struct mixer_ctl *ctl = NULL;
5908 struct soft_step_volume_params *volume_params = NULL;
5909
5910 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5911 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Soft Vol Params", pcm_device_id);
5912 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5913 if (!ctl) {
5914 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5915 return -EINVAL;
5916 }
5917
5918 volume_params =(struct soft_step_volume_params * ) malloc(sizeof(struct soft_step_volume_params));
5919 if (volume_params == NULL){
5920 ALOGE("%s : malloc is failed for volume params", __func__);
5921 return -EINVAL;
5922 } else {
5923 ret = platform_get_soft_step_volume_params(volume_params,out->usecase);
5924 if (ret < 0) {
5925 ALOGE("%s : platform_get_soft_step_volume_params is fialed", __func__);
Karan Naidu28b335a2022-05-18 23:00:08 +05305926 ret = -EINVAL;
5927 goto ERR_EXIT;
Krishna Kishor Jha10ad39f2022-02-21 17:02:47 +05305928 }
5929
5930 }
5931 ret = mixer_ctl_set_array(ctl, volume_params, sizeof(struct soft_step_volume_params)/sizeof(int));
5932 if (ret < 0) {
5933 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
Karan Naidu28b335a2022-05-18 23:00:08 +05305934 ret = -EINVAL;
5935 goto ERR_EXIT;
5936 }
5937
5938 if (volume_params) {
5939 free(volume_params);
Krishna Kishor Jha10ad39f2022-02-21 17:02:47 +05305940 }
5941 return 0;
Karan Naidu28b335a2022-05-18 23:00:08 +05305942
5943ERR_EXIT:
5944 if (volume_params) {
5945 free(volume_params);
5946 }
5947 return ret;
Krishna Kishor Jha10ad39f2022-02-21 17:02:47 +05305948}
5949#endif
5950
Arun Mirpuri5d170872019-03-26 13:21:31 -07005951static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
5952 float right)
5953{
5954 struct stream_out *out = (struct stream_out *)stream;
5955 long volume = 0;
5956 char mixer_ctl_name[128] = "";
5957 struct audio_device *adev = out->dev;
5958 struct mixer_ctl *ctl = NULL;
5959 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5960 PCM_PLAYBACK);
5961
5962 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5963 "Playback %d Volume", pcm_device_id);
5964 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5965 if (!ctl) {
5966 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5967 __func__, mixer_ctl_name);
5968 return -EINVAL;
5969 }
5970 if (left != right)
5971 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
5972 __func__, left, right);
5973 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
5974 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
5975 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
5976 __func__, mixer_ctl_name, volume);
5977 return -EINVAL;
5978 }
5979 return 0;
5980}
5981
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305982static int out_set_compr_volume(struct audio_stream_out *stream, float left,
5983 float right)
5984{
5985 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305986 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305987 char mixer_ctl_name[128];
5988 struct audio_device *adev = out->dev;
5989 struct mixer_ctl *ctl;
5990 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5991 PCM_PLAYBACK);
5992
5993 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5994 "Compress Playback %d Volume", pcm_device_id);
5995 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5996 if (!ctl) {
5997 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5998 __func__, mixer_ctl_name);
5999 return -EINVAL;
6000 }
6001 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
6002 __func__, mixer_ctl_name, left, right);
6003 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
6004 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
6005 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
6006
6007 return 0;
6008}
6009
Zhou Song2b8f28f2017-09-11 10:51:38 +08006010static int out_set_voip_volume(struct audio_stream_out *stream, float left,
6011 float right)
6012{
6013 struct stream_out *out = (struct stream_out *)stream;
6014 char mixer_ctl_name[] = "App Type Gain";
6015 struct audio_device *adev = out->dev;
6016 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05306017 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08006018
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07006019 if (!is_valid_volume(left, right)) {
6020 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
6021 __func__, left, right);
6022 return -EINVAL;
6023 }
6024
Zhou Song2b8f28f2017-09-11 10:51:38 +08006025 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
6026 if (!ctl) {
6027 ALOGE("%s: Could not get ctl for mixer cmd - %s",
6028 __func__, mixer_ctl_name);
6029 return -EINVAL;
6030 }
6031
6032 set_values[0] = 0; //0: Rx Session 1:Tx Session
6033 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05306034 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
6035 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08006036
6037 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
6038 return 0;
6039}
6040
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05306041static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
6042 float right)
6043{
6044 struct stream_out *out = (struct stream_out *)stream;
6045 /* Volume control for pcm playback */
6046 if (left != right) {
6047 return -EINVAL;
6048 } else {
6049 char mixer_ctl_name[128];
6050 struct audio_device *adev = out->dev;
6051 struct mixer_ctl *ctl;
6052 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
6053 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
6054 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
6055 if (!ctl) {
6056 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
6057 return -EINVAL;
6058 }
6059
6060 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
6061 int ret = mixer_ctl_set_value(ctl, 0, volume);
6062 if (ret < 0) {
6063 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
6064 return -EINVAL;
6065 }
6066
6067 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
6068
6069 return 0;
6070 }
6071}
6072
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006073static int out_set_volume(struct audio_stream_out *stream, float left,
6074 float right)
6075{
Eric Laurenta9024de2013-04-04 09:19:12 -07006076 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006077 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306078 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006079
Arun Mirpuri5d170872019-03-26 13:21:31 -07006080 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07006081 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
6082 /* only take left channel into account: the API is for stereo anyway */
6083 out->muted = (left == 0.0f);
6084 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006085 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306086 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006087 /*
6088 * Set mute or umute on HDMI passthrough stream.
6089 * Only take left channel into account.
6090 * Mute is 0 and unmute 1
6091 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306092 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306093 } else if (out->format == AUDIO_FORMAT_DSD){
6094 char mixer_ctl_name[128] = "DSD Volume";
6095 struct audio_device *adev = out->dev;
6096 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
6097
6098 if (!ctl) {
6099 ALOGE("%s: Could not get ctl for mixer cmd - %s",
6100 __func__, mixer_ctl_name);
6101 return -EINVAL;
6102 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05306103 volume[0] = (long)(AmpToDb(left));
6104 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306105 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
6106 return 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006107 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS) &&
Derek Chendf05eea2019-08-01 13:57:49 -07006108 (out->car_audio_stream == CAR_AUDIO_STREAM_MEDIA)) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07006109 ALOGD("%s: Overriding offload set volume for media bus stream", __func__);
6110 struct listnode *node = NULL;
6111 list_for_each(node, &adev->active_outputs_list) {
6112 streams_output_ctxt_t *out_ctxt = node_to_item(node,
6113 streams_output_ctxt_t,
6114 list);
6115 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
6116 out->volume_l = out_ctxt->output->volume_l;
6117 out->volume_r = out_ctxt->output->volume_r;
6118 }
6119 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08006120 pthread_mutex_lock(&out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +08006121 if (!out->a2dp_muted) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07006122 ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
6123 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08006124 pthread_mutex_unlock(&out->latch_lock);
Philippe Gravel1c9ac352019-05-28 16:08:37 -07006125 return ret;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006126 } else {
Weiyin Jiang280ea742020-09-08 20:28:22 +08006127 pthread_mutex_lock(&out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +08006128 ALOGV("%s: compress mute %d", __func__, out->a2dp_muted);
6129 if (!out->a2dp_muted)
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306130 ret = out_set_compr_volume(stream, left, right);
6131 out->volume_l = left;
6132 out->volume_r = right;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006133 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306134 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006135 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07006136 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08006137 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
6138 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Songbaddf9f2020-11-20 13:57:39 +08006139 pthread_mutex_lock(&out->latch_lock);
Aalique Grahame22e49102018-12-18 14:23:57 -08006140 if (!out->standby) {
6141 audio_extn_utils_send_app_type_gain(out->dev,
6142 out->app_type_cfg.app_type,
6143 &out->app_type_cfg.gain[0]);
Zhou Songbaddf9f2020-11-20 13:57:39 +08006144 if (!out->a2dp_muted)
6145 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08006146 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08006147 out->volume_l = left;
6148 out->volume_r = right;
Zhou Songbaddf9f2020-11-20 13:57:39 +08006149 pthread_mutex_unlock(&out->latch_lock);
Zhou Song2b8f28f2017-09-11 10:51:38 +08006150 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006151 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
6152 ALOGV("%s: MMAP set volume called", __func__);
6153 if (!out->standby)
6154 ret = out_set_mmap_volume(stream, left, right);
6155 out->volume_l = left;
6156 out->volume_r = right;
6157 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05306158 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05306159 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
6160 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Zhou Songbaddf9f2020-11-20 13:57:39 +08006161 pthread_mutex_lock(&out->latch_lock);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05306162 /* Volume control for pcm playback */
Zhou Songbaddf9f2020-11-20 13:57:39 +08006163 if (!out->standby && !out->a2dp_muted)
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05306164 ret = out_set_pcm_volume(stream, left, right);
6165 else
6166 out->apply_volume = true;
6167
6168 out->volume_l = left;
6169 out->volume_r = right;
Zhou Songbaddf9f2020-11-20 13:57:39 +08006170 pthread_mutex_unlock(&out->latch_lock);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05306171 return ret;
Derek Chenf13dd492018-11-13 14:53:51 -08006172 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
6173 ALOGV("%s: bus device set volume called", __func__);
Zhou Songbaddf9f2020-11-20 13:57:39 +08006174 pthread_mutex_lock(&out->latch_lock);
6175 if (!out->standby && !out->a2dp_muted)
Derek Chenf13dd492018-11-13 14:53:51 -08006176 ret = out_set_pcm_volume(stream, left, right);
6177 out->volume_l = left;
6178 out->volume_r = right;
Zhou Songbaddf9f2020-11-20 13:57:39 +08006179 pthread_mutex_unlock(&out->latch_lock);
Derek Chenf13dd492018-11-13 14:53:51 -08006180 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07006181 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006182
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006183 return -ENOSYS;
6184}
6185
Zhou Songc9672822017-08-16 16:01:39 +08006186static void update_frames_written(struct stream_out *out, size_t bytes)
6187{
6188 size_t bpf = 0;
6189
6190 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
6191 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
6192 bpf = 1;
6193 else if (!is_offload_usecase(out->usecase))
6194 bpf = audio_bytes_per_sample(out->format) *
6195 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08006196
6197 pthread_mutex_lock(&out->position_query_lock);
6198 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08006199 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08006200 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
6201 }
6202 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08006203}
6204
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006205int split_and_write_audio_haptic_data(struct stream_out *out,
6206 const void *buffer, size_t bytes_to_write)
6207{
6208 struct audio_device *adev = out->dev;
6209
6210 int ret = 0;
6211 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
6212 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
6213 size_t frame_size = channel_count * bytes_per_sample;
6214 size_t frame_count = bytes_to_write / frame_size;
6215
6216 bool force_haptic_path =
6217 property_get_bool("vendor.audio.test_haptic", false);
6218
6219 // extract Haptics data from Audio buffer
6220 bool alloc_haptic_buffer = false;
6221 int haptic_channel_count = adev->haptics_config.channels;
6222 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
6223 size_t audio_frame_size = frame_size - haptic_frame_size;
6224 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
6225
6226 if (adev->haptic_buffer == NULL) {
6227 alloc_haptic_buffer = true;
6228 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
6229 free(adev->haptic_buffer);
6230 adev->haptic_buffer_size = 0;
6231 alloc_haptic_buffer = true;
6232 }
6233
6234 if (alloc_haptic_buffer) {
6235 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08006236 if(adev->haptic_buffer == NULL) {
6237 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
6238 return -ENOMEM;
6239 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006240 adev->haptic_buffer_size = total_haptic_buffer_size;
6241 }
6242
6243 size_t src_index = 0, aud_index = 0, hap_index = 0;
6244 uint8_t *audio_buffer = (uint8_t *)buffer;
6245 uint8_t *haptic_buffer = adev->haptic_buffer;
6246
6247 // This is required for testing only. This works for stereo data only.
6248 // One channel is fed to audio stream and other to haptic stream for testing.
6249 if (force_haptic_path)
6250 audio_frame_size = haptic_frame_size = bytes_per_sample;
6251
6252 for (size_t i = 0; i < frame_count; i++) {
6253 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
6254 audio_frame_size);
6255 aud_index += audio_frame_size;
6256 src_index += audio_frame_size;
6257
6258 if (adev->haptic_pcm)
6259 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
6260 haptic_frame_size);
6261 hap_index += haptic_frame_size;
6262 src_index += haptic_frame_size;
6263
6264 // This is required for testing only.
6265 // Discard haptic channel data.
6266 if (force_haptic_path)
6267 src_index += haptic_frame_size;
6268 }
6269
6270 // write to audio pipeline
6271 ret = pcm_write(out->pcm, (void *)audio_buffer,
6272 frame_count * audio_frame_size);
6273
6274 // write to haptics pipeline
6275 if (adev->haptic_pcm)
6276 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
6277 frame_count * haptic_frame_size);
6278
6279 return ret;
6280}
6281
Aalique Grahame22e49102018-12-18 14:23:57 -08006282#ifdef NO_AUDIO_OUT
6283static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
6284 const void *buffer __unused, size_t bytes)
6285{
6286 struct stream_out *out = (struct stream_out *)stream;
6287
6288 /* No Output device supported other than BT for playback.
6289 * Sleep for the amount of buffer duration
6290 */
6291 lock_output_stream(out);
6292 usleep(bytes * 1000000 / audio_stream_out_frame_size(
6293 (const struct audio_stream_out *)&out->stream) /
6294 out_get_sample_rate(&out->stream.common));
6295 pthread_mutex_unlock(&out->lock);
6296 return bytes;
6297}
6298#endif
6299
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006300static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
6301 size_t bytes)
6302{
6303 struct stream_out *out = (struct stream_out *)stream;
6304 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07006305 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05306306 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006307 const size_t frame_size = audio_stream_out_frame_size(stream);
6308 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05306309 struct audio_usecase *usecase = NULL;
Meng Wang4c32fb42020-01-16 17:57:11 +08006310 uint32_t compr_passthr = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006311
Haynes Mathew George380745d2017-10-04 15:27:45 -07006312 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006313 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306314
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05006315 if (CARD_STATUS_OFFLINE == out->card_status ||
6316 POWER_POLICY_STATUS_OFFLINE == adev->out_power_policy) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08006317
Dhananjay Kumarac341582017-02-23 23:42:25 +05306318 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306319 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05306320 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
6321 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006322 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05306323 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05306324 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05306325 ALOGD(" %s: sound card is not active/SSR state", __func__);
6326 ret= -EIO;
6327 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306328 }
6329 }
6330
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306331 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05306332 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05306333 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306334 goto exit;
6335 }
6336
Haynes Mathew George16081042017-05-31 17:16:49 -07006337 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
6338 ret = -EINVAL;
6339 goto exit;
6340 }
6341
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006342 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306343 !out->is_iec61937_info_available) {
6344
6345 if (!audio_extn_passthru_is_passthrough_stream(out)) {
6346 out->is_iec61937_info_available = true;
6347 } else if (audio_extn_passthru_is_enabled()) {
6348 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05306349 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05306350
6351 if((out->format == AUDIO_FORMAT_DTS) ||
6352 (out->format == AUDIO_FORMAT_DTS_HD)) {
6353 ret = audio_extn_passthru_update_dts_stream_configuration(out,
6354 buffer, bytes);
6355 if (ret) {
6356 if (ret != -ENOSYS) {
6357 out->is_iec61937_info_available = false;
6358 ALOGD("iec61937 transmission info not yet updated retry");
6359 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306360 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05306361 /* if stream has started and after that there is
6362 * stream config change (iec transmission config)
6363 * then trigger select_device to update backend configuration.
6364 */
6365 out->stream_config_changed = true;
6366 pthread_mutex_lock(&adev->lock);
6367 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306368 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08006369 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306370 ret = -EINVAL;
6371 goto exit;
6372 }
Manish Dewangan671a4202017-08-18 17:30:46 +05306373 pthread_mutex_unlock(&adev->lock);
6374 out->stream_config_changed = false;
6375 out->is_iec61937_info_available = true;
6376 }
6377 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05306378
Meng Wang4c32fb42020-01-16 17:57:11 +08006379#ifdef AUDIO_GKI_ENABLED
6380 /* out->compr_config.codec->reserved[0] is for compr_passthr */
6381 compr_passthr = out->compr_config.codec->reserved[0];
6382#else
6383 compr_passthr = out->compr_config.codec->compr_passthr;
6384#endif
6385
Garmond Leung317cbf12017-09-13 16:20:50 -07006386 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Meng Wang4c32fb42020-01-16 17:57:11 +08006387 (compr_passthr == PASSTHROUGH) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05306388 (out->is_iec61937_info_available == true)) {
6389 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
6390 ret = -EINVAL;
6391 goto exit;
6392 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05306393 }
6394 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306395
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006396 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02006397 (audio_extn_a2dp_source_is_suspended())) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006398 if (!(compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER) ||
6399 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Zhou Songd01e7a22020-09-23 22:49:01 +08006400 if (!is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306401 ret = -EIO;
6402 goto exit;
6403 }
6404 }
6405 }
6406
Weiyin Jiangabedea32020-12-09 12:49:19 +08006407 if (is_usb_out_device_type(&out->device_list) &&
6408 !audio_extn_usb_connected(NULL)) {
6409 ret = -EIO;
6410 goto exit;
6411 }
6412
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006413 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07006414 out->standby = false;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006415 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
6416
Eric Laurent150dbfe2013-02-27 14:31:02 -08006417 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006418 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
6419 ret = voice_extn_compress_voip_start_output_stream(out);
6420 else
6421 ret = start_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006422 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006423 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07006424 out->standby = true;
Weiyin Jiangac2bae82020-07-29 17:23:53 +08006425 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006426 goto exit;
6427 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306428 out->started = 1;
Andy Hunga1f48fa2019-07-01 18:14:53 -07006429 out->last_fifo_valid = false; // we're coming out of standby, last_fifo isn't valid.
Weiyin Jiangac2bae82020-07-29 17:23:53 +08006430
6431 if ((last_known_cal_step != -1) && (adev->platform != NULL)) {
vivek mehtab72d08d2016-04-29 03:16:47 -07006432 ALOGD("%s: retry previous failed cal level set", __func__);
Weiyin Jiangac2bae82020-07-29 17:23:53 +08006433 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05306434 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07006435 }
Weiyin Jiangac2bae82020-07-29 17:23:53 +08006436 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306437
6438 if ((out->is_iec61937_info_available == true) &&
6439 (audio_extn_passthru_is_passthrough_stream(out))&&
6440 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
6441 ret = -EINVAL;
6442 goto exit;
6443 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05306444 if (out->set_dual_mono)
6445 audio_extn_send_dual_mono_mixing_coefficients(out);
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006446
Dechen Chai22768452021-07-30 09:29:16 +05306447#ifndef LINUX_ENABLED
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006448 // log startup time in ms.
6449 simple_stats_log(
6450 &out->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Dechen Chai22768452021-07-30 09:29:16 +05306451#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006452 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006453
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006454 if (adev->is_channel_status_set == false &&
6455 compare_device_type(&out->device_list,
6456 AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Alexy Josephb1379942016-01-29 15:49:38 -08006457 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05306458 adev->is_channel_status_set = true;
6459 }
6460
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05306461 if ((adev->use_old_pspd_mix_ctrl == true) &&
6462 (out->pspd_coeff_sent == false)) {
6463 /*
6464 * Need to resend pspd coefficients after stream started for
6465 * older kernel version as it does not save the coefficients
6466 * and also stream has to be started for coeff to apply.
6467 */
6468 usecase = get_usecase_from_list(adev, out->usecase);
6469 if (usecase != NULL) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05306470 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05306471 out->pspd_coeff_sent = true;
6472 }
6473 }
6474
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006475 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08006476 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006477 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006478 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006479 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
6480 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05306481 if (out->send_next_track_params && out->is_compr_metadata_avail) {
6482 ALOGD("copl(%p):send next track params in gapless", out);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08006483 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05306484 out->send_next_track_params = false;
6485 out->is_compr_metadata_avail = false;
6486 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006487 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05306488 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306489 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006490
Ashish Jain83a6cc22016-06-28 14:34:17 +05306491 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05306492 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05306493 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05306494 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006495 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05306496 return -EINVAL;
6497 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05306498 audio_format_t dst_format = out->hal_op_format;
6499 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306500
Dieter Luecking5d57def2018-09-07 14:23:37 +02006501 /* prevent division-by-zero */
6502 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
6503 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
6504 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
6505 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05306506 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006507 ATRACE_END();
6508 return -EINVAL;
6509 }
6510
Ashish Jainf1eaa582016-05-23 20:54:24 +05306511 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
6512 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
6513
Ashish Jain83a6cc22016-06-28 14:34:17 +05306514 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05306515 dst_format,
6516 buffer,
6517 src_format,
6518 frames);
6519
Ashish Jain83a6cc22016-06-28 14:34:17 +05306520 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05306521 bytes_to_write);
6522
6523 /*Convert written bytes in audio flinger format*/
6524 if (ret > 0)
6525 ret = ((ret * format_to_bitwidth_table[out->format]) /
6526 format_to_bitwidth_table[dst_format]);
6527 }
6528 } else
6529 ret = compress_write(out->compr, buffer, bytes);
6530
Zhou Songc9672822017-08-16 16:01:39 +08006531 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
6532 update_frames_written(out, bytes);
6533
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306534 if (ret < 0)
6535 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08006536 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05306537 /*msg to cb thread only if non blocking write is enabled*/
6538 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05306539 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006540 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05306541 } else if (-ENETRESET == ret) {
6542 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306543 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05306544 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05306545 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006546 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05306547 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006548 }
Ashish Jain5106d362016-05-11 19:23:33 +05306549
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05306550 /* Call compr start only when non-zero bytes of data is there to be rendered */
6551 if (!out->playback_started && ret > 0) {
6552 int status = compress_start(out->compr);
6553 if (status < 0) {
6554 ret = status;
6555 ALOGE("%s: compr start failed with err %d", __func__, errno);
6556 goto exit;
6557 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07006558 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006559 out->playback_started = 1;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006560 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006561 out->offload_state = OFFLOAD_STATE_PLAYING;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006562 pthread_mutex_unlock(&out->latch_lock);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006563
6564 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6565 popcount(out->channel_mask),
6566 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006567 }
6568 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006569 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006570 return ret;
6571 } else {
6572 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006573 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006574 if (out->muted)
6575 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006576 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
6577 __func__, frames, frame_size, bytes_to_write);
6578
Aalique Grahame22e49102018-12-18 14:23:57 -08006579 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07006580 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
6581 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
6582 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006583 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
6584 int16_t *src = (int16_t *)buffer;
6585 int16_t *dst = (int16_t *)buffer;
6586
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006587 LOG_ALWAYS_FATAL_IF(channel_count > 2 ||
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006588 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08006589 "out_write called for %s use case with wrong properties",
6590 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006591
6592 /*
6593 * FIXME: this can be removed once audio flinger mixer supports
6594 * mono output
6595 */
6596
6597 /*
6598 * Code below goes over each frame in the buffer and adds both
6599 * L and R samples and then divides by 2 to convert to mono
6600 */
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006601 if (channel_count == 2) {
6602 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
6603 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
6604 }
6605 bytes_to_write /= 2;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006606 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006607 }
Andy Hunga1f48fa2019-07-01 18:14:53 -07006608
6609 // Note: since out_get_presentation_position() is called alternating with out_write()
6610 // by AudioFlinger, we can check underruns using the prior timestamp read.
6611 // (Alternately we could check if the buffer is empty using pcm_get_htimestamp().
6612 if (out->last_fifo_valid) {
6613 // compute drain to see if there is an underrun.
6614 const int64_t current_ns = systemTime(SYSTEM_TIME_MONOTONIC); // sys call
Dhananjay Kumara4429632020-07-11 02:53:37 +05306615 int64_t time_diff_ns = current_ns - out->last_fifo_time_ns;
6616 int64_t frames_by_time =
6617 ((time_diff_ns > 0) && (time_diff_ns < (INT64_MAX / out->config.rate))) ?
6618 (time_diff_ns * out->config.rate / NANOS_PER_SECOND) : 0;
Andy Hunga1f48fa2019-07-01 18:14:53 -07006619 const int64_t underrun = frames_by_time - out->last_fifo_frames_remaining;
6620
6621 if (underrun > 0) {
Dechen Chai22768452021-07-30 09:29:16 +05306622#ifndef LINUX_ENABLED
Andy Hunga1f48fa2019-07-01 18:14:53 -07006623 simple_stats_log(&out->fifo_underruns, underrun);
Dechen Chai22768452021-07-30 09:29:16 +05306624#endif
Andy Hunga1f48fa2019-07-01 18:14:53 -07006625
6626 ALOGW("%s: underrun(%lld) "
6627 "frames_by_time(%lld) > out->last_fifo_frames_remaining(%lld)",
6628 __func__,
6629 (long long)out->fifo_underruns.n,
6630 (long long)frames_by_time,
6631 (long long)out->last_fifo_frames_remaining);
6632 }
6633 out->last_fifo_valid = false; // we're writing below, mark fifo info as stale.
6634 }
6635
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306636 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006637
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006638 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006639
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006640 if (out->config.rate)
6641 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
6642 out->config.rate;
6643
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006644 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006645 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
6646
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006647 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006648 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006649 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306650 out->convert_buffer != NULL) {
6651
6652 memcpy_by_audio_format(out->convert_buffer,
6653 out->hal_op_format,
6654 buffer,
6655 out->hal_ip_format,
6656 out->config.period_size * out->config.channels);
6657
6658 ret = pcm_write(out->pcm, out->convert_buffer,
6659 (out->config.period_size *
6660 out->config.channels *
6661 format_to_bitwidth_table[out->hal_op_format]));
6662 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05306663 /*
6664 * To avoid underrun in DSP when the application is not pumping
6665 * data at required rate, check for the no. of bytes and ignore
6666 * pcm_write if it is less than actual buffer size.
6667 * It is a work around to a change in compress VOIP driver.
6668 */
6669 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
6670 bytes < (out->config.period_size * out->config.channels *
6671 audio_bytes_per_sample(out->format))) {
6672 size_t voip_buf_size =
6673 out->config.period_size * out->config.channels *
6674 audio_bytes_per_sample(out->format);
6675 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
6676 __func__, bytes, voip_buf_size);
6677 usleep(((uint64_t)voip_buf_size - bytes) *
6678 1000000 / audio_stream_out_frame_size(stream) /
6679 out_get_sample_rate(&out->stream.common));
6680 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006681 } else {
6682 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
6683 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
6684 else
6685 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
6686 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306687 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006688
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006689 release_out_focus(out);
6690
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306691 if (ret < 0)
6692 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08006693 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05306694 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006695 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006696 }
6697
6698exit:
Zhou Songc9672822017-08-16 16:01:39 +08006699 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306700 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306701 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306702 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006703 pthread_mutex_unlock(&out->lock);
6704
6705 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006706 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08006707 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306708 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306709 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306710 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306711 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306712 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306713 out->standby = true;
6714 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306715 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006716 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
6717 /* prevent division-by-zero */
6718 uint32_t stream_size = audio_stream_out_frame_size(stream);
6719 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006720
Dieter Luecking5d57def2018-09-07 14:23:37 +02006721 if ((stream_size == 0) || (srate == 0)) {
6722 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
6723 ATRACE_END();
6724 return -EINVAL;
6725 }
6726 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
6727 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006728 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05306729 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006730 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006731 return ret;
6732 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006733 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07006734 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006735 return bytes;
6736}
6737
6738static int out_get_render_position(const struct audio_stream_out *stream,
6739 uint32_t *dsp_frames)
6740{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006741 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08006742
6743 if (dsp_frames == NULL)
6744 return -EINVAL;
6745
6746 *dsp_frames = 0;
6747 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08006748 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05306749
6750 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
6751 * this operation and adev_close_output_stream(where out gets reset).
6752 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05306753 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006754 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05306755 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006756 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05306757 return 0;
6758 }
6759
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006760 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05306761 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306762 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006763 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306764 if (ret < 0)
6765 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006766 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05306767 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006768 }
Naresh Tanniru80659832014-06-04 18:17:56 +05306769 if (-ENETRESET == ret) {
6770 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306771 out->card_status = CARD_STATUS_OFFLINE;
6772 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306773 } else if(ret < 0) {
6774 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306775 ret = -EINVAL;
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05006776 } else if (out->card_status == CARD_STATUS_OFFLINE ||
6777 adev->out_power_policy == POWER_POLICY_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05306778 /*
6779 * Handle corner case where compress session is closed during SSR
6780 * and timestamp is queried
6781 */
6782 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306783 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306784 } else if (out->prev_card_status_offline) {
6785 ALOGE("ERROR: previously sound card was offline,return error");
6786 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306787 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306788 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006789 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05306790 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306791 pthread_mutex_unlock(&out->lock);
6792 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08006793 } else if (audio_is_linear_pcm(out->format)) {
6794 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006795 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08006796 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006797 } else
6798 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006799}
6800
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006801static int out_add_audio_effect(const struct audio_stream *stream __unused,
6802 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006803{
6804 return 0;
6805}
6806
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006807static int out_remove_audio_effect(const struct audio_stream *stream __unused,
6808 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006809{
6810 return 0;
6811}
6812
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006813static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
6814 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006815{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05306816 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006817}
6818
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006819static int out_get_presentation_position(const struct audio_stream_out *stream,
6820 uint64_t *frames, struct timespec *timestamp)
6821{
6822 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05306823 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07006824 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006825
Ashish Jain5106d362016-05-11 19:23:33 +05306826 /* below piece of code is not guarded against any lock because audioFliner serializes
6827 * this operation and adev_close_output_stream( where out gets reset).
6828 */
6829 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05306830 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006831 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05306832 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
6833 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
6834 return 0;
6835 }
6836
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006837 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006838
Ashish Jain5106d362016-05-11 19:23:33 +05306839 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
6840 ret = compress_get_tstamp(out->compr, &dsp_frames,
6841 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08006842 // Adjustment accounts for A2dp encoder latency with offload usecases
6843 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006844 if (is_a2dp_out_device_type(&out->device_list)) {
yidongh0515e042017-07-06 15:00:34 +08006845 unsigned long offset =
6846 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
6847 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
6848 }
Ashish Jain5106d362016-05-11 19:23:33 +05306849 ALOGVV("%s rendered frames %ld sample_rate %d",
6850 __func__, dsp_frames, out->sample_rate);
6851 *frames = dsp_frames;
6852 if (ret < 0)
6853 ret = -errno;
6854 if (-ENETRESET == ret) {
6855 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306856 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05306857 ret = -EINVAL;
6858 } else
6859 ret = 0;
6860 /* this is the best we can do */
6861 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07006862 } else {
6863 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08006864 unsigned int avail;
6865 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
George Gao62ebc722019-07-29 16:29:44 -07006866 uint64_t signed_frames = 0;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006867 uint64_t frames_temp = 0;
George Gao62ebc722019-07-29 16:29:44 -07006868
Andy Hunga1f48fa2019-07-01 18:14:53 -07006869 if (out->kernel_buffer_size > avail) {
6870 frames_temp = out->last_fifo_frames_remaining = out->kernel_buffer_size - avail;
6871 } else {
6872 ALOGW("%s: avail:%u > kernel_buffer_size:%zu clamping!",
6873 __func__, avail, out->kernel_buffer_size);
6874 avail = out->kernel_buffer_size;
6875 frames_temp = out->last_fifo_frames_remaining = 0;
6876 }
6877 out->last_fifo_valid = true;
6878 out->last_fifo_time_ns = audio_utils_ns_from_timespec(timestamp);
6879
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006880 if (out->written >= frames_temp)
6881 signed_frames = out->written - frames_temp;
George Gao62ebc722019-07-29 16:29:44 -07006882
Andy Hunga1f48fa2019-07-01 18:14:53 -07006883 ALOGVV("%s: frames:%lld avail:%u kernel_buffer_size:%zu",
6884 __func__, (long long)signed_frames, avail, out->kernel_buffer_size);
6885
Weiyin Jiangd4633762018-03-16 12:05:03 +08006886 // This adjustment accounts for buffering after app processor.
6887 // It is based on estimated DSP latency per use case, rather than exact.
George Gao9ba8a142020-07-23 14:30:03 -07006888 frames_temp = platform_render_latency(out) *
Robert Lee58215542019-07-15 20:55:12 +08006889 out->sample_rate / 1000000LL;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006890 if (signed_frames >= frames_temp)
6891 signed_frames -= frames_temp;
Aniket Kumar Lataff613152017-07-18 18:19:21 -07006892
Weiyin Jiangd4633762018-03-16 12:05:03 +08006893 // Adjustment accounts for A2dp encoder latency with non offload usecases
6894 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006895 if (is_a2dp_out_device_type(&out->device_list)) {
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006896 frames_temp = audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000;
6897 if (signed_frames >= frames_temp)
6898 signed_frames -= frames_temp;
Weiyin Jiangd4633762018-03-16 12:05:03 +08006899 }
6900
6901 // It would be unusual for this value to be negative, but check just in case ...
George Gao62ebc722019-07-29 16:29:44 -07006902 *frames = signed_frames;
6903 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006904 }
Eric Laurenta7a33042019-07-10 16:20:22 -07006905 } else if (out->card_status == CARD_STATUS_OFFLINE ||
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05006906 adev->out_power_policy == POWER_POLICY_STATUS_OFFLINE ||
Eric Laurenta7a33042019-07-10 16:20:22 -07006907 // audioflinger still needs position updates when A2DP is suspended
Jasmine Cha5c2517f2019-09-09 11:07:28 +08006908 (is_a2dp_out_device_type(&out->device_list) && audio_extn_a2dp_source_is_suspended())) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306909 *frames = out->written;
6910 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306911 if (is_offload_usecase(out->usecase))
6912 ret = -EINVAL;
6913 else
6914 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006915 }
6916 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006917 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006918 return ret;
6919}
6920
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006921static int out_set_callback(struct audio_stream_out *stream,
6922 stream_callback_t callback, void *cookie)
6923{
6924 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006925 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006926
6927 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006928 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006929 out->client_callback = callback;
6930 out->client_cookie = cookie;
6931 if (out->adsp_hdlr_stream_handle) {
6932 ret = audio_extn_adsp_hdlr_stream_set_callback(
6933 out->adsp_hdlr_stream_handle,
6934 callback,
6935 cookie);
6936 if (ret)
6937 ALOGW("%s:adsp hdlr callback registration failed %d",
6938 __func__, ret);
6939 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006940 pthread_mutex_unlock(&out->lock);
6941 return 0;
6942}
6943
6944static int out_pause(struct audio_stream_out* stream)
6945{
6946 struct stream_out *out = (struct stream_out *)stream;
6947 int status = -ENOSYS;
6948 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006949 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006950 ALOGD("copl(%p):pause compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306951 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006952 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006953 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006954 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306955 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05306956 status = compress_pause(out->compr);
6957
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006958 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006959
Mingming Yin21854652016-04-13 11:54:02 -07006960 if (audio_extn_passthru_is_active()) {
6961 ALOGV("offload use case, pause passthru");
6962 audio_extn_passthru_on_pause(out);
6963 }
6964
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306965 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006966 audio_extn_dts_notify_playback_state(out->usecase, 0,
6967 out->sample_rate, popcount(out->channel_mask),
6968 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006969 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08006970 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006971 pthread_mutex_unlock(&out->lock);
6972 }
6973 return status;
6974}
6975
6976static int out_resume(struct audio_stream_out* stream)
6977{
6978 struct stream_out *out = (struct stream_out *)stream;
6979 int status = -ENOSYS;
6980 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006981 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006982 ALOGD("copl(%p):resume compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306983 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006984 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006985 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006986 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306987 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306988 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07006989 }
6990 if (!status) {
6991 out->offload_state = OFFLOAD_STATE_PLAYING;
6992 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306993 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006994 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6995 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006996 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08006997 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006998 pthread_mutex_unlock(&out->lock);
6999 }
7000 return status;
7001}
7002
7003static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
7004{
7005 struct stream_out *out = (struct stream_out *)stream;
7006 int status = -ENOSYS;
7007 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07007008 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007009 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007010 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
7011 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
7012 else
7013 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
7014 pthread_mutex_unlock(&out->lock);
7015 }
7016 return status;
7017}
7018
7019static int out_flush(struct audio_stream_out* stream)
7020{
7021 struct stream_out *out = (struct stream_out *)stream;
7022 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07007023 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07007024 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007025 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08007026 pthread_mutex_lock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07007027 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
Gautam Manam14c198b2020-12-24 14:08:04 +05307028 pthread_mutex_unlock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07007029 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07007030 } else {
7031 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
Gautam Manam14c198b2020-12-24 14:08:04 +05307032 pthread_mutex_unlock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07007033 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08007034 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007035 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07007036 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007037 return 0;
7038 }
7039 return -ENOSYS;
7040}
7041
Haynes Mathew George16081042017-05-31 17:16:49 -07007042static int out_stop(const struct audio_stream_out* stream)
7043{
7044 struct stream_out *out = (struct stream_out *)stream;
7045 struct audio_device *adev = out->dev;
7046 int ret = -ENOSYS;
7047
7048 ALOGV("%s", __func__);
7049 pthread_mutex_lock(&adev->lock);
7050 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
7051 out->playback_started && out->pcm != NULL) {
7052 pcm_stop(out->pcm);
7053 ret = stop_output_stream(out);
7054 out->playback_started = false;
7055 }
7056 pthread_mutex_unlock(&adev->lock);
7057 return ret;
7058}
7059
7060static int out_start(const struct audio_stream_out* stream)
7061{
7062 struct stream_out *out = (struct stream_out *)stream;
7063 struct audio_device *adev = out->dev;
7064 int ret = -ENOSYS;
7065
7066 ALOGV("%s", __func__);
7067 pthread_mutex_lock(&adev->lock);
7068 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
7069 !out->playback_started && out->pcm != NULL) {
7070 ret = start_output_stream(out);
7071 if (ret == 0) {
7072 out->playback_started = true;
7073 }
7074 }
7075 pthread_mutex_unlock(&adev->lock);
7076 return ret;
7077}
7078
7079/*
7080 * Modify config->period_count based on min_size_frames
7081 */
7082static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
7083{
7084 int periodCountRequested = (min_size_frames + config->period_size - 1)
7085 / config->period_size;
7086 int periodCount = MMAP_PERIOD_COUNT_MIN;
7087
7088 ALOGV("%s original config.period_size = %d config.period_count = %d",
7089 __func__, config->period_size, config->period_count);
7090
7091 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
7092 periodCount *= 2;
7093 }
7094 config->period_count = periodCount;
7095
7096 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
7097}
7098
Phil Burkfe17efd2019-03-25 10:23:35 -07007099// Read offset for the positional timestamp from a persistent vendor property.
7100// This is to workaround apparent inaccuracies in the timing information that
7101// is used by the AAudio timing model. The inaccuracies can cause glitches.
7102static int64_t get_mmap_out_time_offset() {
7103 const int32_t kDefaultOffsetMicros = 0;
7104 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08007105 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07007106 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
7107 return mmap_time_offset_micros * (int64_t)1000;
7108}
7109
Haynes Mathew George16081042017-05-31 17:16:49 -07007110static int out_create_mmap_buffer(const struct audio_stream_out *stream,
7111 int32_t min_size_frames,
7112 struct audio_mmap_buffer_info *info)
7113{
7114 struct stream_out *out = (struct stream_out *)stream;
7115 struct audio_device *adev = out->dev;
7116 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07007117 unsigned int offset1 = 0;
7118 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007119 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07007120 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007121 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07007122
Arun Mirpuri5d170872019-03-26 13:21:31 -07007123 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05307124 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07007125 pthread_mutex_lock(&adev->lock);
7126
Sharad Sanglec6f32552018-05-04 16:15:38 +05307127 if (CARD_STATUS_OFFLINE == out->card_status ||
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05007128 CARD_STATUS_OFFLINE == adev->card_status ||
7129 POWER_POLICY_STATUS_OFFLINE == adev->out_power_policy) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307130 ALOGW("out->card_status or adev->card_status offline, try again");
7131 ret = -EIO;
7132 goto exit;
7133 }
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307134 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07007135 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
7136 ret = -EINVAL;
7137 goto exit;
7138 }
7139 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
7140 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
7141 ret = -ENOSYS;
7142 goto exit;
7143 }
7144 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
7145 if (out->pcm_device_id < 0) {
7146 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
7147 __func__, out->pcm_device_id, out->usecase);
7148 ret = -EINVAL;
7149 goto exit;
7150 }
7151
7152 adjust_mmap_period_count(&out->config, min_size_frames);
7153
Arun Mirpuri5d170872019-03-26 13:21:31 -07007154 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07007155 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
7156 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
7157 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307158 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307159 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7160 out->card_status = CARD_STATUS_OFFLINE;
7161 adev->card_status = CARD_STATUS_OFFLINE;
7162 ret = -EIO;
7163 goto exit;
7164 }
7165
Haynes Mathew George16081042017-05-31 17:16:49 -07007166 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
7167 step = "open";
7168 ret = -ENODEV;
7169 goto exit;
7170 }
7171 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
7172 if (ret < 0) {
7173 step = "begin";
7174 goto exit;
7175 }
juyuchen626833d2019-06-04 16:48:02 +08007176
7177 info->flags = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007178 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07007179 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07007180 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07007181 ret = platform_get_mmap_data_fd(adev->platform,
7182 out->pcm_device_id, 0 /*playback*/,
7183 &info->shared_memory_fd,
7184 &mmap_size);
7185 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07007186 // Fall back to non exclusive mode
7187 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
7188 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07007189 out->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
7190 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, out->mmap_shared_memory_fd);
7191
Arun Mirpuri5d170872019-03-26 13:21:31 -07007192 if (mmap_size < buffer_size) {
7193 step = "mmap";
7194 goto exit;
7195 }
juyuchen626833d2019-06-04 16:48:02 +08007196 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07007197 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007198 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07007199 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07007200
7201 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
7202 if (ret < 0) {
7203 step = "commit";
7204 goto exit;
7205 }
7206
Phil Burkfe17efd2019-03-25 10:23:35 -07007207 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
7208
Haynes Mathew George16081042017-05-31 17:16:49 -07007209 out->standby = false;
7210 ret = 0;
7211
Arun Mirpuri5d170872019-03-26 13:21:31 -07007212 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07007213 __func__, info->shared_memory_address, info->buffer_size_frames);
7214
7215exit:
7216 if (ret != 0) {
7217 if (out->pcm == NULL) {
7218 ALOGE("%s: %s - %d", __func__, step, ret);
7219 } else {
7220 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
7221 pcm_close(out->pcm);
7222 out->pcm = NULL;
7223 }
7224 }
7225 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05307226 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07007227 return ret;
7228}
7229
7230static int out_get_mmap_position(const struct audio_stream_out *stream,
7231 struct audio_mmap_position *position)
7232{
7233 struct stream_out *out = (struct stream_out *)stream;
7234 ALOGVV("%s", __func__);
7235 if (position == NULL) {
7236 return -EINVAL;
7237 }
7238 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08007239 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07007240 return -ENOSYS;
7241 }
7242 if (out->pcm == NULL) {
7243 return -ENOSYS;
7244 }
7245
7246 struct timespec ts = { 0, 0 };
7247 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
7248 if (ret < 0) {
7249 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
7250 return ret;
7251 }
Phil Burkfe17efd2019-03-25 10:23:35 -07007252 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7253 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07007254 return 0;
7255}
7256
7257
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007258/** audio_stream_in implementation **/
7259static uint32_t in_get_sample_rate(const struct audio_stream *stream)
7260{
7261 struct stream_in *in = (struct stream_in *)stream;
7262
7263 return in->config.rate;
7264}
7265
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007266static int in_set_sample_rate(struct audio_stream *stream __unused,
7267 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007268{
7269 return -ENOSYS;
7270}
7271
7272static size_t in_get_buffer_size(const struct audio_stream *stream)
7273{
7274 struct stream_in *in = (struct stream_in *)stream;
7275
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007276 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
7277 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07007278 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
Raghu Bankapur37cbf382022-12-01 09:30:00 +05307279 return audio_extn_compr_cap_get_buffer_size(pcm_format_to_audio_format(in->config.format));
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307280 else if(audio_extn_cin_attached_usecase(in))
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307281 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007282
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007283 return in->config.period_size * in->af_period_multiplier *
7284 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007285}
7286
7287static uint32_t in_get_channels(const struct audio_stream *stream)
7288{
7289 struct stream_in *in = (struct stream_in *)stream;
7290
7291 return in->channel_mask;
7292}
7293
7294static audio_format_t in_get_format(const struct audio_stream *stream)
7295{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007296 struct stream_in *in = (struct stream_in *)stream;
7297
7298 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007299}
7300
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007301static int in_set_format(struct audio_stream *stream __unused,
7302 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007303{
7304 return -ENOSYS;
7305}
7306
7307static int in_standby(struct audio_stream *stream)
7308{
7309 struct stream_in *in = (struct stream_in *)stream;
7310 struct audio_device *adev = in->dev;
7311 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307312 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
7313 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07007314 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307315
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007316 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007317 if (!in->standby && in->is_st_session) {
7318 ALOGD("%s: sound trigger pcm stop lab", __func__);
7319 audio_extn_sound_trigger_stop_lab(in);
George Gao3018ede2019-10-23 13:23:00 -07007320 if (adev->num_va_sessions > 0)
7321 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007322 in->standby = 1;
7323 }
7324
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007325 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007326 if (adev->adm_deregister_stream)
7327 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
7328
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08007329 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007330 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08007331 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08007332 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08007333 voice_extn_compress_voip_close_input_stream(stream);
7334 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07007335 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
7336 do_stop = in->capture_started;
7337 in->capture_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07007338 if (in->mmap_shared_memory_fd >= 0) {
7339 ALOGV("%s: closing mmap_shared_memory_fd = %d",
7340 __func__, in->mmap_shared_memory_fd);
7341 close(in->mmap_shared_memory_fd);
7342 in->mmap_shared_memory_fd = -1;
7343 }
Zhou Songa8895042016-07-05 17:54:22 +08007344 } else {
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307345 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05307346 audio_extn_cin_close_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08007347 }
7348
Arun Mirpuri5d170872019-03-26 13:21:31 -07007349 if (in->pcm) {
7350 ATRACE_BEGIN("pcm_in_close");
7351 pcm_close(in->pcm);
7352 ATRACE_END();
7353 in->pcm = NULL;
7354 }
7355
Carter Hsu2e429db2019-05-14 18:50:52 +08007356 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08007357 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08007358
George Gao3018ede2019-10-23 13:23:00 -07007359 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
7360 if (adev->num_va_sessions > 0)
7361 adev->num_va_sessions--;
7362 }
Quinn Malef6050362019-01-30 15:55:40 -08007363
Eric Laurent150dbfe2013-02-27 14:31:02 -08007364 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007365 }
7366 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07007367 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007368 return status;
7369}
7370
Aalique Grahame22e49102018-12-18 14:23:57 -08007371static int in_dump(const struct audio_stream *stream,
7372 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007373{
Aalique Grahame22e49102018-12-18 14:23:57 -08007374 struct stream_in *in = (struct stream_in *)stream;
7375
7376 // We try to get the lock for consistency,
7377 // but it isn't necessary for these variables.
7378 // If we're not in standby, we may be blocked on a read.
7379 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
7380 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
7381 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
7382 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
Dechen Chai22768452021-07-30 09:29:16 +05307383#ifndef LINUX_ENABLED
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007384 char buffer[256]; // for statistics formatting
7385 if (in->start_latency_ms.n > 0) {
7386 simple_stats_to_string(&in->start_latency_ms, buffer, sizeof(buffer));
7387 dprintf(fd, " Start latency ms: %s\n", buffer);
7388 }
Dechen Chai22768452021-07-30 09:29:16 +05307389#endif
Aalique Grahame22e49102018-12-18 14:23:57 -08007390 if (locked) {
7391 pthread_mutex_unlock(&in->lock);
7392 }
Dechen Chai22768452021-07-30 09:29:16 +05307393#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -08007394 // dump error info
7395 (void)error_log_dump(
7396 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Dechen Chai22768452021-07-30 09:29:16 +05307397#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007398 return 0;
7399}
7400
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307401static void in_snd_mon_cb(void * stream, struct str_parms * parms)
7402{
7403 if (!stream || !parms)
7404 return;
7405
7406 struct stream_in *in = (struct stream_in *)stream;
7407 struct audio_device *adev = in->dev;
7408
7409 card_status_t status;
7410 int card;
7411 if (parse_snd_card_status(parms, &card, &status) < 0)
7412 return;
7413
7414 pthread_mutex_lock(&adev->lock);
7415 bool valid_cb = (card == adev->snd_card);
7416 pthread_mutex_unlock(&adev->lock);
7417
7418 if (!valid_cb)
7419 return;
7420
7421 lock_input_stream(in);
7422 if (in->card_status != status)
7423 in->card_status = status;
7424 pthread_mutex_unlock(&in->lock);
7425
7426 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
7427 use_case_table[in->usecase],
7428 status == CARD_STATUS_OFFLINE ? "offline" : "online");
7429
7430 // a better solution would be to report error back to AF and let
7431 // it put the stream to standby
7432 if (status == CARD_STATUS_OFFLINE)
7433 in_standby(&in->stream.common);
7434
7435 return;
7436}
7437
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007438int route_input_stream(struct stream_in *in,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007439 struct listnode *devices,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007440 audio_source_t source)
7441{
7442 struct audio_device *adev = in->dev;
7443 int ret = 0;
7444
7445 lock_input_stream(in);
7446 pthread_mutex_lock(&adev->lock);
7447
7448 /* no audio source uses val == 0 */
7449 if ((in->source != source) && (source != AUDIO_SOURCE_DEFAULT)) {
7450 in->source = source;
7451 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
7452 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
7453 (voice_extn_compress_voip_is_format_supported(in->format)) &&
7454 (in->config.rate == 8000 || in->config.rate == 16000 ||
7455 in->config.rate == 32000 || in->config.rate == 48000 ) &&
7456 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
7457 ret = voice_extn_compress_voip_open_input_stream(in);
7458 if (ret != 0) {
7459 ALOGE("%s: Compress voip input cannot be opened, error:%d",
7460 __func__, ret);
7461 }
7462 }
7463 }
7464
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007465 if (!compare_devices(&in->device_list, devices) && !list_empty(devices) &&
7466 is_audio_in_device_type(devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007467 // Workaround: If routing to an non existing usb device, fail gracefully
7468 // The routing request will otherwise block during 10 second
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007469 struct str_parms *usb_addr =
7470 str_parms_create_str(get_usb_device_address(devices));
7471 if (is_usb_in_device_type(devices) && usb_addr &&
Weiyin Jiangabedea32020-12-09 12:49:19 +08007472 !audio_extn_usb_connected(NULL)) {
7473 ALOGW("%s: ignoring rerouting to non existing USB", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007474 ret = -ENOSYS;
7475 } else {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007476 /* If recording is in progress, change the tx device to new device */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007477 assign_devices(&in->device_list, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007478 if (!in->standby && !in->is_st_session) {
7479 ALOGV("update input routing change");
7480 // inform adm before actual routing to prevent glitches.
7481 if (adev->adm_on_routing_change) {
7482 adev->adm_on_routing_change(adev->adm_data,
7483 in->capture_handle);
7484 ret = select_devices(adev, in->usecase);
7485 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7486 adev->adm_routing_changed = true;
7487 }
7488 }
7489 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007490 if (usb_addr)
7491 str_parms_destroy(usb_addr);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007492 }
7493 pthread_mutex_unlock(&adev->lock);
7494 pthread_mutex_unlock(&in->lock);
7495
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07007496 ALOGV("%s: exit: status(%d)", __func__, ret);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007497 return ret;
7498}
7499
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007500static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
7501{
7502 struct stream_in *in = (struct stream_in *)stream;
7503 struct audio_device *adev = in->dev;
7504 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007505 char value[32];
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307506 int err = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007507
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307508 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007509 parms = str_parms_create_str(kvpairs);
7510
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307511 if (!parms)
7512 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007513 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08007514 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007515
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307516 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
7517 if (err >= 0) {
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307518 strlcpy(in->profile, value, sizeof(in->profile));
7519 ALOGV("updating stream profile with value '%s'", in->profile);
7520 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
7521 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007522 &in->device_list, in->flags, in->format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307523 in->sample_rate, in->bit_width,
7524 in->profile, &in->app_type_cfg);
7525 }
7526
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007527 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08007528 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007529
7530 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307531error:
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307532 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007533}
7534
7535static char* in_get_parameters(const struct audio_stream *stream,
7536 const char *keys)
7537{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007538 struct stream_in *in = (struct stream_in *)stream;
7539 struct str_parms *query = str_parms_create_str(keys);
7540 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007541 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007542
7543 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08007544 if (reply) {
7545 str_parms_destroy(reply);
7546 }
7547 if (query) {
7548 str_parms_destroy(query);
7549 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007550 ALOGE("in_get_parameters: failed to create query or reply");
7551 return NULL;
7552 }
7553
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007554 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007555
7556 voice_extn_in_get_parameters(in, query, reply);
7557
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007558 stream_get_parameter_channels(query, reply,
7559 &in->supported_channel_masks[0]);
7560 stream_get_parameter_formats(query, reply,
7561 &in->supported_formats[0]);
7562 stream_get_parameter_rates(query, reply,
7563 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007564 str = str_parms_to_str(reply);
7565 str_parms_destroy(query);
7566 str_parms_destroy(reply);
7567
7568 ALOGV("%s: exit: returns - %s", __func__, str);
7569 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007570}
7571
Aalique Grahame22e49102018-12-18 14:23:57 -08007572static int in_set_gain(struct audio_stream_in *stream,
7573 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007574{
Aalique Grahame22e49102018-12-18 14:23:57 -08007575 struct stream_in *in = (struct stream_in *)stream;
7576 char mixer_ctl_name[128];
7577 struct mixer_ctl *ctl;
7578 int ctl_value;
7579
7580 ALOGV("%s: gain %f", __func__, gain);
7581
7582 if (stream == NULL)
7583 return -EINVAL;
7584
7585 /* in_set_gain() only used to silence MMAP capture for now */
7586 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
7587 return -ENOSYS;
7588
7589 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
7590
7591 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
7592 if (!ctl) {
7593 ALOGW("%s: Could not get ctl for mixer cmd - %s",
7594 __func__, mixer_ctl_name);
7595 return -ENOSYS;
7596 }
7597
7598 if (gain < RECORD_GAIN_MIN)
7599 gain = RECORD_GAIN_MIN;
7600 else if (gain > RECORD_GAIN_MAX)
7601 gain = RECORD_GAIN_MAX;
7602 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
7603
7604 mixer_ctl_set_value(ctl, 0, ctl_value);
7605
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007606 return 0;
7607}
7608
7609static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
7610 size_t bytes)
7611{
7612 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05307613
7614 if (in == NULL) {
7615 ALOGE("%s: stream_in ptr is NULL", __func__);
7616 return -EINVAL;
7617 }
7618
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007619 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05307620 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307621 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007622
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007623 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05307624
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007625 if (in->is_st_session) {
7626 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
7627 /* Read from sound trigger HAL */
7628 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08007629 if (in->standby) {
George Gao3018ede2019-10-23 13:23:00 -07007630 if (adev->num_va_sessions < UINT_MAX)
7631 adev->num_va_sessions++;
Quinn Malef6050362019-01-30 15:55:40 -08007632 in->standby = 0;
7633 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007634 pthread_mutex_unlock(&in->lock);
7635 return bytes;
7636 }
7637
Haynes Mathew George16081042017-05-31 17:16:49 -07007638 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
7639 ret = -ENOSYS;
7640 goto exit;
7641 }
7642
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007643 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
7644 !in->standby && adev->adm_routing_changed) {
7645 ret = -ENOSYS;
7646 goto exit;
7647 }
7648
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007649 if (in->standby) {
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007650 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
7651
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007652 pthread_mutex_lock(&adev->lock);
7653 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
7654 ret = voice_extn_compress_voip_start_input_stream(in);
7655 else
7656 ret = start_input_stream(in);
George Gao3018ede2019-10-23 13:23:00 -07007657 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
7658 if (adev->num_va_sessions < UINT_MAX)
7659 adev->num_va_sessions++;
7660 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007661 pthread_mutex_unlock(&adev->lock);
7662 if (ret != 0) {
7663 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007664 }
7665 in->standby = 0;
Dechen Chai22768452021-07-30 09:29:16 +05307666#ifndef LINUX_ENABLED
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007667 // log startup time in ms.
7668 simple_stats_log(
7669 &in->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Dechen Chai22768452021-07-30 09:29:16 +05307670#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007671 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007672
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05307673 /* Avoid read if capture_stopped is set */
7674 if (android_atomic_acquire_load(&(in->capture_stopped)) > 0) {
7675 ALOGD("%s: force stopped catpure session, ignoring read request", __func__);
7676 ret = -EINVAL;
7677 goto exit;
7678 }
7679
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007680 // what's the duration requested by the client?
7681 long ns = 0;
7682
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307683 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007684 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
7685 in->config.rate;
7686
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007687 ret = request_in_focus(in, ns);
7688 if (ret != 0)
7689 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007690 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007691
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307692 if (audio_extn_cin_attached_usecase(in)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307693 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
7694 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307695 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007696 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307697 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07007698 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007699 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007700 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07007701 } else if (audio_extn_ffv_get_stream() == in) {
7702 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307703 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007704 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307705 /* data from DSP comes in 24_8 format, convert it to 8_24 */
7706 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
7707 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
7708 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307709 ret = -EINVAL;
7710 goto exit;
7711 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307712 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307713 ret = -errno;
7714 }
7715 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307716 /* bytes read is always set to bytes for non compress usecases */
7717 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007718 }
7719
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007720 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007721
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007722 /*
Quinn Malef6050362019-01-30 15:55:40 -08007723 * Instead of writing zeroes here, we could trust the hardware to always
7724 * provide zeroes when muted. This is also muted with voice recognition
7725 * usecases so that other clients do not have access to voice recognition
7726 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007727 */
Quinn Malef6050362019-01-30 15:55:40 -08007728 if ((ret == 0 && voice_get_mic_mute(adev) &&
7729 !voice_is_in_call_rec_stream(in) &&
Zhou Song62ea0282020-03-22 19:53:01 +08007730 (in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY &&
Manoj Kumar N D54cab152023-01-27 16:41:55 +05307731 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY2 &&
7732 in->source != AUDIO_SOURCE_FM_TUNER &&
7733 !is_single_device_type_equal(&in->device_list, AUDIO_DEVICE_IN_FM_TUNER))) ||
Quinn Malef6050362019-01-30 15:55:40 -08007734 (adev->num_va_sessions &&
7735 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
7736 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
7737 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007738 memset(buffer, 0, bytes);
7739
7740exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307741 frame_size = audio_stream_in_frame_size(stream);
7742 if (frame_size > 0)
7743 in->frames_read += bytes_read/frame_size;
7744
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007745 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307746 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007747 pthread_mutex_unlock(&in->lock);
7748
7749 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307750 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307751 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307752 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307753 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307754 in->standby = true;
7755 }
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307756 if (!audio_extn_cin_attached_usecase(in)) {
Sharad Sangled17c9122017-03-20 15:58:52 +05307757 bytes_read = bytes;
7758 memset(buffer, 0, bytes);
7759 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007760 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007761 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7762 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007763 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05307764 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05307765 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007766 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307767 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007768}
7769
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007770static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007771{
7772 return 0;
7773}
7774
Aalique Grahame22e49102018-12-18 14:23:57 -08007775static int in_get_capture_position(const struct audio_stream_in *stream,
7776 int64_t *frames, int64_t *time)
7777{
7778 if (stream == NULL || frames == NULL || time == NULL) {
7779 return -EINVAL;
7780 }
7781 struct stream_in *in = (struct stream_in *)stream;
7782 int ret = -ENOSYS;
7783
7784 lock_input_stream(in);
7785 // note: ST sessions do not close the alsa pcm driver synchronously
7786 // on standby. Therefore, we may return an error even though the
7787 // pcm stream is still opened.
7788 if (in->standby) {
7789 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
7790 "%s stream in standby but pcm not NULL for non ST session", __func__);
7791 goto exit;
7792 }
7793 if (in->pcm) {
7794 struct timespec timestamp;
7795 unsigned int avail;
7796 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
7797 *frames = in->frames_read + avail;
Robert Lee58215542019-07-15 20:55:12 +08007798 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec
George Gao9ba8a142020-07-23 14:30:03 -07007799 - platform_capture_latency(in) * 1000LL;
Kakanaboina Ramanjaneyulu8cedb092021-03-15 15:55:29 +05307800 //Adjustment accounts for A2dp decoder latency for recording usecase
7801 // Note: decoder latency is returned in ms, while platform_capture_latency in ns.
7802 if (is_a2dp_in_device_type(&in->device_list))
7803 *time -= audio_extn_a2dp_get_decoder_latency() * 1000000LL;
Aalique Grahame22e49102018-12-18 14:23:57 -08007804 ret = 0;
7805 }
7806 }
7807exit:
7808 pthread_mutex_unlock(&in->lock);
7809 return ret;
7810}
7811
Carter Hsu2e429db2019-05-14 18:50:52 +08007812static int in_update_effect_list(bool add, effect_handle_t effect,
7813 struct listnode *head)
7814{
7815 struct listnode *node;
7816 struct in_effect_list *elist = NULL;
7817 struct in_effect_list *target = NULL;
7818 int ret = 0;
7819
7820 if (!head)
7821 return ret;
7822
7823 list_for_each(node, head) {
7824 elist = node_to_item(node, struct in_effect_list, list);
7825 if (elist->handle == effect) {
7826 target = elist;
7827 break;
7828 }
7829 }
7830
7831 if (add) {
7832 if (target) {
7833 ALOGD("effect %p already exist", effect);
7834 return ret;
7835 }
7836
7837 target = (struct in_effect_list *)
7838 calloc(1, sizeof(struct in_effect_list));
7839
7840 if (!target) {
7841 ALOGE("%s:fail to allocate memory", __func__);
7842 return -ENOMEM;
7843 }
7844
7845 target->handle = effect;
7846 list_add_tail(head, &target->list);
7847 } else {
7848 if (target) {
7849 list_remove(&target->list);
7850 free(target);
7851 }
7852 }
7853
7854 return ret;
7855}
7856
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007857static int add_remove_audio_effect(const struct audio_stream *stream,
7858 effect_handle_t effect,
7859 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007860{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007861 struct stream_in *in = (struct stream_in *)stream;
7862 int status = 0;
7863 effect_descriptor_t desc;
7864
7865 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007866 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
7867
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007868 if (status != 0)
7869 return status;
7870
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007871 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007872 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08007873 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08007874 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
7875 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007876 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08007877
7878 in_update_effect_list(enable, effect, &in->aec_list);
7879 enable = !list_empty(&in->aec_list);
7880 if (enable == in->enable_aec)
7881 goto exit;
7882
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007883 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007884 ALOGD("AEC enable %d", enable);
7885
Aalique Grahame22e49102018-12-18 14:23:57 -08007886 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7887 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
7888 in->dev->enable_voicerx = enable;
7889 struct audio_usecase *usecase;
7890 struct listnode *node;
7891 list_for_each(node, &in->dev->usecase_list) {
7892 usecase = node_to_item(node, struct audio_usecase, list);
7893 if (usecase->type == PCM_PLAYBACK)
7894 select_devices(in->dev, usecase->id);
7895 }
7896 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007897 if (!in->standby) {
7898 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
7899 select_devices(in->dev, in->usecase);
7900 }
7901
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007902 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007903 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
7904
7905 in_update_effect_list(enable, effect, &in->ns_list);
7906 enable = !list_empty(&in->ns_list);
7907 if (enable == in->enable_ns)
7908 goto exit;
7909
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007910 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007911 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007912 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08007913 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Ramu Gottipatifa5be522021-12-28 19:18:21 +05307914 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
kunleizd96526c2018-04-09 11:12:32 +08007915 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007916 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
7917 select_devices(in->dev, in->usecase);
7918 } else
7919 select_devices(in->dev, in->usecase);
7920 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007921 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007922exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007923 pthread_mutex_unlock(&in->dev->lock);
7924 pthread_mutex_unlock(&in->lock);
7925
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007926 return 0;
7927}
7928
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007929static int in_add_audio_effect(const struct audio_stream *stream,
7930 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007931{
Eric Laurent994a6932013-07-17 11:51:42 -07007932 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007933 return add_remove_audio_effect(stream, effect, true);
7934}
7935
7936static int in_remove_audio_effect(const struct audio_stream *stream,
7937 effect_handle_t effect)
7938{
Eric Laurent994a6932013-07-17 11:51:42 -07007939 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007940 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007941}
7942
Haynes Mathew George16081042017-05-31 17:16:49 -07007943static int in_stop(const struct audio_stream_in* stream)
7944{
7945 struct stream_in *in = (struct stream_in *)stream;
7946 struct audio_device *adev = in->dev;
7947
7948 int ret = -ENOSYS;
7949 ALOGV("%s", __func__);
7950 pthread_mutex_lock(&adev->lock);
7951 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7952 in->capture_started && in->pcm != NULL) {
7953 pcm_stop(in->pcm);
7954 ret = stop_input_stream(in);
7955 in->capture_started = false;
7956 }
7957 pthread_mutex_unlock(&adev->lock);
7958 return ret;
7959}
7960
7961static int in_start(const struct audio_stream_in* stream)
7962{
7963 struct stream_in *in = (struct stream_in *)stream;
7964 struct audio_device *adev = in->dev;
7965 int ret = -ENOSYS;
7966
7967 ALOGV("%s in %p", __func__, in);
7968 pthread_mutex_lock(&adev->lock);
7969 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7970 !in->capture_started && in->pcm != NULL) {
7971 if (!in->capture_started) {
7972 ret = start_input_stream(in);
7973 if (ret == 0) {
7974 in->capture_started = true;
7975 }
7976 }
7977 }
7978 pthread_mutex_unlock(&adev->lock);
7979 return ret;
7980}
7981
Phil Burke0a86d12019-02-16 22:28:11 -08007982// Read offset for the positional timestamp from a persistent vendor property.
7983// This is to workaround apparent inaccuracies in the timing information that
7984// is used by the AAudio timing model. The inaccuracies can cause glitches.
7985static int64_t in_get_mmap_time_offset() {
7986 const int32_t kDefaultOffsetMicros = 0;
7987 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08007988 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08007989 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
7990 return mmap_time_offset_micros * (int64_t)1000;
7991}
7992
Haynes Mathew George16081042017-05-31 17:16:49 -07007993static int in_create_mmap_buffer(const struct audio_stream_in *stream,
7994 int32_t min_size_frames,
7995 struct audio_mmap_buffer_info *info)
7996{
7997 struct stream_in *in = (struct stream_in *)stream;
7998 struct audio_device *adev = in->dev;
7999 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07008000 unsigned int offset1 = 0;
8001 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07008002 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07008003 uint32_t mmap_size = 0;
8004 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07008005
8006 pthread_mutex_lock(&adev->lock);
8007 ALOGV("%s in %p", __func__, in);
8008
Sharad Sanglec6f32552018-05-04 16:15:38 +05308009 if (CARD_STATUS_OFFLINE == in->card_status||
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05008010 CARD_STATUS_OFFLINE == adev->card_status ||
8011 POWER_POLICY_STATUS_OFFLINE == adev->in_power_policy) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05308012 ALOGW("in->card_status or adev->card_status offline, try again");
8013 ret = -EIO;
8014 goto exit;
8015 }
8016
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05308017 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07008018 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
8019 ret = -EINVAL;
8020 goto exit;
8021 }
8022 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
8023 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
8024 ALOGV("%s in %p", __func__, in);
8025 ret = -ENOSYS;
8026 goto exit;
8027 }
8028 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
8029 if (in->pcm_device_id < 0) {
8030 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
8031 __func__, in->pcm_device_id, in->usecase);
8032 ret = -EINVAL;
8033 goto exit;
8034 }
8035
8036 adjust_mmap_period_count(&in->config, min_size_frames);
8037
8038 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
8039 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
8040 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
8041 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05308042 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05308043 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
8044 in->card_status = CARD_STATUS_OFFLINE;
8045 adev->card_status = CARD_STATUS_OFFLINE;
8046 ret = -EIO;
8047 goto exit;
8048 }
8049
Haynes Mathew George16081042017-05-31 17:16:49 -07008050 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
8051 step = "open";
8052 ret = -ENODEV;
8053 goto exit;
8054 }
8055
8056 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
8057 if (ret < 0) {
8058 step = "begin";
8059 goto exit;
8060 }
Haynes Mathew George16081042017-05-31 17:16:49 -07008061
juyuchen626833d2019-06-04 16:48:02 +08008062 info->flags = 0;
Arun Mirpuri5d170872019-03-26 13:21:31 -07008063 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
8064 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
8065 info->burst_size_frames = in->config.period_size;
8066 ret = platform_get_mmap_data_fd(adev->platform,
8067 in->pcm_device_id, 1 /*capture*/,
8068 &info->shared_memory_fd,
8069 &mmap_size);
8070 if (ret < 0) {
8071 // Fall back to non exclusive mode
8072 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
8073 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07008074 in->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
8075 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, in->mmap_shared_memory_fd);
8076
Arun Mirpuri5d170872019-03-26 13:21:31 -07008077 if (mmap_size < buffer_size) {
8078 step = "mmap";
8079 goto exit;
8080 }
juyuchen626833d2019-06-04 16:48:02 +08008081 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Arun Mirpuri5d170872019-03-26 13:21:31 -07008082 }
8083
8084 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07008085
8086 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
8087 if (ret < 0) {
8088 step = "commit";
8089 goto exit;
8090 }
8091
Phil Burke0a86d12019-02-16 22:28:11 -08008092 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
8093
Haynes Mathew George16081042017-05-31 17:16:49 -07008094 in->standby = false;
8095 ret = 0;
8096
8097 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
8098 __func__, info->shared_memory_address, info->buffer_size_frames);
8099
8100exit:
8101 if (ret != 0) {
8102 if (in->pcm == NULL) {
8103 ALOGE("%s: %s - %d", __func__, step, ret);
8104 } else {
8105 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
8106 pcm_close(in->pcm);
8107 in->pcm = NULL;
8108 }
8109 }
8110 pthread_mutex_unlock(&adev->lock);
8111 return ret;
8112}
8113
8114static int in_get_mmap_position(const struct audio_stream_in *stream,
8115 struct audio_mmap_position *position)
8116{
8117 struct stream_in *in = (struct stream_in *)stream;
8118 ALOGVV("%s", __func__);
8119 if (position == NULL) {
8120 return -EINVAL;
8121 }
Gautam Manam34d1f542021-01-05 20:24:37 +05308122 lock_input_stream(in);
Haynes Mathew George16081042017-05-31 17:16:49 -07008123 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
Gautam Manam34d1f542021-01-05 20:24:37 +05308124 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07008125 return -ENOSYS;
8126 }
8127 if (in->pcm == NULL) {
Gautam Manam34d1f542021-01-05 20:24:37 +05308128 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07008129 return -ENOSYS;
8130 }
8131 struct timespec ts = { 0, 0 };
8132 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
8133 if (ret < 0) {
8134 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
Gautam Manam34d1f542021-01-05 20:24:37 +05308135 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07008136 return ret;
8137 }
Phil Burke0a86d12019-02-16 22:28:11 -08008138 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
8139 + in->mmap_time_offset_nanos;
Gautam Manam34d1f542021-01-05 20:24:37 +05308140 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07008141 return 0;
8142}
8143
Naresh Tannirudcb47c52018-06-25 16:23:32 +05308144static int in_get_active_microphones(const struct audio_stream_in *stream,
8145 struct audio_microphone_characteristic_t *mic_array,
8146 size_t *mic_count) {
8147 struct stream_in *in = (struct stream_in *)stream;
8148 struct audio_device *adev = in->dev;
8149 ALOGVV("%s", __func__);
8150
8151 lock_input_stream(in);
8152 pthread_mutex_lock(&adev->lock);
8153 int ret = platform_get_active_microphones(adev->platform,
8154 audio_channel_count_from_in_mask(in->channel_mask),
8155 in->usecase, mic_array, mic_count);
8156 pthread_mutex_unlock(&adev->lock);
8157 pthread_mutex_unlock(&in->lock);
8158
8159 return ret;
8160}
8161
8162static int adev_get_microphones(const struct audio_hw_device *dev,
8163 struct audio_microphone_characteristic_t *mic_array,
8164 size_t *mic_count) {
8165 struct audio_device *adev = (struct audio_device *)dev;
8166 ALOGVV("%s", __func__);
8167
8168 pthread_mutex_lock(&adev->lock);
8169 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
8170 pthread_mutex_unlock(&adev->lock);
8171
8172 return ret;
8173}
juyuchendb308c22019-01-21 11:57:17 -07008174
8175static void in_update_sink_metadata(struct audio_stream_in *stream,
8176 const struct sink_metadata *sink_metadata) {
8177
8178 if (stream == NULL
8179 || sink_metadata == NULL
8180 || sink_metadata->tracks == NULL) {
8181 return;
8182 }
8183
8184 int error = 0;
8185 struct stream_in *in = (struct stream_in *)stream;
8186 struct audio_device *adev = in->dev;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008187 struct listnode devices;
8188
8189 list_init(&devices);
juyuchendb308c22019-01-21 11:57:17 -07008190
8191 if (sink_metadata->track_count != 0)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008192 reassign_device_list(&devices, sink_metadata->tracks->dest_device, "");
juyuchendb308c22019-01-21 11:57:17 -07008193
8194 lock_input_stream(in);
8195 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008196 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, get_device_types(&devices));
juyuchendb308c22019-01-21 11:57:17 -07008197
Zhou Song503196b2021-07-23 17:31:05 +08008198 if ((in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY ||
8199 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2) &&
8200 !list_empty(&devices) &&
8201 adev->voice_tx_output != NULL) {
juyuchendb308c22019-01-21 11:57:17 -07008202 /* Use the rx device from afe-proxy record to route voice call because
8203 there is no routing if tx device is on primary hal and rx device
8204 is on other hal during voice call. */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008205 assign_devices(&adev->voice_tx_output->device_list, &devices);
juyuchendb308c22019-01-21 11:57:17 -07008206
8207 if (!voice_is_call_state_active(adev)) {
8208 if (adev->mode == AUDIO_MODE_IN_CALL) {
8209 adev->current_call_output = adev->voice_tx_output;
8210 error = voice_start_call(adev);
8211 if (error != 0)
8212 ALOGE("%s: start voice call failed %d", __func__, error);
8213 }
8214 } else {
8215 adev->current_call_output = adev->voice_tx_output;
8216 voice_update_devices_for_all_voice_usecases(adev);
8217 }
8218 }
8219
Zhenlin Lian4f947842022-05-14 15:50:52 +05308220 clear_devices(&devices);
juyuchendb308c22019-01-21 11:57:17 -07008221 pthread_mutex_unlock(&adev->lock);
8222 pthread_mutex_unlock(&in->lock);
8223}
8224
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308225int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07008226 audio_io_handle_t handle,
8227 audio_devices_t devices,
8228 audio_output_flags_t flags,
8229 struct audio_config *config,
8230 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04008231 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008232{
8233 struct audio_device *adev = (struct audio_device *)dev;
8234 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05308235 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008236 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008237 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05308238 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008239 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
8240 bool is_usb_dev = audio_is_usb_out_device(devices) &&
8241 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
8242 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008243 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07008244 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
8245 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008246 bool force_haptic_path =
8247 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07008248 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008249#ifdef AUDIO_GKI_ENABLED
8250 __s32 *generic_dec;
8251#endif
Weiyin Jiang906db3c2021-03-02 13:17:04 +08008252 pthread_mutexattr_t latch_attr;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008253
kunleizdff872d2018-08-20 14:40:33 +08008254 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08008255 is_usb_dev = false;
8256 devices = AUDIO_DEVICE_OUT_SPEAKER;
8257 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
8258 __func__, devices);
Mingshu Pangdbd20562019-11-25 18:04:39 +08008259 if (config->format == AUDIO_FORMAT_DEFAULT)
8260 config->format = AUDIO_FORMAT_PCM_16_BIT;
8261 if (config->sample_rate == 0)
8262 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8263 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8264 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
kunleizd6a9e0c2018-07-30 15:38:52 +08008265 }
8266
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008267 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05308268
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008269 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
8270
Mingming Yin3a941d42016-02-17 18:08:05 -08008271 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04008272 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
8273 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308274
8275
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008276 if (!out) {
8277 return -ENOMEM;
8278 }
8279
Haynes Mathew George204045b2015-02-25 20:32:03 -08008280 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07008281 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Weiyin Jiang906db3c2021-03-02 13:17:04 +08008282 pthread_mutexattr_init(&latch_attr);
8283 pthread_mutexattr_settype(&latch_attr, PTHREAD_MUTEX_RECURSIVE);
8284 pthread_mutex_init(&out->latch_lock, &latch_attr);
8285 pthread_mutexattr_destroy(&latch_attr);
Zhou Song48453a02018-01-10 17:50:59 +08008286 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08008287 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
8288
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008289 if (devices == AUDIO_DEVICE_NONE)
8290 devices = AUDIO_DEVICE_OUT_SPEAKER;
8291
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008292 out->flags = flags;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008293 list_init(&out->device_list);
8294 update_device_list(&out->device_list, devices, address, true /* add devices */);
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07008295 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07008296 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008297 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05308298 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05308299 if (out->channel_mask == AUDIO_CHANNEL_NONE)
8300 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
8301 else
8302 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07008303 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07008304 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08008305 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308306 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308307 out->started = 0;
Zhou Songbaddf9f2020-11-20 13:57:39 +08008308 out->a2dp_muted = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008309 out->hal_output_suspend_supported = 0;
8310 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05308311 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05308312 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05308313 out->pspd_coeff_sent = false;
Phil Burkd898ba62019-06-20 12:49:01 -07008314 out->mmap_shared_memory_fd = -1; // not open
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008315
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05308316 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05308317 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07008318 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
8319
Aalique Grahame22e49102018-12-18 14:23:57 -08008320 if (direct_dev &&
8321 (audio_is_linear_pcm(out->format) ||
8322 config->format == AUDIO_FORMAT_DEFAULT) &&
8323 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
8324 audio_format_t req_format = config->format;
8325 audio_channel_mask_t req_channel_mask = config->channel_mask;
8326 uint32_t req_sample_rate = config->sample_rate;
8327
8328 pthread_mutex_lock(&adev->lock);
8329 if (is_hdmi) {
8330 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
8331 ret = read_hdmi_sink_caps(out);
8332 if (config->sample_rate == 0)
8333 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8334 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8335 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
8336 if (config->format == AUDIO_FORMAT_DEFAULT)
8337 config->format = AUDIO_FORMAT_PCM_16_BIT;
8338 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008339 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
8340 &config->format,
8341 &out->supported_formats[0],
8342 MAX_SUPPORTED_FORMATS,
8343 &config->channel_mask,
8344 &out->supported_channel_masks[0],
8345 MAX_SUPPORTED_CHANNEL_MASKS,
8346 &config->sample_rate,
8347 &out->supported_sample_rates[0],
8348 MAX_SUPPORTED_SAMPLE_RATES);
8349 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008350 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008351
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008352 pthread_mutex_unlock(&adev->lock);
8353 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08008354 if (ret == -ENOSYS) {
8355 /* ignore and go with default */
8356 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08008357 }
8358 // For MMAP NO IRQ, allow conversions in ADSP
8359 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
8360 goto error_open;
8361 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008362 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08008363 goto error_open;
8364 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008365
8366 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
8367 config->sample_rate = req_sample_rate;
8368 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
8369 config->channel_mask = req_channel_mask;
8370 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
8371 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08008372 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008373
8374 out->sample_rate = config->sample_rate;
8375 out->channel_mask = config->channel_mask;
8376 out->format = config->format;
8377 if (is_hdmi) {
8378 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
8379 out->config = pcm_config_hdmi_multi;
8380 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8381 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8382 out->config = pcm_config_mmap_playback;
8383 out->stream.start = out_start;
8384 out->stream.stop = out_stop;
8385 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8386 out->stream.get_mmap_position = out_get_mmap_position;
8387 } else {
8388 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
8389 out->config = pcm_config_hifi;
8390 }
8391
8392 out->config.rate = out->sample_rate;
8393 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
8394 if (is_hdmi) {
8395 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
8396 audio_bytes_per_sample(out->format));
8397 }
8398 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08008399 }
8400
Derek Chenf6318be2017-06-12 17:16:24 -04008401 /* validate bus device address */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008402 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008403 /* extract car audio stream index */
8404 out->car_audio_stream =
8405 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
8406 if (out->car_audio_stream < 0) {
8407 ALOGE("%s: invalid car audio stream %x",
8408 __func__, out->car_audio_stream);
8409 ret = -EINVAL;
8410 goto error_open;
8411 }
Derek Chen5f67a942020-02-24 23:08:13 -08008412 ALOGV("%s: car_audio_stream %x", __func__, out->car_audio_stream);
Derek Chenf6318be2017-06-12 17:16:24 -04008413 }
8414
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008415 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07008416 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008417 if (!voice_extn_is_compress_voip_supported()) {
8418 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
8419 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07008420 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
Lakshman Chaluvarajue7fc9482020-05-30 14:29:29 +05308421 config->channel_mask : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008422 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
8423 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07008424 out->volume_l = INVALID_OUT_VOLUME;
8425 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07008426
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008427 out->config = default_pcm_config_voip_copp;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008428 out->config.rate = out->sample_rate;
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07008429 uint32_t channel_count =
8430 audio_channel_count_from_out_mask(out->channel_mask);
Ramjee Singh968858a2020-08-06 16:30:48 +05308431 out->config.channels = channel_count;
8432
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07008433 uint32_t buffer_size = get_stream_buffer_size(DEFAULT_VOIP_BUF_DURATION_MS,
8434 out->sample_rate, out->format,
8435 channel_count, false);
8436 uint32_t frame_size = audio_bytes_per_sample(out->format) * channel_count;
8437 if (frame_size != 0)
8438 out->config.period_size = buffer_size / frame_size;
8439 else
8440 ALOGW("%s: frame size is 0 for format %#x", __func__, out->format);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008441 }
8442 } else {
8443 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
8444 voice_extn_compress_voip_is_active(out->dev)) &&
8445 (voice_extn_compress_voip_is_config_supported(config))) {
8446 ret = voice_extn_compress_voip_open_output_stream(out);
8447 if (ret != 0) {
8448 ALOGE("%s: Compress voip output cannot be opened, error:%d",
8449 __func__, ret);
8450 goto error_open;
8451 }
Sujin Panicker19027262019-09-16 18:28:06 +05308452 } else {
8453 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8454 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008455 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008456 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008457 } else if (audio_is_linear_pcm(out->format) &&
8458 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
8459 out->channel_mask = config->channel_mask;
8460 out->sample_rate = config->sample_rate;
8461 out->format = config->format;
8462 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
8463 // does this change?
8464 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
8465 out->config.rate = config->sample_rate;
8466 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
8467 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
8468 audio_bytes_per_sample(config->format));
8469 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07008470 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308471 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308472 pthread_mutex_lock(&adev->lock);
8473 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
8474 pthread_mutex_unlock(&adev->lock);
8475
8476 // reject offload during card offline to allow
8477 // fallback to s/w paths
8478 if (offline) {
8479 ret = -ENODEV;
8480 goto error_open;
8481 }
vivek mehta0ea887a2015-08-26 14:01:20 -07008482
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008483 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
8484 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
8485 ALOGE("%s: Unsupported Offload information", __func__);
8486 ret = -EINVAL;
8487 goto error_open;
8488 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008489
Atul Khare3fa6e542017-08-09 00:56:17 +05308490 if (config->offload_info.format == 0)
8491 config->offload_info.format = config->format;
8492 if (config->offload_info.sample_rate == 0)
8493 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008494
Mingming Yin90310102013-11-13 16:57:00 -08008495 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308496 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07008497 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008498 ret = -EINVAL;
8499 goto error_open;
8500 }
8501
Ben Romberger0f8c87b2017-05-24 17:41:11 -07008502 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
8503 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
8504 (audio_extn_passthru_is_passthrough_stream(out)) &&
8505 !((config->sample_rate == 48000) ||
8506 (config->sample_rate == 96000) ||
8507 (config->sample_rate == 192000))) {
8508 ALOGE("%s: Unsupported sample rate %d for audio format %x",
8509 __func__, config->sample_rate, config->offload_info.format);
8510 ret = -EINVAL;
8511 goto error_open;
8512 }
8513
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008514 out->compr_config.codec = (struct snd_codec *)
8515 calloc(1, sizeof(struct snd_codec));
8516
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008517 if (!out->compr_config.codec) {
8518 ret = -ENOMEM;
8519 goto error_open;
8520 }
8521
Dhananjay Kumarac341582017-02-23 23:42:25 +05308522 out->stream.pause = out_pause;
8523 out->stream.resume = out_resume;
8524 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05308525 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05308526 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07008527 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05308528 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07008529 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05308530 } else {
8531 out->usecase = get_offload_usecase(adev, false /* is_compress */);
8532 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07008533 }
vivek mehta446c3962015-09-14 10:57:35 -07008534
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308535 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8536 ALOGD("%s: Setting latency mode to true", __func__);
Meng Wang4c32fb42020-01-16 17:57:11 +08008537#ifdef AUDIO_GKI_ENABLED
8538 /* out->compr_config.codec->reserved[1] is for flags */
8539 out->compr_config.codec->reserved[1] |= audio_extn_utils_get_perf_mode_flag();
8540#else
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308541 out->compr_config.codec->flags |= audio_extn_utils_get_perf_mode_flag();
Meng Wang4c32fb42020-01-16 17:57:11 +08008542#endif
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308543 }
8544
vivek mehta446c3962015-09-14 10:57:35 -07008545 if (out->usecase == USECASE_INVALID) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008546 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Mingming Yin3a941d42016-02-17 18:08:05 -08008547 config->format == 0 && config->sample_rate == 0 &&
8548 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07008549 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08008550 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
8551 } else {
8552 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
8553 ret = -EEXIST;
8554 goto error_open;
8555 }
vivek mehta446c3962015-09-14 10:57:35 -07008556 }
8557
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008558 if (config->offload_info.channel_mask)
8559 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008560 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008561 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008562 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008563 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05308564 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008565 ret = -EINVAL;
8566 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008567 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008568
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008569 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008570 out->sample_rate = config->offload_info.sample_rate;
8571
Mingming Yin3ee55c62014-08-04 14:23:35 -07008572 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008573
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308574 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05308575 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308576 audio_extn_dolby_send_ddp_endp_params(adev);
8577 audio_extn_dolby_set_dmid(adev);
8578 }
vivek mehta0ea887a2015-08-26 14:01:20 -07008579
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008580 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08008581 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008582 out->compr_config.codec->bit_rate =
8583 config->offload_info.bit_rate;
8584 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05308585 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008586 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05308587 /* Update bit width only for non passthrough usecases.
8588 * For passthrough usecases, the output will always be opened @16 bit
8589 */
8590 if (!audio_extn_passthru_is_passthrough_stream(out))
8591 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308592
8593 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
Meng Wang4c32fb42020-01-16 17:57:11 +08008594#ifdef AUDIO_GKI_ENABLED
8595 /* out->compr_config.codec->reserved[1] is for flags */
8596 out->compr_config.codec->reserved[1] |= COMPRESSED_TIMESTAMP_FLAG;
8597 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->reserved[1]);
8598#else
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308599 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
8600 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
Meng Wang4c32fb42020-01-16 17:57:11 +08008601#endif
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308602
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008603 /*TODO: Do we need to change it for passthrough */
8604 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008605
Manish Dewangana6fc5442015-08-24 20:30:31 +05308606 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
8607 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308608 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05308609 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308610 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
8611 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308612
8613 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
8614 AUDIO_FORMAT_PCM) {
8615
8616 /*Based on platform support, configure appropriate alsa format for corresponding
8617 *hal input format.
8618 */
8619 out->compr_config.codec->format = hal_format_to_alsa(
8620 config->offload_info.format);
8621
Ashish Jain83a6cc22016-06-28 14:34:17 +05308622 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05308623 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308624 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308625
Dhananjay Kumarac341582017-02-23 23:42:25 +05308626 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05308627 *hal input format and alsa format might differ based on platform support.
8628 */
8629 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05308630 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308631
8632 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
8633
Deeraj Soman93155a62019-09-30 19:00:37 +05308634 if (property_get_bool("vendor.audio.offload.buffer.duration.enabled", false)) {
8635 if ((config->offload_info.duration_us >= MIN_OFFLOAD_BUFFER_DURATION_MS * 1000) &&
8636 (config->offload_info.duration_us <= MAX_OFFLOAD_BUFFER_DURATION_MS * 1000))
8637 out->info.duration_us = (int64_t)config->offload_info.duration_us;
8638 }
Deeraj Soman65358ab2019-02-07 15:40:49 +05308639
Ashish Jainf1eaa582016-05-23 20:54:24 +05308640 /* Check if alsa session is configured with the same format as HAL input format,
8641 * if not then derive correct fragment size needed to accomodate the
8642 * conversion of HAL input format to alsa format.
8643 */
8644 audio_extn_utils_update_direct_pcm_fragment_size(out);
8645
8646 /*if hal input and output fragment size is different this indicates HAL input format is
8647 *not same as the alsa format
8648 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308649 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05308650 /*Allocate a buffer to convert input data to the alsa configured format.
8651 *size of convert buffer is equal to the size required to hold one fragment size
8652 *worth of pcm data, this is because flinger does not write more than fragment_size
8653 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308654 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
8655 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05308656 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
8657 ret = -ENOMEM;
8658 goto error_open;
8659 }
8660 }
8661 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
8662 out->compr_config.fragment_size =
8663 audio_extn_passthru_get_buffer_size(&config->offload_info);
8664 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8665 } else {
8666 out->compr_config.fragment_size =
8667 platform_get_compress_offload_buffer_size(&config->offload_info);
8668 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8669 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008670
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308671 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8672 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
8673 }
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008674 if (config->offload_info.format == AUDIO_FORMAT_FLAC) {
8675#ifdef AUDIO_GKI_ENABLED
8676 generic_dec =
8677 &(out->compr_config.codec->options.generic.reserved[1]);
8678 ((struct snd_generic_dec_flac *)generic_dec)->sample_size =
8679 AUDIO_OUTPUT_BIT_WIDTH;
8680#else
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05308681 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008682#endif
8683 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008684
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05308685 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
8686 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
8687 }
8688
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008689 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
8690 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008691
Manish Dewangan69426c82017-01-30 17:35:36 +05308692 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
8693 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
8694 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
8695 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8696 out->render_mode = RENDER_MODE_AUDIO_MASTER;
8697 } else {
8698 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
8699 }
Alexy Josephaa54c872014-12-03 02:46:47 -08008700
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05308701 memset(&out->channel_map_param, 0,
8702 sizeof(struct audio_out_channel_map_param));
8703
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008704 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05308705 out->send_next_track_params = false;
8706 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008707 out->offload_state = OFFLOAD_STATE_IDLE;
8708 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08008709 out->writeAt.tv_sec = 0;
8710 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008711
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008712 audio_extn_dts_create_state_notifier_node(out->usecase);
8713
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008714 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
8715 __func__, config->offload_info.version,
8716 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05308717
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308718 /* Check if DSD audio format is supported in codec
8719 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308720 */
8721
8722 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308723 (!platform_check_codec_dsd_support(adev->platform) ||
8724 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308725 ret = -EINVAL;
8726 goto error_open;
8727 }
8728
Ashish Jain5106d362016-05-11 19:23:33 +05308729 /* Disable gapless if any of the following is true
8730 * passthrough playback
8731 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05308732 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05308733 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308734 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308735 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07008736 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308737 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308738 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05308739 check_and_set_gapless_mode(adev, false);
8740 } else
8741 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07008742
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308743 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07008744 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
8745 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308746 if (config->format == AUDIO_FORMAT_DSD) {
8747 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
Meng Wang4c32fb42020-01-16 17:57:11 +08008748#ifdef AUDIO_GKI_ENABLED
8749 /* out->compr_config.codec->reserved[0] is for compr_passthr */
8750 out->compr_config.codec->reserved[0] = PASSTHROUGH_DSD;
8751#else
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308752 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
Meng Wang4c32fb42020-01-16 17:57:11 +08008753#endif
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308754 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07008755
8756 create_offload_callback_thread(out);
8757
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008758 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008759 switch (config->sample_rate) {
8760 case 0:
8761 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8762 break;
8763 case 8000:
8764 case 16000:
8765 case 48000:
8766 out->sample_rate = config->sample_rate;
8767 break;
8768 default:
8769 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
8770 config->sample_rate);
8771 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8772 ret = -EINVAL;
8773 goto error_open;
8774 }
8775 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8776 switch (config->channel_mask) {
8777 case AUDIO_CHANNEL_NONE:
8778 case AUDIO_CHANNEL_OUT_STEREO:
8779 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8780 break;
8781 default:
8782 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
8783 config->channel_mask);
8784 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8785 ret = -EINVAL;
8786 goto error_open;
8787 }
8788 switch (config->format) {
8789 case AUDIO_FORMAT_DEFAULT:
8790 case AUDIO_FORMAT_PCM_16_BIT:
8791 out->format = AUDIO_FORMAT_PCM_16_BIT;
8792 break;
8793 default:
8794 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
8795 config->format);
8796 config->format = AUDIO_FORMAT_PCM_16_BIT;
8797 ret = -EINVAL;
8798 goto error_open;
8799 }
8800
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05308801 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008802 if (ret != 0) {
8803 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008804 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008805 goto error_open;
8806 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008807 } else if (is_single_device_type_equal(&out->device_list,
8808 AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08008809 switch (config->sample_rate) {
8810 case 0:
8811 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
8812 break;
8813 case 8000:
8814 case 16000:
8815 case 48000:
8816 out->sample_rate = config->sample_rate;
8817 break;
8818 default:
8819 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
8820 config->sample_rate);
8821 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8822 ret = -EINVAL;
8823 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008824 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008825 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8826 switch (config->channel_mask) {
8827 case AUDIO_CHANNEL_NONE:
8828 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8829 break;
8830 case AUDIO_CHANNEL_OUT_STEREO:
8831 out->channel_mask = config->channel_mask;
8832 break;
8833 default:
8834 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
8835 config->channel_mask);
8836 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8837 ret = -EINVAL;
8838 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008839 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008840 switch (config->format) {
8841 case AUDIO_FORMAT_DEFAULT:
8842 out->format = AUDIO_FORMAT_PCM_16_BIT;
8843 break;
8844 case AUDIO_FORMAT_PCM_16_BIT:
8845 out->format = config->format;
8846 break;
8847 default:
8848 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
8849 config->format);
8850 config->format = AUDIO_FORMAT_PCM_16_BIT;
8851 ret = -EINVAL;
8852 break;
8853 }
8854 if (ret != 0)
8855 goto error_open;
8856
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008857 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
8858 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08008859 out->config.rate = out->sample_rate;
8860 out->config.channels =
8861 audio_channel_count_from_out_mask(out->channel_mask);
8862 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008863 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008864 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05308865 unsigned int channels = 0;
8866 /*Update config params to default if not set by the caller*/
8867 if (config->sample_rate == 0)
8868 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8869 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8870 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8871 if (config->format == AUDIO_FORMAT_DEFAULT)
8872 config->format = AUDIO_FORMAT_PCM_16_BIT;
8873
8874 channels = audio_channel_count_from_out_mask(out->channel_mask);
8875
Varun Balaraje49253e2017-07-06 19:48:56 +05308876 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
8877 out->usecase = get_interactive_usecase(adev);
8878 out->config = pcm_config_low_latency;
8879 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05308880 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008881 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
8882 out->flags);
8883 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07008884 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8885 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8886 out->config = pcm_config_mmap_playback;
8887 out->stream.start = out_start;
8888 out->stream.stop = out_stop;
8889 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8890 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308891 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8892 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008893 out->hal_output_suspend_supported =
8894 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
8895 out->dynamic_pm_qos_config_supported =
8896 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
8897 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08008898 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
8899 } else {
8900 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
8901 //the mixer path will be a string similar to "low-latency-playback resume"
8902 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
8903 strlcat(out->pm_qos_mixer_path,
8904 " resume", MAX_MIXER_PATH_LEN);
8905 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
8906 out->pm_qos_mixer_path);
8907 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308908 out->config = pcm_config_low_latency;
8909 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
8910 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
8911 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05308912 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
8913 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
8914 if (out->config.period_size <= 0) {
8915 ALOGE("Invalid configuration period size is not valid");
8916 ret = -EINVAL;
8917 goto error_open;
8918 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008919 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
8920 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
8921 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008922 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
8923 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
8924 out->config = pcm_config_haptics_audio;
8925 if (force_haptic_path)
8926 adev->haptics_config = pcm_config_haptics_audio;
8927 else
8928 adev->haptics_config = pcm_config_haptics;
8929
Meng Wangd08ce322020-04-02 08:59:20 +08008930 channels =
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008931 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
8932
8933 if (force_haptic_path) {
8934 out->config.channels = 1;
8935 adev->haptics_config.channels = 1;
8936 } else
8937 adev->haptics_config.channels = audio_channel_count_from_out_mask(out->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008938 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008939 ret = audio_extn_auto_hal_open_output_stream(out);
8940 if (ret) {
8941 ALOGE("%s: Failed to open output stream for bus device", __func__);
8942 ret = -EINVAL;
8943 goto error_open;
8944 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308945 } else {
8946 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008947 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8948 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308949 }
8950 out->hal_ip_format = format = out->format;
8951 out->config.format = hal_format_to_pcm(out->hal_ip_format);
8952 out->hal_op_format = pcm_format_to_hal(out->config.format);
8953 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
8954 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008955 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05308956 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308957 if (out->hal_ip_format != out->hal_op_format) {
8958 uint32_t buffer_size = out->config.period_size *
8959 format_to_bitwidth_table[out->hal_op_format] *
8960 out->config.channels;
8961 out->convert_buffer = calloc(1, buffer_size);
8962 if (out->convert_buffer == NULL){
8963 ALOGE("Allocation failed for convert buffer for size %d",
8964 out->compr_config.fragment_size);
8965 ret = -ENOMEM;
8966 goto error_open;
8967 }
8968 ALOGD("Convert buffer allocated of size %d", buffer_size);
8969 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008970 }
8971
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008972 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
8973 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308974
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008975 /* TODO remove this hardcoding and check why width is zero*/
8976 if (out->bit_width == 0)
8977 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308978 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008979 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008980 &out->device_list, out->flags,
8981 out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05308982 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05308983 &out->app_type_cfg);
Kogara Naveen Kumar65828fe2022-10-14 16:41:04 +05308984 if (((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
8985 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) && (!compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS))) {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08008986 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008987 if(adev->primary_output == NULL)
8988 adev->primary_output = out;
8989 else {
8990 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008991 ret = -EEXIST;
8992 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008993 }
8994 }
8995
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008996 /* Check if this usecase is already existing */
8997 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07008998 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
8999 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009000 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009001 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07009002 ret = -EEXIST;
9003 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009004 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009005
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009006 pthread_mutex_unlock(&adev->lock);
9007
9008 out->stream.common.get_sample_rate = out_get_sample_rate;
9009 out->stream.common.set_sample_rate = out_set_sample_rate;
9010 out->stream.common.get_buffer_size = out_get_buffer_size;
9011 out->stream.common.get_channels = out_get_channels;
9012 out->stream.common.get_format = out_get_format;
9013 out->stream.common.set_format = out_set_format;
9014 out->stream.common.standby = out_standby;
9015 out->stream.common.dump = out_dump;
9016 out->stream.common.set_parameters = out_set_parameters;
9017 out->stream.common.get_parameters = out_get_parameters;
9018 out->stream.common.add_audio_effect = out_add_audio_effect;
9019 out->stream.common.remove_audio_effect = out_remove_audio_effect;
9020 out->stream.get_latency = out_get_latency;
9021 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08009022#ifdef NO_AUDIO_OUT
9023 out->stream.write = out_write_for_no_output;
9024#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009025 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08009026#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009027 out->stream.get_render_position = out_get_render_position;
9028 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07009029 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009030
Haynes Mathew George16081042017-05-31 17:16:49 -07009031 if (out->realtime)
9032 out->af_period_multiplier = af_period_multiplier;
9033 else
9034 out->af_period_multiplier = 1;
9035
Andy Hunga1f48fa2019-07-01 18:14:53 -07009036 out->kernel_buffer_size = out->config.period_size * out->config.period_count;
9037
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009038 out->standby = 1;
Zhou Songbaddf9f2020-11-20 13:57:39 +08009039 out->volume_l = PLAYBACK_GAIN_MAX;
9040 out->volume_r = PLAYBACK_GAIN_MAX;
Eric Laurenta9024de2013-04-04 09:19:12 -07009041 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07009042 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009043
9044 config->format = out->stream.common.get_format(&out->stream.common);
9045 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
9046 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05309047 register_format(out->format, out->supported_formats);
9048 register_channel_mask(out->channel_mask, out->supported_channel_masks);
9049 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009050
Dechen Chai22768452021-07-30 09:29:16 +05309051#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -08009052 out->error_log = error_log_create(
9053 ERROR_LOG_ENTRIES,
9054 1000000000 /* aggregate consecutive identical errors within one second in ns */);
Dechen Chai22768452021-07-30 09:29:16 +05309055#endif
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309056 /*
9057 By locking output stream before registering, we allow the callback
9058 to update stream's state only after stream's initial state is set to
9059 adev state.
9060 */
9061 lock_output_stream(out);
9062 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
9063 pthread_mutex_lock(&adev->lock);
9064 out->card_status = adev->card_status;
9065 pthread_mutex_unlock(&adev->lock);
9066 pthread_mutex_unlock(&out->lock);
9067
Aalique Grahame22e49102018-12-18 14:23:57 -08009068 stream_app_type_cfg_init(&out->app_type_cfg);
9069
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009070 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309071 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07009072 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08009073
9074 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
9075 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
9076 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08009077 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05309078 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08009079 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07009080 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05309081 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
9082 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08009083 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
9084 out->usecase, PCM_PLAYBACK);
9085 hdlr_stream_cfg.flags = out->flags;
9086 hdlr_stream_cfg.type = PCM_PLAYBACK;
9087 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
9088 &hdlr_stream_cfg);
9089 if (ret) {
9090 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
9091 out->adsp_hdlr_stream_handle = NULL;
9092 }
9093 }
Gangadhar Sb0210342019-02-22 17:39:41 +05309094 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
9095 is_direct_passthough, false);
9096 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
9097 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07009098 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07009099 if (ret < 0) {
9100 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
9101 out->ip_hdlr_handle = NULL;
9102 }
9103 }
Derek Chenf939fb72018-11-13 13:34:41 -08009104
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009105 ret = io_streams_map_insert(adev, &out->stream.common,
9106 out->handle, AUDIO_PATCH_HANDLE_NONE);
9107 if (ret != 0)
9108 goto error_open;
9109
Susan Wang6dd13092021-01-25 10:27:11 -05009110 out->out_ctxt.output = out;
Derek Chenf939fb72018-11-13 13:34:41 -08009111
9112 pthread_mutex_lock(&adev->lock);
Susan Wang6dd13092021-01-25 10:27:11 -05009113 list_add_tail(&adev->active_outputs_list, &out->out_ctxt.list);
Derek Chenf939fb72018-11-13 13:34:41 -08009114 pthread_mutex_unlock(&adev->lock);
9115
Eric Laurent994a6932013-07-17 11:51:42 -07009116 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009117 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07009118
9119error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05309120 if (out->convert_buffer)
9121 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07009122 free(out);
9123 *stream_out = NULL;
9124 ALOGD("%s: exit: ret %d", __func__, ret);
9125 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009126}
9127
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309128void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009129 struct audio_stream_out *stream)
9130{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07009131 struct stream_out *out = (struct stream_out *)stream;
9132 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009133 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07009134
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009135 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309136
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009137 io_streams_map_remove(adev, out->handle);
9138
Susan Wang6dd13092021-01-25 10:27:11 -05009139 // remove out_ctxt early to prevent the stream
9140 // being opened in a race condition
9141 pthread_mutex_lock(&adev->lock);
9142 list_remove(&out->out_ctxt.list);
9143 pthread_mutex_unlock(&adev->lock);
9144
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309145 // must deregister from sndmonitor first to prevent races
9146 // between the callback and close_stream
9147 audio_extn_snd_mon_unregister_listener(out);
9148
Ben Rombergerd771a7c2017-02-22 18:05:17 -08009149 /* close adsp hdrl session before standby */
9150 if (out->adsp_hdlr_stream_handle) {
9151 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
9152 if (ret)
9153 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
9154 out->adsp_hdlr_stream_handle = NULL;
9155 }
9156
Manish Dewangan21a850a2017-08-14 12:03:55 +05309157 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07009158 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
9159 out->ip_hdlr_handle = NULL;
9160 }
9161
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009162 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309163 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009164 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05309165 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309166 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009167 if(ret != 0)
9168 ALOGE("%s: Compress voip output cannot be closed, error:%d",
9169 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009170 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009171 out_standby(&stream->common);
9172
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07009173 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08009174 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07009175 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07009176 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07009177 if (out->compr_config.codec != NULL)
9178 free(out->compr_config.codec);
9179 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009180
Zhou Songbaddf9f2020-11-20 13:57:39 +08009181 out->a2dp_muted = false;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05309182
Varun Balaraje49253e2017-07-06 19:48:56 +05309183 if (is_interactive_usecase(out->usecase))
9184 free_interactive_usecase(adev, out->usecase);
9185
Ashish Jain83a6cc22016-06-28 14:34:17 +05309186 if (out->convert_buffer != NULL) {
9187 free(out->convert_buffer);
9188 out->convert_buffer = NULL;
9189 }
9190
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009191 if (adev->voice_tx_output == out)
9192 adev->voice_tx_output = NULL;
9193
Dechen Chai22768452021-07-30 09:29:16 +05309194#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -08009195 error_log_destroy(out->error_log);
9196 out->error_log = NULL;
Dechen Chai22768452021-07-30 09:29:16 +05309197#endif
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05309198 if (adev->primary_output == out)
9199 adev->primary_output = NULL;
9200
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07009201 pthread_cond_destroy(&out->cond);
9202 pthread_mutex_destroy(&out->lock);
Weiyin Jiang280ea742020-09-08 20:28:22 +08009203 pthread_mutex_destroy(&out->pre_lock);
9204 pthread_mutex_destroy(&out->latch_lock);
9205 pthread_mutex_destroy(&out->position_query_lock);
Derek Chenf939fb72018-11-13 13:34:41 -08009206
9207 pthread_mutex_lock(&adev->lock);
Zhenlin Lian4f947842022-05-14 15:50:52 +05309208 clear_devices(&out->device_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009209 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08009210 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07009211 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009212}
9213
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05009214void in_set_power_policy(uint8_t enable)
9215{
9216 struct listnode *node;
9217
9218 ALOGD("%s: Enter, state %d", __func__, enable);
9219
9220 pthread_mutex_lock(&adev->lock);
9221 adev->in_power_policy = enable ? POWER_POLICY_STATUS_ONLINE : POWER_POLICY_STATUS_OFFLINE;
9222 pthread_mutex_unlock(&adev->lock);
9223
9224 if (!enable) {
9225 list_for_each(node, &adev->active_inputs_list) {
9226 streams_input_ctxt_t *in_ctxt = node_to_item(node,
9227 streams_input_ctxt_t,
9228 list);
9229 struct stream_in *in = in_ctxt->input;
9230 in_standby(&in->stream.common);
9231 }
9232 }
9233
9234 ALOGD("%s: Exit", __func__);
9235}
9236
9237void out_set_power_policy(uint8_t enable)
9238{
9239 struct listnode *node;
9240
9241 ALOGD("%s: Enter, state %d", __func__, enable);
9242
9243 pthread_mutex_lock(&adev->lock);
E V Ravi317be872022-02-23 19:08:15 +05309244 adev->out_power_policy = enable ? POWER_POLICY_STATUS_ONLINE : POWER_POLICY_STATUS_OFFLINE;
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05009245 pthread_mutex_unlock(&adev->lock);
9246
9247 if (!enable) {
9248 list_for_each(node, &adev->active_outputs_list) {
9249 streams_output_ctxt_t *out_ctxt = node_to_item(node,
9250 streams_output_ctxt_t,
9251 list);
9252 struct stream_out *out = out_ctxt->output;
9253 out_on_error(&out->stream.common);
9254 }
9255 }
9256
9257 ALOGD("%s: Exit", __func__);
9258}
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009259static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
9260{
9261 struct audio_device *adev = (struct audio_device *)dev;
9262 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009263 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07009264 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009265 int ret;
9266 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08009267 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08009268 struct listnode *node;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07009269 int controller = -1, stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009270
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009271 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009272 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009273
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05309274 if (!parms)
9275 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05309276
Derek Chen6f293672019-04-01 01:40:24 -07009277 /* notify adev and input/output streams on the snd card status */
9278 adev_snd_mon_cb((void *)adev, parms);
9279
Weiyin Jiang24f55292020-12-22 14:35:46 +08009280 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
9281 if (ret >= 0) {
9282 list_for_each(node, &adev->active_outputs_list) {
9283 streams_output_ctxt_t *out_ctxt = node_to_item(node,
9284 streams_output_ctxt_t,
9285 list);
9286 out_snd_mon_cb((void *)out_ctxt->output, parms);
9287 }
Derek Chen6f293672019-04-01 01:40:24 -07009288
Weiyin Jiang24f55292020-12-22 14:35:46 +08009289 list_for_each(node, &adev->active_inputs_list) {
9290 streams_input_ctxt_t *in_ctxt = node_to_item(node,
9291 streams_input_ctxt_t,
9292 list);
9293 in_snd_mon_cb((void *)in_ctxt->input, parms);
9294 }
Derek Chen6f293672019-04-01 01:40:24 -07009295 }
9296
Zhou Songd6d71752019-05-21 18:08:51 +08009297 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05309298 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
9299 if (ret >= 0) {
9300 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08009301 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05309302 adev->bt_sco_on = true;
Shalini Manjunatha3a2e06e2021-02-01 12:23:49 +05309303 /*
9304 * When ever BT_SCO=ON arrives, make sure to route
9305 * all use cases to SCO device, otherwise due to delay in
9306 * BT_SCO=ON and lack of synchronization with create audio patch
9307 * request for SCO device, some times use case not routed properly to
9308 * SCO device
9309 */
9310 struct audio_usecase *usecase;
9311 struct listnode *node;
9312 list_for_each(node, &adev->usecase_list) {
9313 usecase = node_to_item(node, struct audio_usecase, list);
Anver sadhiquef0efca32021-09-03 15:25:44 +05309314 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
Anver sadhique93f3c912021-08-11 11:19:45 +05309315 (!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 +05309316 ALOGD("BT_SCO ON, switch all in use case to it");
9317 select_devices(adev, usecase->id);
9318 }
Mingshu Pangef517202021-04-22 10:35:00 +08009319 if (usecase->stream.out && (usecase->type == PCM_PLAYBACK ||
9320 usecase->type == VOICE_CALL) &&
Anver sadhique93f3c912021-08-11 11:19:45 +05309321 (!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 +05309322 ALOGD("BT_SCO ON, switch all out use case to it");
9323 select_devices(adev, usecase->id);
9324 }
9325 }
9326 }
9327 else {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05309328 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08009329 audio_extn_sco_reset_configuration();
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08009330 }
9331 }
9332
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009333 status = voice_set_parameters(adev, parms);
9334 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08009335 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009336
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009337 status = platform_set_parameters(adev->platform, parms);
9338 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08009339 goto done;
9340
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009341 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
9342 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07009343 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009344 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
9345 adev->bluetooth_nrec = true;
9346 else
9347 adev->bluetooth_nrec = false;
9348 }
9349
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009350 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
9351 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009352 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
9353 adev->screen_off = false;
9354 else
9355 adev->screen_off = true;
Quinn Male70f20f32019-06-26 16:50:26 -07009356 audio_extn_sound_trigger_update_screen_status(adev->screen_off);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009357 }
9358
Eric Laurent4b084132018-10-19 17:33:43 -07009359 ret = str_parms_get_int(parms, "rotation", &val);
9360 if (ret >= 0) {
9361 bool reverse_speakers = false;
9362 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
9363 switch (val) {
9364 // FIXME: note that the code below assumes that the speakers are in the correct placement
9365 // relative to the user when the device is rotated 90deg from its default rotation. This
9366 // assumption is device-specific, not platform-specific like this code.
9367 case 270:
9368 reverse_speakers = true;
9369 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
9370 break;
9371 case 0:
9372 case 180:
9373 camera_rotation = CAMERA_ROTATION_PORTRAIT;
9374 break;
9375 case 90:
9376 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
9377 break;
9378 default:
9379 ALOGE("%s: unexpected rotation of %d", __func__, val);
9380 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07009381 }
Eric Laurent4b084132018-10-19 17:33:43 -07009382 if (status == 0) {
9383 // check and set swap
9384 // - check if orientation changed and speaker active
9385 // - set rotation and cache the rotation value
9386 adev->camera_orientation =
9387 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
9388 if (!audio_extn_is_maxx_audio_enabled())
9389 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
9390 }
9391 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07009392
Mingming Yin514a8bc2014-07-29 15:22:21 -07009393 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
9394 if (ret >= 0) {
9395 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
9396 adev->bt_wb_speech_enabled = true;
9397 else
9398 adev->bt_wb_speech_enabled = false;
9399 }
9400
Zhou Song12c29502019-03-16 10:37:18 +08009401 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
9402 if (ret >= 0) {
9403 val = atoi(value);
9404 adev->swb_speech_mode = val;
9405 }
9406
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07009407 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
9408 if (ret >= 0) {
9409 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309410 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08009411 if (audio_is_output_device(val) &&
9412 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07009413 ALOGV("cache new ext disp type and edid");
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07009414 platform_get_controller_stream_from_params(parms, &controller, &stream);
9415 platform_set_ext_display_device_v2(adev->platform, controller, stream);
9416 ret = platform_get_ext_disp_type_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07009417 if (ret < 0) {
9418 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05309419 } else {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07009420 platform_cache_edid_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07009421 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309422 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07009423 /*
9424 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
9425 * Per AudioPolicyManager, USB device is higher priority than WFD.
9426 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
9427 * If WFD use case occupies AFE proxy, it may result unintended behavior while
9428 * starting voice call on USB
9429 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08009430 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309431 if (ret >= 0)
9432 audio_extn_usb_add_device(device, atoi(value));
9433
Zhou Song6f862822017-11-06 17:27:57 +08009434 if (!audio_extn_usb_is_tunnel_supported()) {
9435 ALOGV("detected USB connect .. disable proxy");
9436 adev->allow_afe_proxy_usage = false;
9437 }
Zhou Song503196b2021-07-23 17:31:05 +08009438 } else if (audio_is_hearing_aid_out_device(device) &&
9439 property_get_bool("persist.vendor.audio.ha_proxy.enabled", false)) {
9440 adev->ha_proxy_enable = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07009441 }
9442 }
9443
9444 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
9445 if (ret >= 0) {
9446 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309447 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07009448 /*
9449 * The HDMI / Displayport disconnect handling has been moved to
9450 * audio extension to ensure that its parameters are not
9451 * invalidated prior to updating sysfs of the disconnect event
9452 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
9453 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309454 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08009455 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309456 if (ret >= 0)
9457 audio_extn_usb_remove_device(device, atoi(value));
9458
Zhou Song6f862822017-11-06 17:27:57 +08009459 if (!audio_extn_usb_is_tunnel_supported()) {
9460 ALOGV("detected USB disconnect .. enable proxy");
9461 adev->allow_afe_proxy_usage = true;
9462 }
Zhou Song503196b2021-07-23 17:31:05 +08009463 } else if (audio_is_hearing_aid_out_device(device)) {
9464 adev->ha_proxy_enable = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07009465 }
9466 }
9467
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009468 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08009469
9470 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08009471 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309472 struct audio_usecase *usecase;
9473 struct listnode *node;
9474 list_for_each(node, &adev->usecase_list) {
9475 usecase = node_to_item(node, struct audio_usecase, list);
Weiyin Jiangff56ff32020-05-08 14:32:21 +08009476 if ((usecase->stream.out == NULL) || (usecase->type != PCM_PLAYBACK))
9477 continue;
9478
9479 if (is_a2dp_out_device_type(&usecase->device_list)) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309480 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05309481 audio_extn_a2dp_set_handoff_mode(true);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05309482 ALOGD("Switching to speaker and muting the stream before select_devices");
9483 check_a2dp_restore_l(adev, usecase->stream.out, false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309484 //force device switch to re configure encoder
9485 select_devices(adev, usecase->id);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05309486 ALOGD("Unmuting the stream after select_devices");
Zhou Songbaddf9f2020-11-20 13:57:39 +08009487 check_a2dp_restore_l(adev, usecase->stream.out, true);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05309488 audio_extn_a2dp_set_handoff_mode(false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309489 break;
Zhou Songd01e7a22020-09-23 22:49:01 +08009490 } else if (is_offload_usecase(usecase->stream.out->usecase)) {
Weiyin Jiang280ea742020-09-08 20:28:22 +08009491 pthread_mutex_lock(&usecase->stream.out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +08009492 if (usecase->stream.out->a2dp_muted) {
Weiyin Jiang280ea742020-09-08 20:28:22 +08009493 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
9494 reassign_device_list(&usecase->stream.out->device_list,
9495 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, "");
9496 check_a2dp_restore_l(adev, usecase->stream.out, true);
9497 break;
9498 }
9499 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309500 }
9501 }
9502 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009503
9504 //handle vr audio setparam
9505 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9506 value, sizeof(value));
9507 if (ret >= 0) {
9508 ALOGI("Setting vr mode to be %s", value);
9509 if (!strncmp(value, "true", 4)) {
9510 adev->vr_audio_mode_enabled = true;
9511 ALOGI("Setting vr mode to true");
9512 } else if (!strncmp(value, "false", 5)) {
9513 adev->vr_audio_mode_enabled = false;
9514 ALOGI("Setting vr mode to false");
9515 } else {
9516 ALOGI("wrong vr mode set");
9517 }
9518 }
9519
Eric Laurent4b084132018-10-19 17:33:43 -07009520 //FIXME: to be replaced by proper video capture properties API
9521 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
9522 if (ret >= 0) {
9523 int camera_facing = CAMERA_FACING_BACK;
9524 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
9525 camera_facing = CAMERA_FACING_FRONT;
9526 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
9527 camera_facing = CAMERA_FACING_BACK;
9528 else {
9529 ALOGW("%s: invalid camera facing value: %s", __func__, value);
9530 goto done;
9531 }
9532 adev->camera_orientation =
9533 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
9534 struct audio_usecase *usecase;
9535 struct listnode *node;
9536 list_for_each(node, &adev->usecase_list) {
9537 usecase = node_to_item(node, struct audio_usecase, list);
9538 struct stream_in *in = usecase->stream.in;
9539 if (usecase->type == PCM_CAPTURE && in != NULL &&
9540 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
9541 select_devices(adev, in->usecase);
9542 }
9543 }
9544 }
9545
Tahir Dawson7fabad42022-06-21 12:37:55 -04009546 audio_extn_auto_hal_set_parameters(adev, parms);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05309547 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08009548done:
9549 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009550 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05309551error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009552 ALOGV("%s: exit with code(%d)", __func__, status);
9553 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009554}
9555
9556static char* adev_get_parameters(const struct audio_hw_device *dev,
9557 const char *keys)
9558{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05309559 ALOGD("%s:%s", __func__, keys);
9560
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009561 struct audio_device *adev = (struct audio_device *)dev;
9562 struct str_parms *reply = str_parms_create();
9563 struct str_parms *query = str_parms_create_str(keys);
9564 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05309565 char value[256] = {0};
9566 int ret = 0;
9567
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009568 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08009569 if (reply) {
9570 str_parms_destroy(reply);
9571 }
9572 if (query) {
9573 str_parms_destroy(query);
9574 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009575 ALOGE("adev_get_parameters: failed to create query or reply");
9576 return NULL;
9577 }
9578
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009579 //handle vr audio getparam
9580
9581 ret = str_parms_get_str(query,
9582 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9583 value, sizeof(value));
9584
9585 if (ret >= 0) {
9586 bool vr_audio_enabled = false;
9587 pthread_mutex_lock(&adev->lock);
9588 vr_audio_enabled = adev->vr_audio_mode_enabled;
9589 pthread_mutex_unlock(&adev->lock);
9590
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07009591 ALOGV("getting vr mode to %d", vr_audio_enabled);
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009592
9593 if (vr_audio_enabled) {
9594 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9595 "true");
9596 goto exit;
9597 } else {
9598 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9599 "false");
9600 goto exit;
9601 }
9602 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009603
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009604 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009605 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08009606 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08009607 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009608 platform_get_parameters(adev->platform, query, reply);
justinwengd5395152019-11-04 12:23:09 +08009609 audio_extn_ma_get_parameters(adev, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05309610 pthread_mutex_unlock(&adev->lock);
9611
Naresh Tannirud7205b62014-06-20 02:54:48 +05309612exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009613 str = str_parms_to_str(reply);
9614 str_parms_destroy(query);
9615 str_parms_destroy(reply);
9616
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07009617 ALOGV("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009618 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009619}
9620
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009621static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009622{
9623 return 0;
9624}
9625
9626static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
9627{
Haynes Mathew George5191a852013-09-11 14:19:36 -07009628 int ret;
9629 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08009630
9631 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
9632
Haynes Mathew George5191a852013-09-11 14:19:36 -07009633 pthread_mutex_lock(&adev->lock);
9634 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07009635 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07009636 pthread_mutex_unlock(&adev->lock);
9637 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009638}
9639
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009640static int adev_set_master_volume(struct audio_hw_device *dev __unused,
9641 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009642{
9643 return -ENOSYS;
9644}
9645
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009646static int adev_get_master_volume(struct audio_hw_device *dev __unused,
9647 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009648{
9649 return -ENOSYS;
9650}
9651
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009652static int adev_set_master_mute(struct audio_hw_device *dev __unused,
9653 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009654{
9655 return -ENOSYS;
9656}
9657
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009658static int adev_get_master_mute(struct audio_hw_device *dev __unused,
9659 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009660{
9661 return -ENOSYS;
9662}
9663
9664static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
9665{
9666 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07009667 struct listnode *node;
9668 struct audio_usecase *usecase = NULL;
9669 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08009670
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009671 pthread_mutex_lock(&adev->lock);
9672 if (adev->mode != mode) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309673 ALOGD("%s: mode %d , prev_mode %d \n", __func__, mode , adev->mode);
9674 adev->prev_mode = adev->mode; /* prev_mode is kept to handle voip concurrency*/
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009675 adev->mode = mode;
Weiyin Jiang96b96f72020-09-22 16:48:19 +08009676 if (mode == AUDIO_MODE_CALL_SCREEN) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309677 adev->current_call_output = adev->primary_output;
9678 voice_start_call(adev);
9679 } else if (voice_is_in_call_or_call_screen(adev) &&
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08009680 (mode == AUDIO_MODE_NORMAL ||
9681 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07009682 list_for_each(node, &adev->usecase_list) {
9683 usecase = node_to_item(node, struct audio_usecase, list);
9684 if (usecase->type == VOICE_CALL)
9685 break;
9686 }
9687 if (usecase &&
9688 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
9689 ret = audio_extn_usb_check_and_set_svc_int(usecase,
9690 true);
9691 if (ret != 0) {
9692 /* default service interval was successfully updated,
9693 reopen USB backend with new service interval */
9694 check_usecases_codec_backend(adev,
9695 usecase,
9696 usecase->out_snd_device);
9697 }
9698 }
9699
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009700 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07009701 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009702 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08009703 // restore device for other active usecases after stop call
9704 list_for_each(node, &adev->usecase_list) {
9705 usecase = node_to_item(node, struct audio_usecase, list);
9706 select_devices(adev, usecase->id);
9707 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009708 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009709 }
9710 pthread_mutex_unlock(&adev->lock);
9711 return 0;
9712}
9713
9714static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
9715{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009716 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08009717 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009718
9719 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08009720 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009721 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009722
Derek Chend2530072014-11-24 12:39:14 -08009723 if (adev->ext_hw_plugin)
9724 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009725
9726 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009727 pthread_mutex_unlock(&adev->lock);
9728
9729 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009730}
9731
9732static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
9733{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009734 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009735 return 0;
9736}
9737
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009738static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009739 const struct audio_config *config)
9740{
Avinash Chandrad7296d42021-08-04 15:07:47 +05309741 bool is_usb_hifi = IS_USB_HIFI;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009742 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009743
Aalique Grahame22e49102018-12-18 14:23:57 -08009744 /* Don't know if USB HIFI in this context so use true to be conservative */
9745 if (check_input_parameters(config->sample_rate, config->format, channel_count,
Avinash Chandrad7296d42021-08-04 15:07:47 +05309746 is_usb_hifi) != 0)
Aalique Grahame22e49102018-12-18 14:23:57 -08009747 return 0;
9748
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009749 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
9750 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009751}
9752
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009753static bool adev_input_allow_hifi_record(struct audio_device *adev,
9754 audio_devices_t devices,
9755 audio_input_flags_t flags,
9756 audio_source_t source) {
9757 const bool allowed = true;
9758
9759 if (!audio_is_usb_in_device(devices))
9760 return !allowed;
9761
9762 switch (flags) {
9763 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009764 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07009765 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
9766 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009767 default:
9768 return !allowed;
9769 }
9770
9771 switch (source) {
9772 case AUDIO_SOURCE_DEFAULT:
9773 case AUDIO_SOURCE_MIC:
9774 case AUDIO_SOURCE_UNPROCESSED:
9775 break;
9776 default:
9777 return !allowed;
9778 }
9779
9780 switch (adev->mode) {
9781 case 0:
9782 break;
9783 default:
9784 return !allowed;
9785 }
9786
9787 return allowed;
9788}
9789
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009790static int adev_update_voice_comm_input_stream(struct stream_in *in,
9791 struct audio_config *config)
9792{
9793 bool valid_rate = (config->sample_rate == 8000 ||
9794 config->sample_rate == 16000 ||
9795 config->sample_rate == 32000 ||
9796 config->sample_rate == 48000);
9797 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
9798
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009799 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08009800 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009801 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9802 in->config = default_pcm_config_voip_copp;
9803 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
9804 DEFAULT_VOIP_BUF_DURATION_MS,
9805 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009806 } else {
9807 ALOGW("%s No valid input in voip, use defaults"
9808 "sample rate %u, channel mask 0x%X",
9809 __func__, config->sample_rate, in->channel_mask);
9810 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009811 in->config.rate = config->sample_rate;
9812 in->sample_rate = config->sample_rate;
9813 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009814 //XXX needed for voice_extn_compress_voip_open_input_stream
9815 in->config.rate = config->sample_rate;
9816 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
Shalini Manjunathaa763cc42019-08-23 15:13:46 +05309817 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009818 voice_extn_compress_voip_is_active(in->dev)) &&
9819 (voice_extn_compress_voip_is_format_supported(in->format)) &&
9820 valid_rate && valid_ch) {
9821 voice_extn_compress_voip_open_input_stream(in);
9822 // update rate entries to match config from AF
9823 in->config.rate = config->sample_rate;
9824 in->sample_rate = config->sample_rate;
9825 } else {
9826 ALOGW("%s compress voip not active, use defaults", __func__);
9827 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009828 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009829 return 0;
9830}
9831
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009832static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07009833 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009834 audio_devices_t devices,
9835 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009836 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309837 audio_input_flags_t flags,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009838 const char *address,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009839 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009840{
9841 struct audio_device *adev = (struct audio_device *)dev;
9842 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009843 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009844 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009845 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05309846 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009847 bool is_usb_dev = audio_is_usb_in_device(devices);
9848 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
9849 devices,
9850 flags,
9851 source);
Andy Hung94320602018-10-29 18:31:12 -07009852 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
9853 " sample_rate %u, channel_mask %#x, format %#x",
9854 __func__, flags, is_usb_dev, may_use_hifi_record,
9855 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309856
kunleizdff872d2018-08-20 14:40:33 +08009857 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08009858 is_usb_dev = false;
9859 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
9860 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
9861 __func__, devices);
9862 }
9863
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009864 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009865
9866 if (!(is_usb_dev && may_use_hifi_record)) {
9867 if (config->sample_rate == 0)
9868 config->sample_rate = 48000;
9869 if (config->channel_mask == AUDIO_CHANNEL_NONE)
9870 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9871 if (config->format == AUDIO_FORMAT_DEFAULT)
9872 config->format = AUDIO_FORMAT_PCM_16_BIT;
9873
9874 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
9875
Aalique Grahame22e49102018-12-18 14:23:57 -08009876 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9877 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009878 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05309879 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009880
9881 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009882
9883 if (!in) {
9884 ALOGE("failed to allocate input stream");
9885 return -ENOMEM;
9886 }
9887
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309888 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05309889 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
9890 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009891 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07009892 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009893
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009894 in->stream.common.get_sample_rate = in_get_sample_rate;
9895 in->stream.common.set_sample_rate = in_set_sample_rate;
9896 in->stream.common.get_buffer_size = in_get_buffer_size;
9897 in->stream.common.get_channels = in_get_channels;
9898 in->stream.common.get_format = in_get_format;
9899 in->stream.common.set_format = in_set_format;
9900 in->stream.common.standby = in_standby;
9901 in->stream.common.dump = in_dump;
9902 in->stream.common.set_parameters = in_set_parameters;
9903 in->stream.common.get_parameters = in_get_parameters;
9904 in->stream.common.add_audio_effect = in_add_audio_effect;
9905 in->stream.common.remove_audio_effect = in_remove_audio_effect;
9906 in->stream.set_gain = in_set_gain;
9907 in->stream.read = in_read;
9908 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08009909 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309910 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07009911 in->stream.set_microphone_direction = in_set_microphone_direction;
9912 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07009913 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009914
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009915 list_init(&in->device_list);
9916 update_device_list(&in->device_list, devices, address, true);
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009917 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009918 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009919 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009920 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009921 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07009922 in->bit_width = 16;
9923 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07009924 in->direction = MIC_DIRECTION_UNSPECIFIED;
9925 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08009926 list_init(&in->aec_list);
9927 list_init(&in->ns_list);
Phil Burkd898ba62019-06-20 12:49:01 -07009928 in->mmap_shared_memory_fd = -1; // not open
Haynes Mathew George46740472017-10-27 18:40:12 -07009929
Andy Hung94320602018-10-29 18:31:12 -07009930 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08009931 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
9932 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
9933 /* Force channel config requested to mono if incall
9934 record is being requested for only uplink/downlink */
9935 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
9936 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9937 ret = -EINVAL;
9938 goto err_open;
9939 }
9940 }
9941
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009942 if (is_usb_dev && may_use_hifi_record) {
9943 /* HiFi record selects an appropriate format, channel, rate combo
9944 depending on sink capabilities*/
9945 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
9946 &config->format,
9947 &in->supported_formats[0],
9948 MAX_SUPPORTED_FORMATS,
9949 &config->channel_mask,
9950 &in->supported_channel_masks[0],
9951 MAX_SUPPORTED_CHANNEL_MASKS,
9952 &config->sample_rate,
9953 &in->supported_sample_rates[0],
9954 MAX_SUPPORTED_SAMPLE_RATES);
9955 if (ret != 0) {
9956 ret = -EINVAL;
9957 goto err_open;
9958 }
9959 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009960 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309961 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05309962 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
9963 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
9964 in->config.format = PCM_FORMAT_S32_LE;
9965 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309966 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
9967 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
9968 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
9969 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
9970 bool ret_error = false;
9971 in->bit_width = 24;
9972 /* 24 bit is restricted to UNPROCESSED source only,also format supported
9973 from HAL is 24_packed and 8_24
9974 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
9975 24_packed return error indicating supported format is 24_packed
9976 *> In case of any other source requesting 24 bit or float return error
9977 indicating format supported is 16 bit only.
9978
9979 on error flinger will retry with supported format passed
9980 */
9981 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
9982 (source != AUDIO_SOURCE_CAMCORDER)) {
9983 config->format = AUDIO_FORMAT_PCM_16_BIT;
9984 if (config->sample_rate > 48000)
9985 config->sample_rate = 48000;
9986 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07009987 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
9988 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309989 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
9990 ret_error = true;
9991 }
9992
9993 if (ret_error) {
9994 ret = -EINVAL;
9995 goto err_open;
9996 }
9997 }
9998
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009999 in->channel_mask = config->channel_mask;
10000 in->format = config->format;
10001
10002 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +053010003
Huicheng Liu1404ba12020-09-11 01:03:25 -040010004 /* validate bus device address */
10005 if (compare_device_type(&in->device_list, AUDIO_DEVICE_IN_BUS)) {
10006 /* extract car audio stream index */
10007 in->car_audio_stream =
10008 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
10009 if (in->car_audio_stream < 0) {
10010 ALOGE("%s: invalid car audio stream %x",
10011 __func__, in->car_audio_stream);
10012 ret = -EINVAL;
10013 goto err_open;
10014 }
10015 ALOGV("%s: car_audio_stream 0x%x", __func__, in->car_audio_stream);
Huicheng Liuea4fd422021-01-12 18:34:50 -050010016 ret = audio_extn_auto_hal_open_input_stream(in);
10017 if (ret) {
10018 ALOGE("%s: Failed to open input stream for bus device", __func__);
10019 ret = -EINVAL;
10020 goto err_open;
10021 }
Huicheng Liu1404ba12020-09-11 01:03:25 -040010022 }
10023
Susan Wange3959562021-03-11 11:50:26 -050010024 /* reassign use case for echo reference stream on automotive platforms */
10025 if (in->source == AUDIO_SOURCE_ECHO_REFERENCE) {
10026 ret = audio_extn_auto_hal_open_echo_reference_stream(in);
10027 }
10028
Kogara Naveen Kumar379ff692022-01-31 11:56:51 +053010029 if ((in->source == AUDIO_SOURCE_FM_TUNER) || (devices == AUDIO_DEVICE_IN_FM_TUNER)) {
Samyak Jain0aa07ab2019-04-04 14:36:32 +053010030 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
10031 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
10032 else {
10033 ret = -EINVAL;
10034 goto err_open;
10035 }
10036 }
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +053010037#ifdef PLATFORM_AUTO
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +053010038 if ((config->sample_rate == 48000 ||
10039 config->sample_rate == 32000 ||
10040 config->sample_rate == 24000 ||
10041 config->sample_rate == 16000 ||
10042 config->sample_rate == 8000)&&
Deeraj Somanfa377bf2019-02-06 12:57:59 +053010043 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
10044 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +053010045 (flags & AUDIO_INPUT_FLAG_FAST) != 0)
10046#else
10047 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
10048 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
10049 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
10050 (flags & AUDIO_INPUT_FLAG_FAST) != 0)
10051#endif
10052{
Haynes Mathew George484e8d22017-07-31 18:55:17 -070010053 is_low_latency = true;
10054#if LOW_LATENCY_CAPTURE_USE_CASE
Revathi Uddarajud9f23d92020-07-27 10:55:06 +053010055 if ((flags & AUDIO_INPUT_FLAG_VOIP_TX) != 0)
10056 in->usecase = USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY;
10057 else
10058 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Haynes Mathew George484e8d22017-07-31 18:55:17 -070010059#endif
10060 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -080010061 if (!in->realtime) {
10062 in->config = pcm_config_audio_capture;
10063 frame_size = audio_stream_in_frame_size(&in->stream);
10064 buffer_size = get_input_buffer_size(config->sample_rate,
10065 config->format,
10066 channel_count,
10067 is_low_latency);
10068 in->config.period_size = buffer_size / frame_size;
10069 in->config.rate = config->sample_rate;
10070 in->af_period_multiplier = 1;
10071 } else {
10072 // period size is left untouched for rt mode playback
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +053010073#ifdef PLATFORM_AUTO
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +053010074 switch(config->sample_rate)
10075 {
10076 case 48000:
10077 in->config = pcm_config_audio_capture_rt_48KHz;
10078 break;
10079 case 32000:
10080 in->config = pcm_config_audio_capture_rt_32KHz;
10081 break;
10082 case 24000:
10083 in->config = pcm_config_audio_capture_rt_24KHz;
10084 break;
10085 case 16000:
10086 in->config = pcm_config_audio_capture_rt_16KHz;
10087 break;
10088 case 8000:
10089 in->config = pcm_config_audio_capture_rt_8KHz;
10090 break;
10091 default:
10092 in->config = pcm_config_audio_capture_rt_48KHz;
10093 }
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +053010094#else
10095 in->config = pcm_config_audio_capture_rt_48KHz;
10096#endif
Aalique Grahame22e49102018-12-18 14:23:57 -080010097 in->af_period_multiplier = af_period_multiplier;
10098 }
Kogara Naveen Kumarc5758232022-11-07 20:25:40 +053010099
10100 /* assign concurrent capture usecase if record has to caried out from
10101 * actual hardware input source */
10102 if (audio_extn_is_concurrent_capture_enabled() &&
10103 !audio_is_virtual_input_source(in->source)) {
10104 /* Acquire lock to avoid two concurrent use cases initialized to
10105 same pcm record use case */
10106 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY) {
10107 pthread_mutex_lock(&adev->lock);
10108 if (!(adev->pcm_low_latency_record_uc_state)) {
10109 ALOGD("%s: using USECASE_AUDIO_RECORD_LOW_LATENCY",__func__);
10110 adev->pcm_low_latency_record_uc_state = 1;
10111 pthread_mutex_unlock(&adev->lock);
10112 } else if (audio_extn_is_concurrent_low_latency_pcm_record_enabled()) {
10113 in->usecase = get_low_latency_record_usecase(adev);
10114 pthread_mutex_unlock(&adev->lock);
10115 } else {
10116 pthread_mutex_unlock(&adev->lock);
10117 /* Assign compress record use case for second record */
10118 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
10119 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
10120 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
10121 if (audio_extn_cin_applicable_stream(in)) {
10122 in->sample_rate = config->sample_rate;
10123 ret = audio_extn_cin_configure_input_stream(in, config);
10124 if (ret)
10125 goto err_open;
10126 }
10127 }
10128 }
10129 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -070010130 }
10131
Susan Wangb803cb52021-10-14 12:03:36 -040010132 /* Additional sample rates added below must also be present
10133 in audio_policy_configuration.xml for mmap_no_irq_in */
10134 bool valid_mmap_record_rate = (config->sample_rate == 8000 ||
10135 config->sample_rate == 16000 ||
Susan Wang89da9042021-10-14 12:03:36 -040010136 config->sample_rate == 24000 ||
Susan Wangb803cb52021-10-14 12:03:36 -040010137 config->sample_rate == 32000 ||
10138 config->sample_rate == 48000);
10139 if (valid_mmap_record_rate &&
10140 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -070010141 in->realtime = 0;
10142 in->usecase = USECASE_AUDIO_RECORD_MMAP;
10143 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -070010144 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -070010145 in->stream.start = in_start;
10146 in->stream.stop = in_stop;
10147 in->stream.create_mmap_buffer = in_create_mmap_buffer;
10148 in->stream.get_mmap_position = in_get_mmap_position;
Ramjee Singhbcb3b6c2021-11-17 13:19:16 +053010149 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -070010150 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
Haynes Mathew George46740472017-10-27 18:40:12 -070010151 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -070010152 in->usecase = USECASE_AUDIO_RECORD_HIFI;
10153 in->config = pcm_config_audio_capture;
10154 frame_size = audio_stream_in_frame_size(&in->stream);
10155 buffer_size = get_input_buffer_size(config->sample_rate,
10156 config->format,
10157 channel_count,
10158 false /*is_low_latency*/);
10159 in->config.period_size = buffer_size / frame_size;
10160 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -070010161 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -070010162 switch (config->format) {
10163 case AUDIO_FORMAT_PCM_32_BIT:
10164 in->bit_width = 32;
10165 break;
10166 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
10167 case AUDIO_FORMAT_PCM_8_24_BIT:
10168 in->bit_width = 24;
10169 break;
10170 default:
10171 in->bit_width = 16;
10172 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010173 } else if (is_single_device_type_equal(&in->device_list,
10174 AUDIO_DEVICE_IN_TELEPHONY_RX) ||
10175 is_single_device_type_equal(&in->device_list,
10176 AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070010177 if (config->sample_rate == 0)
10178 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
10179 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
10180 config->sample_rate != 8000) {
10181 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
10182 ret = -EINVAL;
10183 goto err_open;
10184 }
10185 if (config->format == AUDIO_FORMAT_DEFAULT)
10186 config->format = AUDIO_FORMAT_PCM_16_BIT;
10187 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
10188 config->format = AUDIO_FORMAT_PCM_16_BIT;
10189 ret = -EINVAL;
10190 goto err_open;
10191 }
10192
10193 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
Zhou Song62ea0282020-03-22 19:53:01 +080010194 if (adev->ha_proxy_enable &&
10195 is_single_device_type_equal(&in->device_list,
10196 AUDIO_DEVICE_IN_TELEPHONY_RX))
10197 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY2;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070010198 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070010199 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -080010200 in->af_period_multiplier = 1;
10201 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
Shalini Manjunathaac412b32020-01-03 15:00:14 +053010202 (!voice_extn_is_compress_voip_supported()) &&
Aalique Grahame22e49102018-12-18 14:23:57 -080010203 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
10204 (config->sample_rate == 8000 ||
10205 config->sample_rate == 16000 ||
10206 config->sample_rate == 32000 ||
10207 config->sample_rate == 48000) &&
10208 channel_count == 1) {
10209 in->usecase = USECASE_AUDIO_RECORD_VOIP;
10210 in->config = pcm_config_audio_capture;
10211 frame_size = audio_stream_in_frame_size(&in->stream);
10212 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
10213 config->sample_rate,
10214 config->format,
10215 channel_count, false /*is_low_latency*/);
10216 in->config.period_size = buffer_size / frame_size;
10217 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
10218 in->config.rate = config->sample_rate;
10219 in->af_period_multiplier = 1;
Mingshu Pangc2d65042021-01-14 16:19:10 +080010220 } else if (in->realtime) {
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +053010221#ifdef PLATFORM_AUTO
Kogara Naveen Kumara688a812022-04-27 16:45:59 +053010222 switch(config->sample_rate)
10223 {
10224 case 48000:
10225 in->config = pcm_config_audio_capture_rt_48KHz;
10226 break;
10227 case 32000:
10228 in->config = pcm_config_audio_capture_rt_32KHz;
10229 break;
10230 case 24000:
10231 in->config = pcm_config_audio_capture_rt_24KHz;
10232 break;
10233 case 16000:
10234 in->config = pcm_config_audio_capture_rt_16KHz;
10235 break;
10236 case 8000:
10237 in->config = pcm_config_audio_capture_rt_8KHz;
10238 break;
10239 default:
10240 in->config = pcm_config_audio_capture_rt_48KHz;
10241 }
Mingshu Pangc2d65042021-01-14 16:19:10 +080010242 in->config.format = pcm_format_from_audio_format(config->format);
10243 in->af_period_multiplier = af_period_multiplier;
Krishna Kishor Jhac1542b22022-08-22 13:12:09 +053010244#else
10245 in->config = pcm_config_audio_capture_rt_48KHz;
10246#endif
10247} else {
Revathi Uddarajud2634032017-12-07 14:42:34 +053010248 int ret_val;
10249 pthread_mutex_lock(&adev->lock);
10250 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
10251 in, config, &channel_mask_updated);
10252 pthread_mutex_unlock(&adev->lock);
10253
10254 if (!ret_val) {
10255 if (channel_mask_updated == true) {
10256 ALOGD("%s: return error to retry with updated channel mask (%#x)",
10257 __func__, config->channel_mask);
10258 ret = -EINVAL;
10259 goto err_open;
10260 }
10261 ALOGD("%s: created multi-channel session succesfully",__func__);
10262 } else if (audio_extn_compr_cap_enabled() &&
10263 audio_extn_compr_cap_format_supported(config->format) &&
10264 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
10265 audio_extn_compr_cap_init(in);
10266 } else if (audio_extn_cin_applicable_stream(in)) {
Deeraj Soman14230922019-01-30 16:39:30 +053010267 ret = audio_extn_cin_configure_input_stream(in, config);
Revathi Uddarajud2634032017-12-07 14:42:34 +053010268 if (ret)
10269 goto err_open;
10270 } else {
10271 in->config = pcm_config_audio_capture;
10272 in->config.rate = config->sample_rate;
10273 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +053010274 in->format = config->format;
10275 frame_size = audio_stream_in_frame_size(&in->stream);
10276 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -070010277 config->format,
10278 channel_count,
10279 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +020010280 /* prevent division-by-zero */
10281 if (frame_size == 0) {
10282 ALOGE("%s: Error frame_size==0", __func__);
10283 ret = -EINVAL;
10284 goto err_open;
10285 }
10286
Revathi Uddarajud2634032017-12-07 14:42:34 +053010287 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -080010288 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -080010289
Revathi Uddarajud2634032017-12-07 14:42:34 +053010290 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
10291 /* optionally use VOIP usecase depending on config(s) */
10292 ret = adev_update_voice_comm_input_stream(in, config);
10293 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -080010294
Revathi Uddarajud2634032017-12-07 14:42:34 +053010295 if (ret) {
10296 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
10297 goto err_open;
10298 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -080010299 }
Jaideep Sharmad305a4a2020-02-27 14:29:04 +053010300
10301 /* assign concurrent capture usecase if record has to caried out from
10302 * actual hardware input source */
10303 if (audio_extn_is_concurrent_capture_enabled() &&
10304 !audio_is_virtual_input_source(in->source)) {
Samyak Jainc37062f2019-04-25 18:41:06 +053010305 /* Acquire lock to avoid two concurrent use cases initialized to
10306 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +080010307
Samyak Jainc37062f2019-04-25 18:41:06 +053010308 if (in->usecase == USECASE_AUDIO_RECORD) {
10309 pthread_mutex_lock(&adev->lock);
10310 if (!(adev->pcm_record_uc_state)) {
10311 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
10312 adev->pcm_record_uc_state = 1;
10313 pthread_mutex_unlock(&adev->lock);
Krishna Kishor Jha0f4d8482022-02-18 10:56:05 +053010314 } else if (audio_extn_is_concurrent_pcm_record_enabled()) {
10315 in->usecase = get_record_usecase(adev);
10316 pthread_mutex_unlock(&adev->lock);
Samyak Jainc37062f2019-04-25 18:41:06 +053010317 } else {
10318 pthread_mutex_unlock(&adev->lock);
10319 /* Assign compress record use case for second record */
10320 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
10321 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
10322 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
10323 if (audio_extn_cin_applicable_stream(in)) {
10324 in->sample_rate = config->sample_rate;
Deeraj Soman14230922019-01-30 16:39:30 +053010325 ret = audio_extn_cin_configure_input_stream(in, config);
Samyak Jainc37062f2019-04-25 18:41:06 +053010326 if (ret)
10327 goto err_open;
10328 }
10329 }
10330 }
kunleiz28c73e72019-03-27 17:24:04 +080010331 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -070010332 }
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +053010333
Ramjee Singh82fd0c12019-08-21 16:31:33 +053010334 if (audio_extn_ssr_get_stream() != in)
10335 in->config.channels = channel_count;
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -070010336
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -070010337 in->sample_rate = in->config.rate;
10338
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010339 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
10340 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010341 &in->device_list, flags, in->format,
Haynes Mathew George4ffef292017-11-21 15:08:02 -080010342 in->sample_rate, in->bit_width,
10343 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +053010344 register_format(in->format, in->supported_formats);
10345 register_channel_mask(in->channel_mask, in->supported_channel_masks);
10346 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010347
Dechen Chai22768452021-07-30 09:29:16 +053010348#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -080010349 in->error_log = error_log_create(
10350 ERROR_LOG_ENTRIES,
10351 1000000000 /* aggregate consecutive identical errors within one second */);
Dechen Chai22768452021-07-30 09:29:16 +053010352#endif
Aalique Grahame22e49102018-12-18 14:23:57 -080010353
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010354 /* This stream could be for sound trigger lab,
10355 get sound trigger pcm if present */
10356 audio_extn_sound_trigger_check_and_get_session(in);
10357
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010358 lock_input_stream(in);
10359 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
10360 pthread_mutex_lock(&adev->lock);
10361 in->card_status = adev->card_status;
10362 pthread_mutex_unlock(&adev->lock);
10363 pthread_mutex_unlock(&in->lock);
10364
Aalique Grahame22e49102018-12-18 14:23:57 -080010365 stream_app_type_cfg_init(&in->app_type_cfg);
10366
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010367 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -080010368
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010369 ret = io_streams_map_insert(adev, &in->stream.common,
10370 handle, AUDIO_PATCH_HANDLE_NONE);
10371 if (ret != 0)
10372 goto err_open;
10373
Susan Wang6dd13092021-01-25 10:27:11 -050010374 in->in_ctxt.input = in;
Derek Chenf939fb72018-11-13 13:34:41 -080010375
10376 pthread_mutex_lock(&adev->lock);
Susan Wang6dd13092021-01-25 10:27:11 -050010377 list_add_tail(&adev->active_inputs_list, &in->in_ctxt.list);
Derek Chenf939fb72018-11-13 13:34:41 -080010378 pthread_mutex_unlock(&adev->lock);
10379
Eric Laurent994a6932013-07-17 11:51:42 -070010380 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -080010381 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010382
10383err_open:
Krishna Kishor Jha0f4d8482022-02-18 10:56:05 +053010384 if (audio_extn_is_concurrent_pcm_record_enabled() && is_pcm_record_usecase(in->usecase)) {
10385 free_record_usecase(adev, in->usecase);
10386 } else if (in->usecase == USECASE_AUDIO_RECORD) {
Samyak Jainc37062f2019-04-25 18:41:06 +053010387 pthread_mutex_lock(&adev->lock);
10388 adev->pcm_record_uc_state = 0;
10389 pthread_mutex_unlock(&adev->lock);
10390 }
Kogara Naveen Kumarc5758232022-11-07 20:25:40 +053010391 if (audio_extn_is_concurrent_low_latency_pcm_record_enabled() && is_pcm_low_latency_record_usecase(in->usecase)) {
10392 free_low_latency_record_usecase(adev, in->usecase);
10393 } else if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY) {
10394 pthread_mutex_lock(&adev->lock);
10395 adev->pcm_low_latency_record_uc_state = 0;
10396 pthread_mutex_unlock(&adev->lock);
10397 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010398 free(in);
10399 *stream_in = NULL;
10400 return ret;
10401}
10402
10403static void adev_close_input_stream(struct audio_hw_device *dev,
10404 struct audio_stream_in *stream)
10405{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080010406 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -070010407 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -070010408 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +053010409
Sidipotu Ashokf43018c2014-05-02 16:21:50 +053010410 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080010411
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010412 if (in == NULL) {
10413 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
10414 return;
10415 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010416 io_streams_map_remove(adev, in->capture_handle);
10417
Susan Wang6dd13092021-01-25 10:27:11 -050010418 // remove out_ctxt early to prevent the stream
10419 // being opened in a race condition
10420 pthread_mutex_lock(&adev->lock);
10421 list_remove(&in->in_ctxt.list);
10422 pthread_mutex_unlock(&adev->lock);
10423
kunleiz70e57612018-12-28 17:50:23 +080010424 /* must deregister from sndmonitor first to prevent races
10425 * between the callback and close_stream
10426 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010427 audio_extn_snd_mon_unregister_listener(stream);
10428
kunleiz70e57612018-12-28 17:50:23 +080010429 /* Disable echo reference if there are no active input, hfp call
10430 * and sound trigger while closing input stream
10431 */
Eric Laurent637e2d42018-11-15 12:24:31 -080010432 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +080010433 !audio_extn_hfp_is_active(adev) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010434 !audio_extn_sound_trigger_check_ec_ref_enable()) {
10435 struct listnode out_devices;
10436 list_init(&out_devices);
10437 platform_set_echo_reference(adev, false, &out_devices);
Zhenlin Lian4f947842022-05-14 15:50:52 +053010438 clear_devices(&out_devices);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010439 } else
kunleiz70e57612018-12-28 17:50:23 +080010440 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +053010441
Dechen Chai22768452021-07-30 09:29:16 +053010442#ifndef LINUX_ENABLED
Weiyin Jiang2995f662019-04-17 14:25:12 +080010443 error_log_destroy(in->error_log);
10444 in->error_log = NULL;
Dechen Chai22768452021-07-30 09:29:16 +053010445#endif
Pallavid7c7a272018-01-16 11:22:55 +053010446
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080010447 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +053010448 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080010449 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +053010450 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080010451 if (ret != 0)
10452 ALOGE("%s: Compress voip input cannot be closed, error:%d",
10453 __func__, ret);
10454 } else
10455 in_standby(&stream->common);
10456
Weiyin Jiang280ea742020-09-08 20:28:22 +080010457 pthread_mutex_destroy(&in->lock);
10458 pthread_mutex_destroy(&in->pre_lock);
10459
Revathi Uddarajud2634032017-12-07 14:42:34 +053010460 pthread_mutex_lock(&adev->lock);
Krishna Kishor Jha0f4d8482022-02-18 10:56:05 +053010461 if (audio_extn_is_concurrent_pcm_record_enabled() && is_pcm_record_usecase(in->usecase)) {
10462 free_record_usecase(adev, in->usecase);
10463 } else if (in->usecase == USECASE_AUDIO_RECORD) {
Samyak Jain15fda662018-12-18 16:40:52 +053010464 adev->pcm_record_uc_state = 0;
10465 }
10466
Kogara Naveen Kumarc5758232022-11-07 20:25:40 +053010467 if (audio_extn_is_concurrent_low_latency_pcm_record_enabled() && is_pcm_low_latency_record_usecase(in->usecase)) {
10468 free_low_latency_record_usecase(adev, in->usecase);
10469 } else if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY) {
10470 adev->pcm_low_latency_record_uc_state = 0;
10471 }
10472
Kunlei Zhang5d5d8d92020-02-26 15:00:59 +080010473 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
10474 adev->enable_voicerx = false;
10475 }
10476
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -070010477 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -070010478 audio_extn_ssr_deinit();
10479 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010480
Garmond Leunge2433c32017-09-28 21:51:22 -070010481 if (audio_extn_ffv_get_stream() == in) {
10482 audio_extn_ffv_stream_deinit();
10483 }
10484
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010485 if (audio_extn_compr_cap_enabled() &&
Subhadra Jagadeesan63a1e832023-01-13 11:26:38 +053010486 audio_extn_compr_cap_format_supported(pcm_format_to_audio_format((in->config).format)))
Mingming Yine62d7842013-10-25 16:26:03 -070010487 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +053010488
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +053010489 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +053010490 audio_extn_cin_free_input_stream_resources(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010491
Mingming Yinfd7607b2016-01-22 12:48:44 -080010492 if (in->is_st_session) {
10493 ALOGV("%s: sound trigger pcm stop lab", __func__);
10494 audio_extn_sound_trigger_stop_lab(in);
10495 }
Zhenlin Lian4f947842022-05-14 15:50:52 +053010496 clear_devices(&in->device_list);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010497 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +053010498 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010499 return;
10500}
10501
Aalique Grahame22e49102018-12-18 14:23:57 -080010502/* verifies input and output devices and their capabilities.
10503 *
10504 * This verification is required when enabling extended bit-depth or
10505 * sampling rates, as not all qcom products support it.
10506 *
10507 * Suitable for calling only on initialization such as adev_open().
10508 * It fills the audio_device use_case_table[] array.
10509 *
10510 * Has a side-effect that it needs to configure audio routing / devices
10511 * in order to power up the devices and read the device parameters.
10512 * It does not acquire any hw device lock. Should restore the devices
10513 * back to "normal state" upon completion.
10514 */
10515static int adev_verify_devices(struct audio_device *adev)
10516{
10517 /* enumeration is a bit difficult because one really wants to pull
10518 * the use_case, device id, etc from the hidden pcm_device_table[].
10519 * In this case there are the following use cases and device ids.
10520 *
10521 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
10522 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
10523 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
10524 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
10525 * [USECASE_AUDIO_RECORD] = {0, 0},
10526 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
10527 * [USECASE_VOICE_CALL] = {2, 2},
10528 *
10529 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
10530 * USECASE_VOICE_CALL omitted, but possible for either input or output.
10531 */
10532
10533 /* should be the usecases enabled in adev_open_input_stream() */
10534 static const int test_in_usecases[] = {
10535 USECASE_AUDIO_RECORD,
10536 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
10537 };
10538 /* should be the usecases enabled in adev_open_output_stream()*/
10539 static const int test_out_usecases[] = {
10540 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
10541 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
10542 };
10543 static const usecase_type_t usecase_type_by_dir[] = {
10544 PCM_PLAYBACK,
10545 PCM_CAPTURE,
10546 };
10547 static const unsigned flags_by_dir[] = {
10548 PCM_OUT,
10549 PCM_IN,
10550 };
10551
10552 size_t i;
10553 unsigned dir;
10554 const unsigned card_id = adev->snd_card;
10555
10556 for (dir = 0; dir < 2; ++dir) {
10557 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
10558 const unsigned flags_dir = flags_by_dir[dir];
10559 const size_t testsize =
10560 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
10561 const int *testcases =
10562 dir ? test_in_usecases : test_out_usecases;
10563 const audio_devices_t audio_device =
10564 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
10565
10566 for (i = 0; i < testsize; ++i) {
10567 const audio_usecase_t audio_usecase = testcases[i];
10568 int device_id;
10569 struct pcm_params **pparams;
10570 struct stream_out out;
10571 struct stream_in in;
10572 struct audio_usecase uc_info;
10573 int retval;
10574
10575 pparams = &adev->use_case_table[audio_usecase];
10576 pcm_params_free(*pparams); /* can accept null input */
10577 *pparams = NULL;
10578
10579 /* find the device ID for the use case (signed, for error) */
10580 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
10581 if (device_id < 0)
10582 continue;
10583
10584 /* prepare structures for device probing */
10585 memset(&uc_info, 0, sizeof(uc_info));
10586 uc_info.id = audio_usecase;
10587 uc_info.type = usecase_type;
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010588 list_init(&uc_info.device_list);
Aalique Grahame22e49102018-12-18 14:23:57 -080010589 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -080010590 memset(&in, 0, sizeof(in));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010591 list_init(&in.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010592 update_device_list(&in.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -080010593 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
10594 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -080010595 }
10596 memset(&out, 0, sizeof(out));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010597 list_init(&out.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010598 update_device_list(&out.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -080010599 uc_info.stream.out = &out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010600 update_device_list(&uc_info.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -080010601 uc_info.in_snd_device = SND_DEVICE_NONE;
10602 uc_info.out_snd_device = SND_DEVICE_NONE;
10603 list_add_tail(&adev->usecase_list, &uc_info.list);
10604
10605 /* select device - similar to start_(in/out)put_stream() */
10606 retval = select_devices(adev, audio_usecase);
10607 if (retval >= 0) {
10608 *pparams = pcm_params_get(card_id, device_id, flags_dir);
10609#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -070010610 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -080010611 if (*pparams) {
10612 ALOGV("%s: (%s) card %d device %d", __func__,
10613 dir ? "input" : "output", card_id, device_id);
10614 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
10615 } else {
10616 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
10617 }
10618#endif
10619 }
10620
10621 /* deselect device - similar to stop_(in/out)put_stream() */
10622 /* 1. Get and set stream specific mixer controls */
10623 retval = disable_audio_route(adev, &uc_info);
10624 /* 2. Disable the rx device */
10625 retval = disable_snd_device(adev,
10626 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
10627 list_remove(&uc_info.list);
10628 }
10629 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010630 return 0;
10631}
10632
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010633int update_patch(unsigned int num_sources,
10634 const struct audio_port_config *sources,
10635 unsigned int num_sinks,
10636 const struct audio_port_config *sinks,
10637 audio_patch_handle_t handle,
10638 struct audio_patch_info *p_info,
10639 patch_type_t patch_type, bool new_patch)
10640{
Aniket Kumar Latad13758f2020-08-06 15:11:36 -070010641 ALOGV("%s: enter", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010642
10643 if (p_info == NULL) {
10644 ALOGE("%s: Invalid patch pointer", __func__);
10645 return -EINVAL;
10646 }
10647
10648 if (new_patch) {
10649 p_info->patch = (struct audio_patch *) calloc(1, sizeof(struct audio_patch));
10650 if (p_info->patch == NULL) {
10651 ALOGE("%s: Could not allocate patch", __func__);
10652 return -ENOMEM;
10653 }
10654 }
10655
10656 p_info->patch->id = handle;
10657 p_info->patch->num_sources = num_sources;
10658 p_info->patch->num_sinks = num_sinks;
10659
10660 for (int i = 0; i < num_sources; i++)
10661 p_info->patch->sources[i] = sources[i];
10662 for (int i = 0; i < num_sinks; i++)
10663 p_info->patch->sinks[i] = sinks[i];
10664
10665 p_info->patch_type = patch_type;
10666 return 0;
10667}
10668
10669audio_patch_handle_t generate_patch_handle()
10670{
10671 static audio_patch_handle_t patch_handle = AUDIO_PATCH_HANDLE_NONE;
10672 if (++patch_handle < 0)
10673 patch_handle = AUDIO_PATCH_HANDLE_NONE + 1;
10674 return patch_handle;
10675}
10676
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010677int adev_create_audio_patch(struct audio_hw_device *dev,
10678 unsigned int num_sources,
10679 const struct audio_port_config *sources,
10680 unsigned int num_sinks,
10681 const struct audio_port_config *sinks,
10682 audio_patch_handle_t *handle)
10683{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010684 int ret = 0;
10685 struct audio_device *adev = (struct audio_device *)dev;
10686 struct audio_patch_info *p_info = NULL;
10687 patch_type_t patch_type = PATCH_NONE;
10688 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10689 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
10690 struct audio_stream_info *s_info = NULL;
10691 struct audio_stream *stream = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010692 struct listnode devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010693 audio_devices_t device_type = AUDIO_DEVICE_NONE;
10694 bool new_patch = false;
10695 char addr[AUDIO_DEVICE_MAX_ADDRESS_LEN];
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010696
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010697 ALOGD("%s: enter: num sources %d, num_sinks %d, handle %d", __func__,
10698 num_sources, num_sinks, *handle);
10699
10700 if (num_sources == 0 || num_sources > AUDIO_PATCH_PORTS_MAX ||
10701 num_sinks == 0 || num_sinks > AUDIO_PATCH_PORTS_MAX) {
10702 ALOGE("%s: Invalid patch arguments", __func__);
10703 ret = -EINVAL;
10704 goto done;
10705 }
10706
10707 if (num_sources > 1) {
10708 ALOGE("%s: Multiple sources are not supported", __func__);
10709 ret = -EINVAL;
10710 goto done;
10711 }
10712
10713 if (sources == NULL || sinks == NULL) {
10714 ALOGE("%s: Invalid sources or sinks port config", __func__);
10715 ret = -EINVAL;
10716 goto done;
10717 }
10718
10719 ALOGV("%s: source role %d, source type %d", __func__,
10720 sources[0].type, sources[0].role);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010721 list_init(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010722
10723 // Populate source/sink information and fetch stream info
10724 switch (sources[0].type) {
10725 case AUDIO_PORT_TYPE_DEVICE: // Patch for audio capture or loopback
10726 device_type = sources[0].ext.device.type;
10727 strlcpy(&addr[0], &sources[0].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010728 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010729 if (sinks[0].type == AUDIO_PORT_TYPE_MIX) {
10730 patch_type = PATCH_CAPTURE;
10731 io_handle = sinks[0].ext.mix.handle;
10732 input_source = sinks[0].ext.mix.usecase.source;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010733 ALOGD("%s: Capture patch from device %x to mix %d",
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010734 __func__, device_type, io_handle);
10735 } else {
10736 // Device to device patch is not implemented.
10737 // This space will need changes if audio HAL
10738 // handles device to device patches in the future.
10739 patch_type = PATCH_DEVICE_LOOPBACK;
10740 }
10741 break;
10742 case AUDIO_PORT_TYPE_MIX: // Patch for audio playback
10743 io_handle = sources[0].ext.mix.handle;
10744 for (int i = 0; i < num_sinks; i++) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010745 device_type = sinks[i].ext.device.type;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010746 strlcpy(&addr[0], &sinks[i].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010747 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010748 }
10749 patch_type = PATCH_PLAYBACK;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010750 ALOGD("%s: Playback patch from mix handle %d to device %x",
10751 __func__, io_handle, get_device_types(&devices));
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010752 break;
10753 case AUDIO_PORT_TYPE_SESSION:
10754 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010755 ALOGE("%s: Unsupported source type %d", __func__, sources[0].type);
10756 ret = -EINVAL;
10757 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010758 }
10759
10760 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010761
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010762 // Generate patch info and update patch
10763 if (*handle == AUDIO_PATCH_HANDLE_NONE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010764 *handle = generate_patch_handle();
10765 p_info = (struct audio_patch_info *)
10766 calloc(1, sizeof(struct audio_patch_info));
10767 if (p_info == NULL) {
10768 ALOGE("%s: Failed to allocate memory", __func__);
10769 pthread_mutex_unlock(&adev->lock);
10770 ret = -ENOMEM;
10771 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010772 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010773 new_patch = true;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010774 } else {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010775 p_info = fetch_patch_info_l(adev, *handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010776 if (p_info == NULL) {
10777 ALOGE("%s: Unable to fetch patch for received patch handle %d",
10778 __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010779 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010780 ret = -EINVAL;
10781 goto done;
10782 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010783 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010784 update_patch(num_sources, sources, num_sinks, sinks,
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010785 *handle, p_info, patch_type, new_patch);
10786
10787 // Fetch stream info of associated mix for playback or capture patches
10788 if (p_info->patch_type == PATCH_PLAYBACK ||
10789 p_info->patch_type == PATCH_CAPTURE) {
10790 s_info = hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10791 if (s_info == NULL) {
10792 ALOGE("%s: Failed to obtain stream info", __func__);
10793 if (new_patch)
10794 free(p_info);
10795 pthread_mutex_unlock(&adev->lock);
10796 ret = -EINVAL;
10797 goto done;
10798 }
10799 ALOGV("%s: Fetched stream info with io_handle %d", __func__, io_handle);
10800 s_info->patch_handle = *handle;
10801 stream = s_info->stream;
10802 }
10803 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010804
10805 // Update routing for stream
10806 if (stream != NULL) {
Revathi Uddaraju4255a632021-12-02 05:11:13 -080010807 if (p_info->patch_type == PATCH_PLAYBACK) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010808 ret = route_output_stream((struct stream_out *) stream, &devices);
Revathi Uddaraju4255a632021-12-02 05:11:13 -080010809 } else if (p_info->patch_type == PATCH_CAPTURE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010810 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Revathi Uddaraju4255a632021-12-02 05:11:13 -080010811 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010812 if (ret < 0) {
10813 pthread_mutex_lock(&adev->lock);
10814 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10815 if (new_patch)
10816 free(p_info);
10817 pthread_mutex_unlock(&adev->lock);
10818 ALOGE("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10819 goto done;
10820 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010821 }
10822
10823 // Add new patch to patch map
10824 if (!ret && new_patch) {
10825 pthread_mutex_lock(&adev->lock);
10826 hashmapPut(adev->patch_map, (void *) (intptr_t) *handle, (void *) p_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010827 ALOGD("%s: Added a new patch with handle %d", __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010828 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010829 }
10830
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010831done:
Zhenlin Lian4f947842022-05-14 15:50:52 +053010832 clear_devices(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010833 audio_extn_hw_loopback_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010834 num_sources,
10835 sources,
10836 num_sinks,
10837 sinks,
10838 handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010839 audio_extn_auto_hal_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010840 num_sources,
10841 sources,
10842 num_sinks,
10843 sinks,
10844 handle);
10845 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010846}
10847
10848int adev_release_audio_patch(struct audio_hw_device *dev,
10849 audio_patch_handle_t handle)
10850{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010851 struct audio_device *adev = (struct audio_device *) dev;
10852 int ret = 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010853 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010854 struct audio_stream *stream = NULL;
Derek Chenf939fb72018-11-13 13:34:41 -080010855
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010856 if (handle == AUDIO_PATCH_HANDLE_NONE) {
10857 ALOGE("%s: Invalid patch handle %d", __func__, handle);
10858 ret = -EINVAL;
10859 goto done;
10860 }
10861
10862 ALOGD("%s: Remove patch with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010863 pthread_mutex_lock(&adev->lock);
10864 struct audio_patch_info *p_info = fetch_patch_info_l(adev, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010865 if (p_info == NULL) {
10866 ALOGE("%s: Patch info not found with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010867 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010868 ret = -EINVAL;
10869 goto done;
10870 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010871 struct audio_patch *patch = p_info->patch;
10872 if (patch == NULL) {
10873 ALOGE("%s: Patch not found for handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010874 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010875 ret = -EINVAL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010876 goto done;
10877 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010878 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10879 switch (patch->sources[0].type) {
10880 case AUDIO_PORT_TYPE_MIX:
10881 io_handle = patch->sources[0].ext.mix.handle;
10882 break;
10883 case AUDIO_PORT_TYPE_DEVICE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010884 if (p_info->patch_type == PATCH_CAPTURE)
10885 io_handle = patch->sinks[0].ext.mix.handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010886 break;
10887 case AUDIO_PORT_TYPE_SESSION:
10888 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010889 pthread_mutex_unlock(&adev->lock);
10890 ret = -EINVAL;
10891 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010892 }
10893
10894 // Remove patch and reset patch handle in stream info
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010895 patch_type_t patch_type = p_info->patch_type;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010896 patch_map_remove_l(adev, handle);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010897 if (patch_type == PATCH_PLAYBACK ||
10898 patch_type == PATCH_CAPTURE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010899 struct audio_stream_info *s_info =
10900 hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10901 if (s_info == NULL) {
10902 ALOGE("%s: stream for io_handle %d is not available", __func__, io_handle);
10903 pthread_mutex_unlock(&adev->lock);
10904 goto done;
10905 }
10906 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10907 stream = s_info->stream;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010908 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010909 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010910
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010911 if (stream != NULL) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010912 struct listnode devices;
10913 list_init(&devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010914 if (patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010915 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010916 else if (patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010917 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Zhenlin Lian4f947842022-05-14 15:50:52 +053010918 clear_devices(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010919 }
10920
10921 if (ret < 0)
10922 ALOGW("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10923
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010924done:
10925 audio_extn_hw_loopback_release_audio_patch(dev, handle);
10926 audio_extn_auto_hal_release_audio_patch(dev, handle);
10927
10928 ALOGV("%s: Successfully released patch %d", __func__, handle);
Derek Chenf939fb72018-11-13 13:34:41 -080010929 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010930}
10931
10932int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
10933{
Derek Chenf13dd492018-11-13 14:53:51 -080010934 int ret = 0;
10935
10936 ret = audio_extn_hw_loopback_get_audio_port(dev, config);
10937 ret |= audio_extn_auto_hal_get_audio_port(dev, config);
10938 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010939}
10940
10941int adev_set_audio_port_config(struct audio_hw_device *dev,
10942 const struct audio_port_config *config)
10943{
Derek Chenf13dd492018-11-13 14:53:51 -080010944 int ret = 0;
10945
10946 ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
10947 ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
10948 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010949}
10950
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -070010951static int adev_dump(const audio_hw_device_t *device __unused,
10952 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010953{
10954 return 0;
10955}
10956
10957static int adev_close(hw_device_t *device)
10958{
Aalique Grahame22e49102018-12-18 14:23:57 -080010959 size_t i;
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010960 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -070010961
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010962 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -070010963 return 0;
10964
10965 pthread_mutex_lock(&adev_init_lock);
10966
10967 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +053010968 if (audio_extn_spkr_prot_is_enabled())
10969 audio_extn_spkr_prot_deinit();
Jaideep Sharmaa2b49672019-09-10 20:37:03 +053010970 audio_extn_battery_properties_listener_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010971 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010972 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -080010973 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010974 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -080010975 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010976 audio_extn_utils_release_streams_cfg_lists(
10977 &adev->streams_output_cfg_list,
10978 &adev->streams_input_cfg_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010979 if (audio_extn_qap_is_enabled())
10980 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010981 if (audio_extn_qaf_is_enabled())
10982 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -070010983 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +080010984 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -070010985 free(adev->snd_dev_ref_cnt);
10986 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010987 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
10988 pcm_params_free(adev->use_case_table[i]);
10989 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010990 if (adev->adm_deinit)
10991 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010992 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010993 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010994 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010995 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010996 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010997 if (adev->device_cfg_params) {
10998 free(adev->device_cfg_params);
10999 adev->device_cfg_params = NULL;
11000 }
Derek Chend2530072014-11-24 12:39:14 -080011001 if(adev->ext_hw_plugin)
11002 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -080011003 audio_extn_auto_hal_deinit();
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011004 free_map(adev->patch_map);
11005 free_map(adev->io_streams_map);
Kiran Kandi910e1862013-10-29 13:29:42 -070011006 free(device);
11007 adev = NULL;
11008 }
11009 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +053011010 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011011 return 0;
11012}
11013
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070011014/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
11015 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
11016 * just that it _might_ work.
11017 */
11018static int period_size_is_plausible_for_low_latency(int period_size)
11019{
11020 switch (period_size) {
11021 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -070011022 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070011023 case 240:
11024 case 320:
11025 case 480:
11026 return 1;
11027 default:
11028 return 0;
11029 }
11030}
11031
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053011032static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
11033{
11034 bool is_snd_card_status = false;
11035 bool is_ext_device_status = false;
11036 char value[32];
11037 int card = -1;
11038 card_status_t status;
11039
11040 if (cookie != adev || !parms)
11041 return;
11042
11043 if (!parse_snd_card_status(parms, &card, &status)) {
11044 is_snd_card_status = true;
11045 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
11046 is_ext_device_status = true;
11047 } else {
11048 // not a valid event
11049 return;
11050 }
11051
11052 pthread_mutex_lock(&adev->lock);
11053 if (card == adev->snd_card || is_ext_device_status) {
11054 if (is_snd_card_status && adev->card_status != status) {
Jaideep Sharmacb402512020-09-24 17:51:07 +053011055 ALOGD("%s card_status %d", __func__, status);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053011056 adev->card_status = status;
11057 platform_snd_card_update(adev->platform, status);
11058 audio_extn_fm_set_parameters(adev, parms);
Derek Chend6f371d2019-03-01 13:45:58 -080011059 audio_extn_auto_hal_set_parameters(adev, parms);
Zhou Song4f43e352019-07-02 00:32:23 +080011060 if (status == CARD_STATUS_OFFLINE)
11061 audio_extn_sco_reset_configuration();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053011062 } else if (is_ext_device_status) {
11063 platform_set_parameters(adev->platform, parms);
11064 }
11065 }
11066 pthread_mutex_unlock(&adev->lock);
11067 return;
11068}
11069
Weiyin Jiang280ea742020-09-08 20:28:22 +080011070/* adev lock held */
11071int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011072{
11073 struct audio_usecase *uc_info;
Zhou Song407e5aa2020-12-27 19:13:04 +080011074 struct audio_usecase *usecase;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080011075 struct listnode devices;
Zhou Song407e5aa2020-12-27 19:13:04 +080011076 struct listnode *node;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011077
11078 uc_info = get_usecase_from_list(adev, out->usecase);
11079 if (uc_info == NULL) {
11080 ALOGE("%s: Could not find the usecase (%d) in the list",
11081 __func__, out->usecase);
11082 return -EINVAL;
11083 }
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080011084 list_init(&devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011085
Zhou Songbaddf9f2020-11-20 13:57:39 +080011086 ALOGD("%s: enter: usecase(%d: %s), a2dp muted %d", __func__,
11087 out->usecase, use_case_table[out->usecase], out->a2dp_muted);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011088
11089 if (restore) {
Weiyin Jiang280ea742020-09-08 20:28:22 +080011090 pthread_mutex_lock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011091 // restore A2DP device for active usecases and unmute if required
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080011092 if (is_a2dp_out_device_type(&out->device_list)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011093 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
Zhou Songe5225132019-09-26 15:33:36 +080011094 if (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)
11095 select_devices(adev, uc_info->id);
Zhou Songbaddf9f2020-11-20 13:57:39 +080011096
11097 if (is_offload_usecase(out->usecase)) {
11098 if (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)
Weiyin Jiang280ea742020-09-08 20:28:22 +080011099 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
Zhou Songbaddf9f2020-11-20 13:57:39 +080011100 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
11101 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
11102 } else {
11103 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011104 }
Zhou Songbaddf9f2020-11-20 13:57:39 +080011105 out->a2dp_muted = false;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011106 }
Weiyin Jiang280ea742020-09-08 20:28:22 +080011107 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011108 } else {
Weiyin Jiang280ea742020-09-08 20:28:22 +080011109 pthread_mutex_lock(&out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +080011110 // mute stream and switch to speaker if suspended
11111 if (!out->a2dp_muted && !out->standby) {
Zhou Songbaddf9f2020-11-20 13:57:39 +080011112 assign_devices(&devices, &out->device_list);
11113 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Zhou Song407e5aa2020-12-27 19:13:04 +080011114 list_for_each(node, &adev->usecase_list) {
11115 usecase = node_to_item(node, struct audio_usecase, list);
Zhou Songe63b6fe2021-04-15 13:54:46 +080011116 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
11117 !is_a2dp_out_device_type(&usecase->stream.out->device_list) &&
Zhou Songcf77af02021-05-14 18:21:14 +080011118 !is_sco_out_device_type(&usecase->stream.out->device_list) &&
Zhou Songe63b6fe2021-04-15 13:54:46 +080011119 platform_check_backends_match(SND_DEVICE_OUT_SPEAKER,
11120 usecase->out_snd_device)) {
Zhou Song407e5aa2020-12-27 19:13:04 +080011121 assign_devices(&out->device_list, &usecase->stream.out->device_list);
11122 break;
11123 }
11124 }
Zhou Songcf77af02021-05-14 18:21:14 +080011125 if ((is_a2dp_out_device_type(&devices) && list_length(&devices) == 1) ||
11126 (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)) {
Zhou Song8edbbdb2021-01-14 16:48:03 +080011127 out->a2dp_muted = true;
11128 if (is_offload_usecase(out->usecase)) {
11129 if (out->offload_state == OFFLOAD_STATE_PLAYING)
11130 compress_pause(out->compr);
11131 out_set_compr_volume(&out->stream, (float)0, (float)0);
Zhou Song8edbbdb2021-01-14 16:48:03 +080011132 } else {
Weiyin Jiang906db3c2021-03-02 13:17:04 +080011133 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
11134 out_set_voip_volume(&out->stream, (float)0, (float)0);
11135 else
11136 out_set_pcm_volume(&out->stream, (float)0, (float)0);
11137
Zhou Song8edbbdb2021-01-14 16:48:03 +080011138 /* wait for stale pcm drained before switching to speaker */
11139 uint32_t latency =
11140 (out->config.period_count * out->config.period_size * 1000) /
11141 (out->config.rate);
11142 usleep(latency * 1000);
11143 }
Zhou Songbaddf9f2020-11-20 13:57:39 +080011144 }
11145 select_devices(adev, out->usecase);
Zhou Song8edbbdb2021-01-14 16:48:03 +080011146 ALOGD("%s: switched to device:%s and stream muted:%d", __func__,
11147 platform_get_snd_device_name(uc_info->out_snd_device), out->a2dp_muted);
Zhou Songbaddf9f2020-11-20 13:57:39 +080011148 if (is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011149 if (out->offload_state == OFFLOAD_STATE_PLAYING)
11150 compress_resume(out->compr);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011151 }
Zhou Songbaddf9f2020-11-20 13:57:39 +080011152 assign_devices(&out->device_list, &devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011153 }
Weiyin Jiang280ea742020-09-08 20:28:22 +080011154 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011155 }
Zhenlin Lian4f947842022-05-14 15:50:52 +053011156 clear_devices(&devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053011157 ALOGV("%s: exit", __func__);
11158 return 0;
11159}
11160
Haynes Mathew George01156f92018-04-13 15:29:54 -070011161void adev_on_battery_status_changed(bool charging)
11162{
11163 pthread_mutex_lock(&adev->lock);
11164 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
11165 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +080011166 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -070011167 pthread_mutex_unlock(&adev->lock);
11168}
11169
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011170static int adev_open(const hw_module_t *module, const char *name,
11171 hw_device_t **device)
11172{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053011173 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -080011174 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053011175 char mixer_ctl_name[128] = {0};
11176 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053011177
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080011178 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011179 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
11180
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070011181 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -070011182 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070011183 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -070011184 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070011185 ALOGD("%s: returning existing instance of adev", __func__);
11186 ALOGD("%s: exit", __func__);
11187 pthread_mutex_unlock(&adev_init_lock);
11188 return 0;
11189 }
11190
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011191 adev = calloc(1, sizeof(struct audio_device));
11192
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -070011193 if (!adev) {
11194 pthread_mutex_unlock(&adev_init_lock);
11195 return -ENOMEM;
11196 }
11197
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -070011198 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
11199
Weiyin Jiange6ce6312019-01-28 18:28:22 +080011200 // register audio ext hidl at the earliest
11201 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053011202#ifdef DYNAMIC_LOG_ENABLED
11203 register_for_dynamic_logging("hal");
11204#endif
11205
Derek Chenf939fb72018-11-13 13:34:41 -080011206 /* default audio HAL major version */
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011207 uint32_t maj_version = 3;
Derek Chenf939fb72018-11-13 13:34:41 -080011208 if(property_get("vendor.audio.hal.maj.version", value, NULL))
11209 maj_version = atoi(value);
11210
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011211 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -080011212 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011213 adev->device.common.module = (struct hw_module_t *)module;
11214 adev->device.common.close = adev_close;
11215
11216 adev->device.init_check = adev_init_check;
11217 adev->device.set_voice_volume = adev_set_voice_volume;
11218 adev->device.set_master_volume = adev_set_master_volume;
11219 adev->device.get_master_volume = adev_get_master_volume;
11220 adev->device.set_master_mute = adev_set_master_mute;
11221 adev->device.get_master_mute = adev_get_master_mute;
11222 adev->device.set_mode = adev_set_mode;
11223 adev->device.set_mic_mute = adev_set_mic_mute;
11224 adev->device.get_mic_mute = adev_get_mic_mute;
11225 adev->device.set_parameters = adev_set_parameters;
11226 adev->device.get_parameters = adev_get_parameters;
11227 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
11228 adev->device.open_output_stream = adev_open_output_stream;
11229 adev->device.close_output_stream = adev_close_output_stream;
11230 adev->device.open_input_stream = adev_open_input_stream;
11231 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053011232 adev->device.create_audio_patch = adev_create_audio_patch;
11233 adev->device.release_audio_patch = adev_release_audio_patch;
11234 adev->device.get_audio_port = adev_get_audio_port;
11235 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011236 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +053011237 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011238
11239 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011240 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -080011241 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011242 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011243 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -080011244 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -070011245 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +053011246 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -070011247 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -070011248 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -070011249 /* Init audio and voice feature */
11250 audio_extn_feature_init();
11251 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070011252 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -080011253 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -080011254 list_init(&adev->active_inputs_list);
11255 list_init(&adev->active_outputs_list);
Rahul Sharma99770982019-03-06 17:05:26 +053011256 list_init(&adev->audio_patch_record_list);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011257 adev->io_streams_map = hashmapCreate(AUDIO_IO_PORTS_MAX, audio_extn_utils_hash_fn,
11258 audio_extn_utils_hash_eq);
11259 if (!adev->io_streams_map) {
11260 ALOGE("%s: Could not create io streams map", __func__);
11261 ret = -ENOMEM;
11262 goto adev_open_err;
11263 }
11264 adev->patch_map = hashmapCreate(AUDIO_PATCH_PORTS_MAX, audio_extn_utils_hash_fn,
11265 audio_extn_utils_hash_eq);
11266 if (!adev->patch_map) {
11267 ALOGE("%s: Could not create audio patch map", __func__);
11268 ret = -ENOMEM;
11269 goto adev_open_err;
11270 }
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -080011271 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -070011272 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +053011273 adev->pcm_record_uc_state = 0;
Kogara Naveen Kumarc5758232022-11-07 20:25:40 +053011274 adev->pcm_low_latency_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +053011275 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +053011276 adev->perf_lock_opts[0] = 0x101;
11277 adev->perf_lock_opts[1] = 0x20E;
11278 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +080011279 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -070011280 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053011281 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070011282 adev->adm_routing_changed = false;
Revathi Uddarajub26e3932020-06-10 14:51:02 +053011283 adev->a2dp_started = false;
Zhou Song503196b2021-07-23 17:31:05 +080011284 adev->ha_proxy_enable = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +053011285
Zhou Song68ebc352019-12-05 17:11:15 +080011286 audio_extn_perf_lock_init();
11287
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011288 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -070011289 adev->platform = platform_init(adev);
11290 if (!adev->platform) {
Eric Laurentb23d5282013-05-14 15:27:20 -070011291 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011292 ret = -EINVAL;
11293 goto adev_open_err;
Eric Laurentb23d5282013-05-14 15:27:20 -070011294 }
Eric Laurentc4aef752013-09-12 17:45:53 -070011295
Aalique Grahame22e49102018-12-18 14:23:57 -080011296 adev->extspk = audio_extn_extspk_init(adev);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053011297 if (audio_extn_qap_is_enabled()) {
11298 ret = audio_extn_qap_init(adev);
11299 if (ret < 0) {
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053011300 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011301 goto adev_open_err;
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053011302 }
11303 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
11304 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
11305 }
Aalique Grahame22e49102018-12-18 14:23:57 -080011306
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053011307 if (audio_extn_qaf_is_enabled()) {
11308 ret = audio_extn_qaf_init(adev);
11309 if (ret < 0) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053011310 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011311 goto adev_open_err;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053011312 }
11313
11314 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
11315 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
11316 }
11317
Derek Chenae7b0342019-02-08 15:17:04 -080011318 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -080011319 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
11320
Eric Laurentc4aef752013-09-12 17:45:53 -070011321 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
11322 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
11323 if (adev->visualizer_lib == NULL) {
11324 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
11325 } else {
11326 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
11327 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080011328 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070011329 "visualizer_hal_start_output");
11330 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080011331 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070011332 "visualizer_hal_stop_output");
11333 }
11334 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +053011335 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080011336 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -080011337 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +080011338 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +053011339 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070011340 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -070011341
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080011342 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
11343 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
11344 if (adev->offload_effects_lib == NULL) {
11345 ALOGE("%s: DLOPEN failed for %s", __func__,
11346 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
11347 } else {
11348 ALOGV("%s: DLOPEN successful for %s", __func__,
11349 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
11350 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +053011351 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080011352 "offload_effects_bundle_hal_start_output");
11353 adev->offload_effects_stop_output =
11354 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
11355 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080011356 adev->offload_effects_set_hpx_state =
11357 (int (*)(bool))dlsym(adev->offload_effects_lib,
11358 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +053011359 adev->offload_effects_get_parameters =
11360 (void (*)(struct str_parms *, struct str_parms *))
11361 dlsym(adev->offload_effects_lib,
11362 "offload_effects_bundle_get_parameters");
11363 adev->offload_effects_set_parameters =
11364 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
11365 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080011366 }
11367 }
11368
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070011369 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
11370 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
11371 if (adev->adm_lib == NULL) {
11372 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
11373 } else {
11374 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
11375 adev->adm_init = (adm_init_t)
11376 dlsym(adev->adm_lib, "adm_init");
11377 adev->adm_deinit = (adm_deinit_t)
11378 dlsym(adev->adm_lib, "adm_deinit");
11379 adev->adm_register_input_stream = (adm_register_input_stream_t)
11380 dlsym(adev->adm_lib, "adm_register_input_stream");
11381 adev->adm_register_output_stream = (adm_register_output_stream_t)
11382 dlsym(adev->adm_lib, "adm_register_output_stream");
11383 adev->adm_deregister_stream = (adm_deregister_stream_t)
11384 dlsym(adev->adm_lib, "adm_deregister_stream");
11385 adev->adm_request_focus = (adm_request_focus_t)
11386 dlsym(adev->adm_lib, "adm_request_focus");
11387 adev->adm_abandon_focus = (adm_abandon_focus_t)
11388 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -070011389 adev->adm_set_config = (adm_set_config_t)
11390 dlsym(adev->adm_lib, "adm_set_config");
11391 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
11392 dlsym(adev->adm_lib, "adm_request_focus_v2");
11393 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
11394 dlsym(adev->adm_lib, "adm_is_noirq_avail");
11395 adev->adm_on_routing_change = (adm_on_routing_change_t)
11396 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070011397 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
11398 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070011399 }
11400 }
11401
Aalique Grahame22e49102018-12-18 14:23:57 -080011402 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070011403 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +080011404 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Kunlei Zhanga3c4cb02021-03-05 16:03:54 +080011405 adev->fluence_nn_usecase_id = USECASE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -080011406 //initialize this to false for now,
11407 //this will be set to true through set param
11408 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070011409
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -070011410 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011411 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -080011412
11413 if (k_enable_extended_precision)
11414 adev_verify_devices(adev);
11415
Xiaojun Sang785b5da2017-08-03 15:52:29 +080011416 adev->dsp_bit_width_enforce_mode =
11417 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011418
Dhananjay Kumard6d32152016-10-13 16:11:03 +053011419 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
11420 &adev->streams_output_cfg_list,
11421 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070011422
Kiran Kandi910e1862013-10-29 13:29:42 -070011423 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070011424
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070011425 int trial;
Manisha Agarwalc75a0202019-12-06 18:48:25 +053011426 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070011427 trial = atoi(value);
11428 if (period_size_is_plausible_for_low_latency(trial)) {
11429 pcm_config_low_latency.period_size = trial;
11430 pcm_config_low_latency.start_threshold = trial / 4;
11431 pcm_config_low_latency.avail_min = trial / 4;
11432 configured_low_latency_capture_period_size = trial;
11433 }
11434 }
ronghuiz93177262021-04-21 19:58:13 +080011435 if (property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070011436 trial = atoi(value);
11437 if (period_size_is_plausible_for_low_latency(trial)) {
11438 configured_low_latency_capture_period_size = trial;
11439 }
11440 }
11441
Vignesh Kulothungan7d374312018-02-21 17:12:00 -080011442 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
11443
Eric Laurent4b084132018-10-19 17:33:43 -070011444 adev->camera_orientation = CAMERA_DEFAULT;
11445
Manisha Agarwalc75a0202019-12-06 18:48:25 +053011446 if (property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -070011447 af_period_multiplier = atoi(value);
11448 if (af_period_multiplier < 0)
11449 af_period_multiplier = 2;
11450 else if (af_period_multiplier > 4)
11451 af_period_multiplier = 4;
11452
11453 ALOGV("new period_multiplier = %d", af_period_multiplier);
11454 }
11455
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080011456 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080011457
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -070011458 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070011459 pthread_mutex_unlock(&adev_init_lock);
11460
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070011461 if (adev->adm_init)
11462 adev->adm_data = adev->adm_init();
11463
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053011464 qahwi_init(*device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080011465 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053011466
11467 audio_extn_snd_mon_init();
11468 pthread_mutex_lock(&adev->lock);
11469 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
11470 adev->card_status = CARD_STATUS_ONLINE;
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -050011471 adev->out_power_policy = POWER_POLICY_STATUS_ONLINE;
11472 adev->in_power_policy = POWER_POLICY_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -070011473 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
11474 /*
11475 * if the battery state callback happens before charging can be queried,
11476 * it will be guarded with the adev->lock held in the cb function and so
11477 * the callback value will reflect the latest state
11478 */
11479 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053011480 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +080011481 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -070011482 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +080011483 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053011484 /* Allocate memory for Device config params */
11485 adev->device_cfg_params = (struct audio_device_config_param*)
11486 calloc(platform_get_max_codec_backend(),
11487 sizeof(struct audio_device_config_param));
11488 if (adev->device_cfg_params == NULL)
11489 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053011490
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053011491 /*
11492 * Check if new PSPD matrix mixer control is supported. If not
11493 * supported, then set flag so that old mixer ctrl is sent while
11494 * sending pspd coefficients on older kernel version. Query mixer
11495 * control for default pcm id and channel value one.
11496 */
11497 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
11498 "AudStr %d ChMixer Weight Ch %d", 0, 1);
11499
11500 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
11501 if (!ctl) {
11502 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
11503 __func__, mixer_ctl_name);
11504 adev->use_old_pspd_mix_ctrl = true;
11505 }
11506
Jaideep Sharma0fa53812020-09-17 09:00:11 +053011507 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011508 return 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011509
11510adev_open_err:
11511 free_map(adev->patch_map);
11512 free_map(adev->io_streams_map);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080011513 free(adev->snd_dev_ref_cnt);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011514 pthread_mutex_destroy(&adev->lock);
11515 free(adev);
11516 adev = NULL;
11517 *device = NULL;
11518 pthread_mutex_unlock(&adev_init_lock);
11519 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011520}
11521
11522static struct hw_module_methods_t hal_module_methods = {
11523 .open = adev_open,
11524};
11525
11526struct audio_module HAL_MODULE_INFO_SYM = {
11527 .common = {
11528 .tag = HARDWARE_MODULE_TAG,
11529 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
11530 .hal_api_version = HARDWARE_HAL_API_VERSION,
11531 .id = AUDIO_HARDWARE_MODULE_ID,
11532 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -080011533 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011534 .methods = &hal_module_methods,
11535 },
11536};