blob: 7684f218748c519df968de6e3d2f460052590905 [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.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070039#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041/*#define VERY_VERY_VERBOSE_LOGGING*/
42#ifdef VERY_VERY_VERBOSE_LOGGING
43#define ALOGVV ALOGV
44#else
45#define ALOGVV(a...) do { } while(0)
46#endif
George Gao3018ede2019-10-23 13:23:00 -070047#include <limits.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080048#include <errno.h>
49#include <pthread.h>
50#include <stdint.h>
51#include <sys/time.h>
52#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070054#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include <sys/resource.h>
56#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
Aalique Grahame22e49102018-12-18 14:23:57 -080058#include <log/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070059#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080060#include <cutils/str_parms.h>
61#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062#include <cutils/atomic.h>
63#include <cutils/sched_policy.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070064#include <hardware/audio_effect.h>
Haynes Mathew George484e8d22017-07-31 18:55:17 -070065#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070066#include <system/thread_defs.h>
Haynes Mathew George16081042017-05-31 17:16:49 -070067#include <tinyalsa/asoundlib.h>
Andy Hunga1f48fa2019-07-01 18:14:53 -070068#include <utils/Timers.h> // systemTime
Eric Laurentb23d5282013-05-14 15:27:20 -070069#include <audio_effects/effect_aec.h>
70#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053071#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080072#include "audio_hw.h"
Wei Wangf7ca6c92017-11-21 14:51:20 -080073#include "audio_perf.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070074#include "platform_api.h"
75#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070076#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080077#include "voice_extn.h"
Ashish Jaind5694242017-09-05 20:09:06 +053078#include "ip_hdlr_intf.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080079
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070080#include "sound/compress_params.h"
Xiaojun Sang782e5b12020-06-29 21:13:06 +080081
82#ifdef AUDIO_GKI_ENABLED
83#include "sound/audio_compressed_formats.h"
84#endif
85
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080086#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080087
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053088#ifdef DYNAMIC_LOG_ENABLED
89#include <log_xml_parser.h>
90#define LOG_MASK HAL_MOD_FILE_AUDIO_HW
91#include <log_utils.h>
92#endif
93
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070094#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053095/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
96#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070097#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Vikram Panduranga93f080e2017-06-07 18:16:14 -070098#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Arun Mirpuri5d170872019-03-26 13:21:31 -070099#define MMAP_PLAYBACK_VOLUME_MAX 0x2000
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530100#define PCM_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530101#define DSD_VOLUME_MIN_DB (-110)
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700102#define INVALID_OUT_VOLUME -1
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700103#define AUDIO_IO_PORTS_MAX 32
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700104
Zhou Songbaddf9f2020-11-20 13:57:39 +0800105#define PLAYBACK_GAIN_MAX 1.0f
Aalique Grahame22e49102018-12-18 14:23:57 -0800106#define RECORD_GAIN_MIN 0.0f
107#define RECORD_GAIN_MAX 1.0f
108#define RECORD_VOLUME_CTL_MAX 0x2000
109
110/* treat as unsigned Q1.13 */
111#define APP_TYPE_GAIN_DEFAULT 0x2000
112
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700113#define PROXY_OPEN_RETRY_COUNT 100
114#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800115
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800116#define GET_USECASE_AUDIO_PLAYBACK_PRIMARY(db) \
117 (db)? USECASE_AUDIO_PLAYBACK_DEEP_BUFFER : \
118 USECASE_AUDIO_PLAYBACK_LOW_LATENCY
119#define GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(db) \
120 (db)? pcm_config_deep_buffer : pcm_config_low_latency
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800121
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700122#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700123#define DEFAULT_VOIP_BUF_DURATION_MS 20
124#define DEFAULT_VOIP_BIT_DEPTH_BYTE sizeof(int16_t)
125#define DEFAULT_VOIP_SAMP_RATE 48000
126
127#define VOIP_IO_BUF_SIZE(SR, DURATION_MS, BIT_DEPTH) (SR)/1000 * DURATION_MS * BIT_DEPTH
128
129struct pcm_config default_pcm_config_voip_copp = {
130 .channels = 1,
131 .rate = DEFAULT_VOIP_SAMP_RATE, /* changed when the stream is opened */
132 .period_size = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
133 .period_count = 2,
134 .format = PCM_FORMAT_S16_LE,
kunleiz95b597a2017-10-23 17:07:33 +0800135 .avail_min = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
136 .stop_threshold = INT_MAX,
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700137};
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700138
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700139#define MIN_CHANNEL_COUNT 1
140#define DEFAULT_CHANNEL_COUNT 2
141#define MAX_HIFI_CHANNEL_COUNT 8
142
Aalique Grahame22e49102018-12-18 14:23:57 -0800143#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
144#define MAX_CHANNEL_COUNT 1
145#else
146#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
147#define XSTR(x) STR(x)
148#define STR(x) #x
149#endif
150
Dechen Chai22768452021-07-30 09:29:16 +0530151#ifdef LINUX_ENABLED
152static inline int64_t audio_utils_ns_from_timespec(const struct timespec *ts)
153{
154 return ts->tv_sec * 1000000000LL + ts->tv_nsec;
155}
156#endif
157
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700158static unsigned int configured_low_latency_capture_period_size =
159 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
160
Haynes Mathew George16081042017-05-31 17:16:49 -0700161#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
162#define MMAP_PERIOD_COUNT_MIN 32
163#define MMAP_PERIOD_COUNT_MAX 512
164#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
165
Aalique Grahame22e49102018-12-18 14:23:57 -0800166/* This constant enables extended precision handling.
167 * TODO The flag is off until more testing is done.
168 */
169static const bool k_enable_extended_precision = false;
Arun Mirpurie008ed22019-03-21 11:21:04 -0700170extern int AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Aalique Grahame22e49102018-12-18 14:23:57 -0800171
Eric Laurentb23d5282013-05-14 15:27:20 -0700172struct pcm_config pcm_config_deep_buffer = {
173 .channels = 2,
174 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
175 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
176 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
177 .format = PCM_FORMAT_S16_LE,
178 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
179 .stop_threshold = INT_MAX,
180 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
181};
182
183struct pcm_config pcm_config_low_latency = {
184 .channels = 2,
185 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
186 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
187 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
188 .format = PCM_FORMAT_S16_LE,
189 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
190 .stop_threshold = INT_MAX,
191 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
192};
193
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800194struct pcm_config pcm_config_haptics_audio = {
195 .channels = 1,
196 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
197 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
198 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
199 .format = PCM_FORMAT_S16_LE,
200 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
201 .stop_threshold = INT_MAX,
202 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
203};
204
205struct pcm_config pcm_config_haptics = {
206 .channels = 1,
207 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
208 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
209 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
210 .format = PCM_FORMAT_S16_LE,
211 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
212 .stop_threshold = INT_MAX,
213 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
214};
215
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700216static int af_period_multiplier = 4;
217struct pcm_config pcm_config_rt = {
218 .channels = 2,
219 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
220 .period_size = ULL_PERIOD_SIZE, //1 ms
221 .period_count = 512, //=> buffer size is 512ms
222 .format = PCM_FORMAT_S16_LE,
223 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
224 .stop_threshold = INT_MAX,
225 .silence_threshold = 0,
226 .silence_size = 0,
227 .avail_min = ULL_PERIOD_SIZE, //1 ms
228};
229
Eric Laurentb23d5282013-05-14 15:27:20 -0700230struct pcm_config pcm_config_hdmi_multi = {
231 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
232 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
233 .period_size = HDMI_MULTI_PERIOD_SIZE,
234 .period_count = HDMI_MULTI_PERIOD_COUNT,
235 .format = PCM_FORMAT_S16_LE,
236 .start_threshold = 0,
237 .stop_threshold = INT_MAX,
238 .avail_min = 0,
239};
240
Haynes Mathew George16081042017-05-31 17:16:49 -0700241struct pcm_config pcm_config_mmap_playback = {
242 .channels = 2,
243 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
244 .period_size = MMAP_PERIOD_SIZE,
245 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
246 .format = PCM_FORMAT_S16_LE,
247 .start_threshold = MMAP_PERIOD_SIZE*8,
248 .stop_threshold = INT32_MAX,
249 .silence_threshold = 0,
250 .silence_size = 0,
251 .avail_min = MMAP_PERIOD_SIZE, //1 ms
252};
253
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700254struct pcm_config pcm_config_hifi = {
255 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
256 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
257 .period_size = HIFI_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
258 .period_count = HIFI_BUFFER_OUTPUT_PERIOD_COUNT,
259 .format = PCM_FORMAT_S24_3LE,
260 .start_threshold = 0,
261 .stop_threshold = INT_MAX,
262 .avail_min = 0,
263};
264
Eric Laurentb23d5282013-05-14 15:27:20 -0700265struct pcm_config pcm_config_audio_capture = {
266 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700267 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
268 .format = PCM_FORMAT_S16_LE,
269};
270
Haynes Mathew George16081042017-05-31 17:16:49 -0700271struct pcm_config pcm_config_mmap_capture = {
272 .channels = 2,
273 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
274 .period_size = MMAP_PERIOD_SIZE,
275 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
276 .format = PCM_FORMAT_S16_LE,
277 .start_threshold = 0,
278 .stop_threshold = INT_MAX,
279 .silence_threshold = 0,
280 .silence_size = 0,
281 .avail_min = MMAP_PERIOD_SIZE, //1 ms
282};
283
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700284#define AFE_PROXY_CHANNEL_COUNT 2
285#define AFE_PROXY_SAMPLING_RATE 48000
286
287#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
288#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
289
290struct pcm_config pcm_config_afe_proxy_playback = {
291 .channels = AFE_PROXY_CHANNEL_COUNT,
292 .rate = AFE_PROXY_SAMPLING_RATE,
293 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
294 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
295 .format = PCM_FORMAT_S16_LE,
296 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
297 .stop_threshold = INT_MAX,
298 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
299};
300
301#define AFE_PROXY_RECORD_PERIOD_SIZE 768
302#define AFE_PROXY_RECORD_PERIOD_COUNT 4
303
Aalique Grahame22e49102018-12-18 14:23:57 -0800304struct pcm_config pcm_config_audio_capture_rt = {
305 .channels = 2,
306 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
307 .period_size = ULL_PERIOD_SIZE,
308 .period_count = 512,
309 .format = PCM_FORMAT_S16_LE,
310 .start_threshold = 0,
311 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
312 .silence_threshold = 0,
313 .silence_size = 0,
314 .avail_min = ULL_PERIOD_SIZE, //1 ms
315};
316
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +0530317struct pcm_config pcm_config_audio_capture_rt_48KHz = {
318 .channels = 2,
319 .rate = 48000,
320 .period_size = 48,
321 .period_count = 512,
322 .format = PCM_FORMAT_S16_LE,
323 .start_threshold = 0,
324 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
325 .silence_threshold = 0,
326 .silence_size = 0,
327 .avail_min = 48, //1 ms
328};
329struct pcm_config pcm_config_audio_capture_rt_32KHz = {
330 .channels = 2,
331 .rate = 32000,
332 .period_size = 32,
333 .period_count = 512,
334 .format = PCM_FORMAT_S16_LE,
335 .start_threshold = 0,
336 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
337 .silence_threshold = 0,
338 .silence_size = 0,
339 .avail_min = 32, //1 ms
340};
341struct pcm_config pcm_config_audio_capture_rt_24KHz = {
342 .channels = 2,
343 .rate = 24000,
344 .period_size = 24,
345 .period_count = 512,
346 .format = PCM_FORMAT_S16_LE,
347 .start_threshold = 0,
348 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
349 .silence_threshold = 0,
350 .silence_size = 0,
351 .avail_min = 24, //1 ms
352};
353struct pcm_config pcm_config_audio_capture_rt_16KHz = {
354 .channels = 2,
355 .rate = 16000,
356 .period_size = 16,
357 .period_count = 512,
358 .format = PCM_FORMAT_S16_LE,
359 .start_threshold = 0,
360 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
361 .silence_threshold = 0,
362 .silence_size = 0,
363 .avail_min = 16, //1 ms
364};
365struct pcm_config pcm_config_audio_capture_rt_8KHz = {
366 .channels = 2,
367 .rate = 8000,
368 .period_size = 8,
369 .period_count = 512,
370 .format = PCM_FORMAT_S16_LE,
371 .start_threshold = 0,
372 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
373 .silence_threshold = 0,
374 .silence_size = 0,
375 .avail_min = 8, //1 ms
376};
377
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700378struct pcm_config pcm_config_afe_proxy_record = {
379 .channels = AFE_PROXY_CHANNEL_COUNT,
380 .rate = AFE_PROXY_SAMPLING_RATE,
381 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
382 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
383 .format = PCM_FORMAT_S16_LE,
384 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
385 .stop_threshold = INT_MAX,
386 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
387};
388
Ashish Jainf1eaa582016-05-23 20:54:24 +0530389#define AUDIO_MAX_PCM_FORMATS 7
390
391const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
392 [AUDIO_FORMAT_DEFAULT] = 0,
393 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
394 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
395 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
396 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
397 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
398 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
399};
400
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800401const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700402 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
403 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800404 [USECASE_AUDIO_PLAYBACK_WITH_HAPTICS] = "audio-with-haptics-playback",
Meng Wang51d8c2a2020-04-27 15:23:21 +0800405 [USECASE_AUDIO_PLAYBACK_HAPTICS] = "haptics-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700406 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
407 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700408 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700409 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700410 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
411 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
412 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
413 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
414 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
415 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
416 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
417 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
Haynes Mathew George16081042017-05-31 17:16:49 -0700418 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
419 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700420 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Aalique Grahame22e49102018-12-18 14:23:57 -0800421 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
vivek mehta0ea887a2015-08-26 14:01:20 -0700422
Eric Laurentb23d5282013-05-14 15:27:20 -0700423 [USECASE_AUDIO_RECORD] = "audio-record",
Krishna Kishor Jha0f4d8482022-02-18 10:56:05 +0530424 [USECASE_AUDIO_RECORD2] = "audio-record2",
425 [USECASE_AUDIO_RECORD3] = "audio-record3",
Mingming Yine62d7842013-10-25 16:26:03 -0700426 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530427 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
428 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
429 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Dhananjay Kumar376e38b2017-09-28 22:26:23 +0530430 [USECASE_AUDIO_RECORD_COMPRESS5] = "audio-record-compress5",
431 [USECASE_AUDIO_RECORD_COMPRESS6] = "audio-record-compress6",
Eric Laurentb23d5282013-05-14 15:27:20 -0700432 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700433 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700434 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700435 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700436
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800437 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800438 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Derek Chenf7092792017-05-23 12:23:53 -0400439 [USECASE_AUDIO_HFP_SCO_DOWNLINK] = "hfp-sco-downlink",
440 [USECASE_AUDIO_HFP_SCO_WB_DOWNLINK] = "hfp-sco-wb-downlink",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700441
Derek Chenf7092792017-05-23 12:23:53 -0400442 [USECASE_VOICE_CALL] = "voice-call",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700443 [USECASE_VOICE2_CALL] = "voice2-call",
444 [USECASE_VOLTE_CALL] = "volte-call",
445 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800446 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800447 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
448 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800449 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700450 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
451 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
452 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800453 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
454 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
455 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
456
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700457 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
458 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700459 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
460 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700461
462 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
463 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Zhou Song62ea0282020-03-22 19:53:01 +0800464 [USECASE_AUDIO_RECORD_AFE_PROXY2] = "afe-proxy-record2",
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +0530465 [USECASE_AUDIO_PLAYBACK_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700466
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530467 /* Transcode loopback cases */
Surendar Karka93cd25a2018-08-28 14:21:37 +0530468 [USECASE_AUDIO_TRANSCODE_LOOPBACK_RX] = "audio-transcode-loopback-rx",
469 [USECASE_AUDIO_TRANSCODE_LOOPBACK_TX] = "audio-transcode-loopback-tx",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700470
471 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
472 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Revathi Uddarajud9f23d92020-07-27 10:55:06 +0530473 [USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY] = "audio-record-voip-low-latency",
Varun Balaraje49253e2017-07-06 19:48:56 +0530474 /* For Interactive Audio Streams */
475 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
476 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
477 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
478 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
479 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
480 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
481 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
482 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700483
Aniket Kumar Lata7fd86e12018-02-20 19:26:10 -0800484 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture",
485
Derek Chenf6318be2017-06-12 17:16:24 -0400486 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
487
488 [USECASE_AUDIO_PLAYBACK_MEDIA] = "media-playback",
489 [USECASE_AUDIO_PLAYBACK_SYS_NOTIFICATION] = "sys-notification-playback",
490 [USECASE_AUDIO_PLAYBACK_NAV_GUIDANCE] = "nav-guidance-playback",
491 [USECASE_AUDIO_PLAYBACK_PHONE] = "phone-playback",
Derek Chen1bcdc6b2020-02-06 22:44:53 -0800492 [USECASE_AUDIO_PLAYBACK_FRONT_PASSENGER] = "front-passenger-playback",
Derek Chendf05eea2019-08-01 13:57:49 -0700493 [USECASE_AUDIO_PLAYBACK_REAR_SEAT] = "rear-seat-playback",
Rahul Sharma99770982019-03-06 17:05:26 +0530494 [USECASE_AUDIO_FM_TUNER_EXT] = "fm-tuner-ext",
Derek Chena30a5f42019-12-03 11:17:09 -0500495 [USECASE_ICC_CALL] = "icc-call",
Huicheng Liu1404ba12020-09-11 01:03:25 -0400496
497 [USECASE_AUDIO_RECORD_BUS] = "audio-record",
498 [USECASE_AUDIO_RECORD_BUS_FRONT_PASSENGER] = "front-passenger-record",
499 [USECASE_AUDIO_RECORD_BUS_REAR_SEAT] = "rear-seat-record",
Fei Tongaffdf732020-02-20 20:39:05 +0800500 [USECASE_AUDIO_PLAYBACK_SYNTHESIZER] = "synth-loopback",
Susan Wange3959562021-03-11 11:50:26 -0500501 [USECASE_AUDIO_RECORD_ECHO_REF_EXT] = "echo-reference-external",
Eric Laurentb23d5282013-05-14 15:27:20 -0700502};
503
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700504static const audio_usecase_t offload_usecases[] = {
505 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700506 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
507 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
508 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
509 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
510 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
511 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
512 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
513 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700514};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800515
Varun Balaraje49253e2017-07-06 19:48:56 +0530516static const audio_usecase_t interactive_usecases[] = {
517 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
518 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
519 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
520 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
521 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
522 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
523 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
524 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
525};
526
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800527#define STRING_TO_ENUM(string) { #string, string }
528
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800529struct string_to_enum {
530 const char *name;
531 uint32_t value;
532};
533
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700534static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800535 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800536 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
537 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
538 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700539 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800540 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
541 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800542 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700543 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
544 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
545 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
546 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
547 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
548 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
549 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
550 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
551 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
552 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
553 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800554};
555
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700556static const struct string_to_enum formats_name_to_enum_table[] = {
557 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
558 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
559 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700560 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
561 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
562 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700563 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800564 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
565 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700566 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800567};
568
569//list of all supported sample rates by HDMI specification.
570static const int out_hdmi_sample_rates[] = {
571 32000, 44100, 48000, 88200, 96000, 176400, 192000,
572};
573
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700574static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800575 STRING_TO_ENUM(32000),
576 STRING_TO_ENUM(44100),
577 STRING_TO_ENUM(48000),
578 STRING_TO_ENUM(88200),
579 STRING_TO_ENUM(96000),
580 STRING_TO_ENUM(176400),
581 STRING_TO_ENUM(192000),
Mingshu pange8aedf12019-10-25 15:38:27 +0800582 STRING_TO_ENUM(352800),
583 STRING_TO_ENUM(384000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700584};
585
Carter Hsu2e429db2019-05-14 18:50:52 +0800586struct in_effect_list {
587 struct listnode list;
588 effect_handle_t handle;
589};
590
Krishna Kishor Jha0f4d8482022-02-18 10:56:05 +0530591static const audio_usecase_t record_usecases[] = {
592 USECASE_AUDIO_RECORD,
593 USECASE_AUDIO_RECORD2,
594 USECASE_AUDIO_RECORD3,
595};
596
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700597static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700598static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700599static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700600//cache last MBDRC cal step level
601static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700602
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530603static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Arun Mirpuri5d170872019-03-26 13:21:31 -0700604static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800605static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530606static int out_set_pcm_volume(struct audio_stream_out *stream, float left, float right);
Krishna Kishor Jha10ad39f2022-02-21 17:02:47 +0530607#ifdef SOFT_VOLUME
608static int out_set_soft_volume_params(struct audio_stream_out *stream);
609#endif
Derek Chen6f293672019-04-01 01:40:24 -0700610static void adev_snd_mon_cb(void *cookie, struct str_parms *parms);
611static void in_snd_mon_cb(void * stream, struct str_parms * parms);
612static void out_snd_mon_cb(void * stream, struct str_parms * parms);
613
Zhou Song331c8e52019-08-26 14:16:12 +0800614static int configure_btsco_sample_rate(snd_device_t snd_device);
615
Vatsal Buchac09ae062018-11-14 13:25:08 +0530616#ifdef AUDIO_FEATURE_ENABLED_GCOV
617extern void __gcov_flush();
618static void enable_gcov()
619{
620 __gcov_flush();
621}
622#else
623static void enable_gcov()
624{
625}
626#endif
627
justinweng20fb6d82019-02-21 18:49:00 -0700628static int in_set_microphone_direction(const struct audio_stream_in *stream,
629 audio_microphone_direction_t dir);
630static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom);
631
Krishna Kishor Jha0f4d8482022-02-18 10:56:05 +0530632static bool is_pcm_record_usecase(audio_usecase_t uc_id)
633{
634 unsigned int record_uc_index;
635 unsigned int num_usecase = sizeof(record_usecases)/sizeof(record_usecases[0]);
636
637 for (record_uc_index = 0; record_uc_index < num_usecase; record_uc_index++) {
638 if (uc_id == record_usecases[record_uc_index])
639 return true;
640 }
641 return false;
642}
643
644static audio_usecase_t get_record_usecase(struct audio_device *adev)
645{
646 audio_usecase_t ret_uc = USECASE_INVALID;
647 unsigned int record_uc_index;
648 unsigned int num_usecase = sizeof(record_usecases)/sizeof(record_usecases[0]);
649
650 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
651 for (record_uc_index = 0; record_uc_index < num_usecase; record_uc_index++) {
652 if (!(adev->pcm_record_uc_state & (0x1 << record_uc_index))) {
653 adev->pcm_record_uc_state |= 0x1 << record_uc_index;
654 ret_uc = record_usecases[record_uc_index];
655 break;
656 }
657 }
658
659 ALOGV("%s: pcm record usecase is %d", __func__, ret_uc);
660 return ret_uc;
661}
662
663static void free_record_usecase(struct audio_device *adev,
664 audio_usecase_t uc_id)
665{
666 unsigned int record_uc_index;
667 unsigned int num_usecase = sizeof(record_usecases)/sizeof(record_usecases[0]);
668
669 for (record_uc_index = 0; record_uc_index < num_usecase; record_uc_index++) {
670 if (record_usecases[record_uc_index] == uc_id) {
671 adev->pcm_record_uc_state &= ~(0x1 << record_uc_index);
672 break;
673 }
674 }
675 ALOGV("%s: free pcm record usecase %d", __func__, uc_id);
676}
677
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700678static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
679 int flags __unused)
680{
681 int dir = 0;
682 switch (uc_id) {
683 case USECASE_AUDIO_RECORD_LOW_LATENCY:
Revathi Uddarajud9f23d92020-07-27 10:55:06 +0530684 case USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY:
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700685 dir = 1;
686 case USECASE_AUDIO_PLAYBACK_ULL:
687 break;
688 default:
689 return false;
690 }
691
692 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
693 PCM_PLAYBACK : PCM_CAPTURE);
694 if (adev->adm_is_noirq_avail)
695 return adev->adm_is_noirq_avail(adev->adm_data,
696 adev->snd_card, dev_id, dir);
697 return false;
698}
699
700static void register_out_stream(struct stream_out *out)
701{
702 struct audio_device *adev = out->dev;
703 if (is_offload_usecase(out->usecase) ||
704 !adev->adm_register_output_stream)
705 return;
706
707 // register stream first for backward compatibility
708 adev->adm_register_output_stream(adev->adm_data,
709 out->handle,
710 out->flags);
711
712 if (!adev->adm_set_config)
713 return;
714
715 if (out->realtime)
716 adev->adm_set_config(adev->adm_data,
717 out->handle,
718 out->pcm, &out->config);
719}
720
721static void register_in_stream(struct stream_in *in)
722{
723 struct audio_device *adev = in->dev;
724 if (!adev->adm_register_input_stream)
725 return;
726
727 adev->adm_register_input_stream(adev->adm_data,
728 in->capture_handle,
729 in->flags);
730
731 if (!adev->adm_set_config)
732 return;
733
734 if (in->realtime)
735 adev->adm_set_config(adev->adm_data,
736 in->capture_handle,
737 in->pcm,
738 &in->config);
739}
740
741static void request_out_focus(struct stream_out *out, long ns)
742{
743 struct audio_device *adev = out->dev;
744
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700745 if (adev->adm_request_focus_v2)
746 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
747 else if (adev->adm_request_focus)
748 adev->adm_request_focus(adev->adm_data, out->handle);
749}
750
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700751static int request_in_focus(struct stream_in *in, long ns)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700752{
753 struct audio_device *adev = in->dev;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700754 int ret = 0;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700755
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700756 if (adev->adm_request_focus_v2_1)
757 ret = adev->adm_request_focus_v2_1(adev->adm_data, in->capture_handle, ns);
758 else if (adev->adm_request_focus_v2)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700759 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
760 else if (adev->adm_request_focus)
761 adev->adm_request_focus(adev->adm_data, in->capture_handle);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700762
763 return ret;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700764}
765
766static void release_out_focus(struct stream_out *out)
767{
768 struct audio_device *adev = out->dev;
769
770 if (adev->adm_abandon_focus)
771 adev->adm_abandon_focus(adev->adm_data, out->handle);
772}
773
774static void release_in_focus(struct stream_in *in)
775{
776 struct audio_device *adev = in->dev;
777 if (adev->adm_abandon_focus)
778 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
779}
780
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530781static int parse_snd_card_status(struct str_parms *parms, int *card,
782 card_status_t *status)
783{
784 char value[32]={0};
785 char state[32]={0};
786
787 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
788 if (ret < 0)
789 return -1;
790
791 // sscanf should be okay as value is of max length 32.
792 // same as sizeof state.
793 if (sscanf(value, "%d,%s", card, state) < 2)
794 return -1;
795
796 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
797 CARD_STATUS_OFFLINE;
798 return 0;
799}
800
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700801static inline void adjust_frames_for_device_delay(struct stream_out *out,
802 uint32_t *dsp_frames) {
803 // Adjustment accounts for A2dp encoder latency with offload usecases
804 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -0800805 if (is_a2dp_out_device_type(&out->device_list)) {
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700806 unsigned long offset =
807 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
808 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
809 }
810}
811
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700812static inline bool free_entry(void *key __unused,
813 void *value, void *context __unused)
814{
815 free(value);
816 return true;
817}
818
819static inline void free_map(Hashmap *map)
820{
821 if (map) {
822 hashmapForEach(map, free_entry, (void *) NULL);
823 hashmapFree(map);
824 }
825}
826
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800827static inline void patch_map_remove_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700828 audio_patch_handle_t patch_handle)
829{
830 if (patch_handle == AUDIO_PATCH_HANDLE_NONE)
831 return;
832
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700833 struct audio_patch_info *p_info =
834 hashmapGet(adev->patch_map, (void *) (intptr_t) patch_handle);
835 if (p_info) {
836 ALOGV("%s: Remove patch %d", __func__, patch_handle);
837 hashmapRemove(adev->patch_map, (void *) (intptr_t) patch_handle);
838 free(p_info->patch);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700839 free(p_info);
840 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700841}
842
843static inline int io_streams_map_insert(struct audio_device *adev,
844 struct audio_stream *stream,
845 audio_io_handle_t handle,
846 audio_patch_handle_t patch_handle)
847{
848 struct audio_stream_info *s_info =
849 (struct audio_stream_info *) calloc(1, sizeof(struct audio_stream_info));
850
851 if (s_info == NULL) {
852 ALOGE("%s: Could not allocate stream info", __func__);
853 return -ENOMEM;
854 }
855 s_info->stream = stream;
856 s_info->patch_handle = patch_handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700857
858 pthread_mutex_lock(&adev->lock);
859 struct audio_stream_info *stream_info =
860 hashmapPut(adev->io_streams_map, (void *) (intptr_t) handle, (void *) s_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700861 if (stream_info != NULL)
862 free(stream_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800863 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Latad13758f2020-08-06 15:11:36 -0700864 ALOGV("%s: Added stream in io_streams_map with handle %d", __func__, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700865 return 0;
866}
867
868static inline void io_streams_map_remove(struct audio_device *adev,
869 audio_io_handle_t handle)
870{
871 pthread_mutex_lock(&adev->lock);
872 struct audio_stream_info *s_info =
873 hashmapRemove(adev->io_streams_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700874 if (s_info == NULL)
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800875 goto done;
Aniket Kumar Latad13758f2020-08-06 15:11:36 -0700876 ALOGV("%s: Removed stream with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800877 patch_map_remove_l(adev, s_info->patch_handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700878 free(s_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800879done:
880 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700881 return;
882}
883
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800884static struct audio_patch_info* fetch_patch_info_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700885 audio_patch_handle_t handle)
886{
887 struct audio_patch_info *p_info = NULL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700888 p_info = (struct audio_patch_info *)
889 hashmapGet(adev->patch_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700890 return p_info;
891}
892
vivek mehtaa76401a2015-04-24 14:12:15 -0700893__attribute__ ((visibility ("default")))
894bool audio_hw_send_gain_dep_calibration(int level) {
895 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700896 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700897
898 pthread_mutex_lock(&adev_init_lock);
899
900 if (adev != NULL && adev->platform != NULL) {
901 pthread_mutex_lock(&adev->lock);
902 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700903
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530904 // cache level info for any of the use case which
905 // was not started.
906 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700907
vivek mehtaa76401a2015-04-24 14:12:15 -0700908 pthread_mutex_unlock(&adev->lock);
909 } else {
910 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
911 }
912
913 pthread_mutex_unlock(&adev_init_lock);
914
915 return ret_val;
916}
917
Ashish Jain5106d362016-05-11 19:23:33 +0530918static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
919{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800920 bool gapless_enabled = false;
921 const char *mixer_ctl_name = "Compress Gapless Playback";
922 struct mixer_ctl *ctl;
923
924 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700925 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530926
927 /*Disable gapless if its AV playback*/
928 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800929
930 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
931 if (!ctl) {
932 ALOGE("%s: Could not get ctl for mixer cmd - %s",
933 __func__, mixer_ctl_name);
934 return -EINVAL;
935 }
936
937 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
938 ALOGE("%s: Could not set gapless mode %d",
939 __func__, gapless_enabled);
940 return -EINVAL;
941 }
942 return 0;
943}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700944
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700945__attribute__ ((visibility ("default")))
946int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
947 int table_size) {
948 int ret_val = 0;
949 ALOGV("%s: enter ... ", __func__);
950
951 pthread_mutex_lock(&adev_init_lock);
952 if (adev == NULL) {
953 ALOGW("%s: adev is NULL .... ", __func__);
954 goto done;
955 }
956
957 pthread_mutex_lock(&adev->lock);
958 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
959 pthread_mutex_unlock(&adev->lock);
960done:
961 pthread_mutex_unlock(&adev_init_lock);
962 ALOGV("%s: exit ... ", __func__);
963 return ret_val;
964}
965
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800966bool audio_hw_send_qdsp_parameter(int stream_type, float vol, bool active)
Aalique Grahame22e49102018-12-18 14:23:57 -0800967{
968 bool ret = false;
969 ALOGV("%s: enter ...", __func__);
970
971 pthread_mutex_lock(&adev_init_lock);
972
973 if (adev != NULL && adev->platform != NULL) {
974 pthread_mutex_lock(&adev->lock);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800975 ret = audio_extn_qdsp_set_state(adev, stream_type, vol, active);
Aalique Grahame22e49102018-12-18 14:23:57 -0800976 pthread_mutex_unlock(&adev->lock);
977 }
978
979 pthread_mutex_unlock(&adev_init_lock);
980
981 ALOGV("%s: exit with ret %d", __func__, ret);
982 return ret;
983}
Aalique Grahame22e49102018-12-18 14:23:57 -0800984
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700985static bool is_supported_format(audio_format_t format)
986{
Eric Laurent86e17132013-09-12 17:49:30 -0700987 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530988 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530989 format == AUDIO_FORMAT_AAC_LC ||
990 format == AUDIO_FORMAT_AAC_HE_V1 ||
991 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530992 format == AUDIO_FORMAT_AAC_ADTS_LC ||
993 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
994 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530995 format == AUDIO_FORMAT_AAC_LATM_LC ||
996 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
997 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530998 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
999 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +05301000 format == AUDIO_FORMAT_PCM_FLOAT ||
1001 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -07001002 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301003 format == AUDIO_FORMAT_AC3 ||
1004 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -07001005 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301006 format == AUDIO_FORMAT_DTS ||
1007 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001008 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301009 format == AUDIO_FORMAT_ALAC ||
1010 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301011 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301012 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001013 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05301014 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07001015 format == AUDIO_FORMAT_APTX ||
1016 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08001017 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001018
1019 return false;
1020}
1021
Kunlei Zhang67cc7072020-12-18 17:16:49 +08001022static bool is_supported_conc_usecase_for_power_mode_call(struct audio_device *adev)
1023{
1024 struct listnode *node;
1025 struct audio_usecase *usecase;
1026
1027 list_for_each(node, &adev->usecase_list) {
1028 usecase = node_to_item(node, struct audio_usecase, list);
1029 if (usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1030 ALOGD("%s: FM usecase is active, not setting power mode", __func__);
1031 return false;
1032 }
1033 }
1034
1035 return true;
1036}
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001037static inline bool is_mmap_usecase(audio_usecase_t uc_id)
1038{
1039 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
Zhou Song62ea0282020-03-22 19:53:01 +08001040 (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY2) ||
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001041 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
1042}
1043
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07001044static inline bool is_valid_volume(float left, float right)
1045{
1046 return ((left >= 0.0f && right >= 0.0f) ? true : false);
1047}
1048
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301049static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301050{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301051 ALOGV("%s", __func__);
1052 audio_route_apply_and_update_path(adev->audio_route,
1053 "asrc-mode");
1054 adev->asrc_mode_enabled = true;
1055}
1056
1057static void disable_asrc_mode(struct audio_device *adev)
1058{
1059 ALOGV("%s", __func__);
1060 audio_route_reset_and_update_path(adev->audio_route,
1061 "asrc-mode");
1062 adev->asrc_mode_enabled = false;
1063}
1064
Saurav Kumarc1411662020-10-14 10:50:45 +05301065static void check_and_configure_headphone(struct audio_device *adev,
1066 struct audio_usecase *uc_info,
1067 snd_device_t snd_device)
1068{
1069 struct listnode *node;
1070 struct audio_usecase *usecase;
1071 int new_backend_idx, usecase_backend_idx;
1072 bool spkr_hph_single_be_native_concurrency;
1073
1074 new_backend_idx = platform_get_backend_index(snd_device);
1075 spkr_hph_single_be_native_concurrency = platform_get_spkr_hph_single_be_native_concurrency_flag();
Zhou Songd4b18c42021-01-14 15:15:29 +08001076 if ((spkr_hph_single_be_native_concurrency && (new_backend_idx == DEFAULT_CODEC_BACKEND)) ||
1077 uc_info->id == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
Saurav Kumarc1411662020-10-14 10:50:45 +05301078 list_for_each(node, &adev->usecase_list) {
1079 usecase = node_to_item(node, struct audio_usecase, list);
1080 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
1081 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
1082 if (((usecase_backend_idx == HEADPHONE_BACKEND) ||
1083 (usecase_backend_idx == HEADPHONE_44_1_BACKEND)) &&
1084 ((usecase->stream.out->sample_rate % OUTPUT_SAMPLING_RATE_44100) == 0)) {
1085 disable_audio_route(adev, usecase);
1086 disable_snd_device(adev, usecase->out_snd_device);
1087 usecase->stream.out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Saurav Kumar70902382020-10-28 11:16:04 +05301088 platform_check_and_set_codec_backend_cfg(adev, usecase,
1089 usecase->out_snd_device);
Saurav Kumarc1411662020-10-14 10:50:45 +05301090 enable_snd_device(adev, usecase->out_snd_device);
Zhou Songd4b18c42021-01-14 15:15:29 +08001091 enable_audio_route(adev, usecase);
Saurav Kumarc1411662020-10-14 10:50:45 +05301092 }
1093 }
Revathi Uddaraju2c0eac02021-07-27 02:06:42 -07001094 else if ((usecase->type != PCM_CAPTURE) && (usecase == uc_info)) {
1095 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
1096 if (((usecase_backend_idx == HEADPHONE_BACKEND) ||
1097 (usecase_backend_idx == HEADPHONE_44_1_BACKEND)) &&
1098 ((usecase->stream.out->sample_rate % OUTPUT_SAMPLING_RATE_44100) == 0)) {
1099 usecase->stream.out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1100 platform_check_and_set_codec_backend_cfg(adev, usecase,
1101 usecase->out_snd_device);
1102 }
1103 }
Saurav Kumarc1411662020-10-14 10:50:45 +05301104 }
1105 }
1106}
1107
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301108/*
1109 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
1110 * 44.1 or Native DSD backends are enabled for any of current use case.
1111 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
1112 * - Disable current mix path use case(Headphone backend) and re-enable it with
1113 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
1114 * e.g. Naitve DSD or Headphone 44.1 -> + 48
1115 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301116static void check_and_set_asrc_mode(struct audio_device *adev,
1117 struct audio_usecase *uc_info,
1118 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301119{
1120 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301121 int i, num_new_devices = 0;
1122 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
1123 /*
1124 *Split snd device for new combo use case
1125 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
1126 */
1127 if (platform_split_snd_device(adev->platform,
1128 snd_device,
1129 &num_new_devices,
1130 split_new_snd_devices) == 0) {
1131 for (i = 0; i < num_new_devices; i++)
1132 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
1133 } else {
1134 int new_backend_idx = platform_get_backend_index(snd_device);
1135 if (((new_backend_idx == HEADPHONE_BACKEND) ||
1136 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
1137 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
1138 !adev->asrc_mode_enabled) {
1139 struct listnode *node = NULL;
1140 struct audio_usecase *uc = NULL;
1141 struct stream_out *curr_out = NULL;
1142 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
1143 int i, num_devices, ret = 0;
1144 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301145
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301146 list_for_each(node, &adev->usecase_list) {
1147 uc = node_to_item(node, struct audio_usecase, list);
1148 curr_out = (struct stream_out*) uc->stream.out;
1149 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
1150 /*
1151 *Split snd device for existing combo use case
1152 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
1153 */
1154 ret = platform_split_snd_device(adev->platform,
1155 uc->out_snd_device,
1156 &num_devices,
1157 split_snd_devices);
1158 if (ret < 0 || num_devices == 0) {
1159 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
1160 split_snd_devices[0] = uc->out_snd_device;
1161 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -08001162 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301163 for (i = 0; i < num_devices; i++) {
1164 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
1165 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
1166 if((new_backend_idx == HEADPHONE_BACKEND) &&
1167 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
1168 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07001169 ALOGV("%s:DSD or native stream detected enabling asrcmode in hardware",
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301170 __func__);
1171 enable_asrc_mode(adev);
1172 break;
1173 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
1174 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
1175 (usecase_backend_idx == HEADPHONE_BACKEND)) {
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07001176 ALOGV("%s: 48K stream detected, disabling and enabling it \
1177 with asrcmode in hardware", __func__);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301178 disable_audio_route(adev, uc);
1179 disable_snd_device(adev, uc->out_snd_device);
1180 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
1181 if (new_backend_idx == DSD_NATIVE_BACKEND)
1182 audio_route_apply_and_update_path(adev->audio_route,
1183 "hph-true-highquality-mode");
1184 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
1185 (curr_out->bit_width >= 24))
1186 audio_route_apply_and_update_path(adev->audio_route,
1187 "hph-highquality-mode");
1188 enable_asrc_mode(adev);
1189 enable_snd_device(adev, uc->out_snd_device);
1190 enable_audio_route(adev, uc);
1191 break;
1192 }
1193 }
1194 // reset split devices count
1195 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -08001196 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301197 if (adev->asrc_mode_enabled)
1198 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301199 }
1200 }
1201 }
1202}
1203
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001204static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
1205 struct audio_effect_config effect_config,
1206 unsigned int param_value)
1207{
1208 char mixer_ctl_name[] = "Audio Effect";
1209 struct mixer_ctl *ctl;
1210 long set_values[6];
Eric Laurent637e2d42018-11-15 12:24:31 -08001211 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001212
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001213 if (in == NULL) {
1214 ALOGE("%s: active input stream is NULL", __func__);
1215 return -EINVAL;
1216 }
1217
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001218 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1219 if (!ctl) {
1220 ALOGE("%s: Could not get mixer ctl - %s",
1221 __func__, mixer_ctl_name);
1222 return -EINVAL;
1223 }
1224
1225 set_values[0] = 1; //0:Rx 1:Tx
1226 set_values[1] = in->app_type_cfg.app_type;
1227 set_values[2] = (long)effect_config.module_id;
1228 set_values[3] = (long)effect_config.instance_id;
1229 set_values[4] = (long)effect_config.param_id;
1230 set_values[5] = param_value;
1231
1232 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
1233
1234 return 0;
1235
1236}
1237
1238static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
1239 int effect_type, unsigned int *param_value)
1240{
1241 int ret = 0;
1242 struct audio_effect_config other_effect_config;
1243 struct audio_usecase *usecase = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08001244 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001245
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001246 if (in == NULL) {
1247 ALOGE("%s: active input stream is NULL", __func__);
1248 return -EINVAL;
1249 }
1250
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001251 usecase = get_usecase_from_list(adev, in->usecase);
1252 if (!usecase)
1253 return -EINVAL;
1254
1255 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
1256 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
1257 if (ret < 0) {
1258 ALOGE("%s Failed to get effect params %d", __func__, ret);
1259 return ret;
1260 }
1261
1262 if (module_id == other_effect_config.module_id) {
1263 //Same module id for AEC/NS. Values need to be combined
1264 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
1265 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
1266 *param_value |= other_effect_config.param_value;
1267 }
1268 }
1269
1270 return ret;
1271}
1272
1273static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
Gangadhar Sb0210342019-02-22 17:39:41 +05301274{
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001275 struct audio_effect_config effect_config;
1276 struct audio_usecase *usecase = NULL;
1277 int ret = 0;
1278 unsigned int param_value = 0;
Eric Laurent637e2d42018-11-15 12:24:31 -08001279 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001280
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001281 if(!voice_extn_is_dynamic_ecns_enabled())
1282 return ENOSYS;
1283
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001284 if (!in) {
1285 ALOGE("%s: Invalid input stream", __func__);
1286 return -EINVAL;
1287 }
1288
1289 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
1290
1291 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +08001292 if (usecase == NULL) {
1293 ALOGE("%s: Could not find the usecase (%d) in the list",
1294 __func__, in->usecase);
1295 return -EINVAL;
1296 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001297
1298 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
1299 if (ret < 0) {
1300 ALOGE("%s Failed to get module id %d", __func__, ret);
1301 return ret;
1302 }
1303 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
1304 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
1305
1306 if(enable)
1307 param_value = effect_config.param_value;
1308
1309 /*Special handling for AEC & NS effects Param values need to be
1310 updated if module ids are same*/
1311
1312 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
1313 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
1314 if (ret < 0)
1315 return ret;
1316 }
1317
1318 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
1319
1320 return ret;
1321}
1322
1323static void check_and_enable_effect(struct audio_device *adev)
1324{
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001325 if(!voice_extn_is_dynamic_ecns_enabled())
1326 return;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001327
Eric Laurent637e2d42018-11-15 12:24:31 -08001328 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001329
Eric Laurent637e2d42018-11-15 12:24:31 -08001330 if (in != NULL && !in->standby) {
1331 if (in->enable_aec)
1332 enable_disable_effect(adev, EFFECT_AEC, true);
1333
1334 if (in->enable_ns &&
1335 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1336 enable_disable_effect(adev, EFFECT_NS, true);
1337 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001338 }
1339}
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001340
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001341int pcm_ioctl(struct pcm *pcm, int request, ...)
1342{
1343 va_list ap;
1344 void * arg;
1345 int pcm_fd = *(int*)pcm;
1346
1347 va_start(ap, request);
1348 arg = va_arg(ap, void *);
1349 va_end(ap);
1350
1351 return ioctl(pcm_fd, request, arg);
1352}
1353
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001354int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001355 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001356{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001357 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001358 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +05301359 struct stream_out *out = NULL;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301360 struct stream_in *in = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001361 struct listnode out_devices;
Soumya Managoli6993b762018-06-28 16:04:57 +05301362 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001363
1364 if (usecase == NULL)
1365 return -EINVAL;
1366
1367 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
1368
Carter Hsu2e429db2019-05-14 18:50:52 +08001369 if (usecase->type == PCM_CAPTURE) {
1370 struct stream_in *in = usecase->stream.in;
1371 struct audio_usecase *uinfo;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001372 snd_device = usecase->in_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001373
1374 if (in) {
1375 if (in->enable_aec || in->enable_ec_port) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001376 list_init(&out_devices);
1377 update_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "", true);
Carter Hsu2e429db2019-05-14 18:50:52 +08001378 struct listnode *node;
1379 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1380 USECASE_AUDIO_PLAYBACK_VOIP);
1381 if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001382 assign_devices(&out_devices,
1383 &voip_usecase->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001384 } else if (adev->primary_output &&
1385 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001386 assign_devices(&out_devices,
1387 &adev->primary_output->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001388 } else {
1389 list_for_each(node, &adev->usecase_list) {
1390 uinfo = node_to_item(node, struct audio_usecase, list);
1391 if (uinfo->type != PCM_CAPTURE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001392 assign_devices(&out_devices,
1393 &uinfo->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001394 break;
1395 }
1396 }
1397 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001398
1399 platform_set_echo_reference(adev, true, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001400 in->ec_opened = true;
1401 }
1402 }
Guodong Huf5e614d2019-06-24 18:42:03 +08001403 } else if ((usecase->type == TRANSCODE_LOOPBACK_TX) || ((usecase->type == PCM_HFP_CALL) &&
1404 ((usecase->id == USECASE_AUDIO_HFP_SCO) || (usecase->id == USECASE_AUDIO_HFP_SCO_WB)) &&
1405 (usecase->in_snd_device == SND_DEVICE_IN_VOICE_SPEAKER_MIC_HFP_MMSECNS))) {
Carter Hsu2e429db2019-05-14 18:50:52 +08001406 snd_device = usecase->in_snd_device;
1407 } else {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001408 snd_device = usecase->out_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001409 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001410
Kunlei Zhanga3c4cb02021-03-05 16:03:54 +08001411 if (usecase->type == PCM_CAPTURE) {
1412 if (platform_get_fluence_nn_state(adev->platform) == 0) {
1413 platform_set_fluence_nn_state(adev->platform, true);
1414 ALOGD("%s: set fluence nn capture state", __func__);
1415 }
1416 }
1417
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001418#ifdef DS1_DOLBY_DAP_ENABLED
1419 audio_extn_dolby_set_dmid(adev);
1420 audio_extn_dolby_set_endpoint(adev);
1421#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001422 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001423 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301424 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001425 audio_extn_utils_send_app_type_cfg(adev, usecase);
Jasmine Cha4dcc1092019-03-04 18:12:47 +08001426 if (audio_extn_is_maxx_audio_enabled())
1427 audio_extn_ma_set_device(usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301428 audio_extn_utils_send_audio_calibration(adev, usecase);
Zhou Songbaddf9f2020-11-20 13:57:39 +08001429 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1430 out = usecase->stream.out;
1431 if (out && out->compr)
Manish Dewangan58229382017-02-02 15:48:41 +05301432 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1433 }
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301434
1435 if (usecase->type == PCM_CAPTURE) {
Kunlei Zhanga3c4cb02021-03-05 16:03:54 +08001436 if (platform_get_fluence_nn_state(adev->platform) == 1 &&
1437 adev->fluence_nn_usecase_id == USECASE_INVALID ) {
1438 adev->fluence_nn_usecase_id = usecase->id;
1439 ALOGD("%s: assign fluence nn usecase %d", __func__, usecase->id);
1440 }
1441 }
1442
1443 if (usecase->type == PCM_CAPTURE) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301444 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001445 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301446 ALOGD("%s: set custom mtmx params v1", __func__);
1447 audio_extn_set_custom_mtmx_params_v1(adev, usecase, true);
1448 }
1449 } else {
1450 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
1451 }
Manish Dewangan58229382017-02-02 15:48:41 +05301452
Andy Hung756ecc12018-10-19 17:47:12 -07001453 // we shouldn't truncate mixer_path
1454 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1455 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1456 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001457 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001458 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301459 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1460 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1461 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1462 if (parms) {
1463 audio_extn_fm_set_parameters(adev, parms);
1464 str_parms_destroy(parms);
1465 }
1466 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001467 ALOGV("%s: exit", __func__);
1468 return 0;
1469}
1470
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001471int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001472 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001473{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001474 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001475 char mixer_path[MIXER_PATH_MAX_LENGTH];
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301476 struct stream_in *in = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001477
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301478 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001479 return -EINVAL;
1480
1481 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301482 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001483 snd_device = usecase->in_snd_device;
1484 else
1485 snd_device = usecase->out_snd_device;
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001486
1487 /* disable island and power mode on supported device for voice call */
1488 if (usecase->type == VOICE_CALL) {
1489 if (usecase->in_snd_device != SND_DEVICE_NONE) {
1490 if (platform_get_island_cfg_on_device(adev->platform, usecase->in_snd_device) &&
1491 platform_get_power_mode_on_device(adev->platform, usecase->in_snd_device)) {
1492 platform_set_island_cfg_on_device(adev, usecase->in_snd_device, false);
1493 platform_set_power_mode_on_device(adev, usecase->in_snd_device, false);
1494 platform_reset_island_power_status(adev->platform, usecase->in_snd_device);
Kunlei Zhang91c4b332020-07-20 17:53:14 +08001495 if (voice_is_lte_call_active(adev))
1496 platform_set_tx_lpi_mode(adev->platform, false);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001497 ALOGD("%s: disable island cfg and power mode in voice tx path",
1498 __func__);
1499 }
1500 }
1501 if (usecase->out_snd_device != SND_DEVICE_NONE) {
1502 if (platform_get_island_cfg_on_device(adev->platform, usecase->out_snd_device) &&
1503 platform_get_power_mode_on_device(adev->platform, usecase->out_snd_device)) {
1504 platform_set_island_cfg_on_device(adev, usecase->out_snd_device, false);
1505 platform_set_power_mode_on_device(adev, usecase->out_snd_device, false);
1506 platform_reset_island_power_status(adev->platform, usecase->out_snd_device);
1507 ALOGD("%s: disable island cfg and power mode in voice rx path",
1508 __func__);
1509 }
1510 }
1511 }
1512
Andy Hung756ecc12018-10-19 17:47:12 -07001513 // we shouldn't truncate mixer_path
1514 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1515 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1516 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001517 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001518 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001519 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Carter Hsu2e429db2019-05-14 18:50:52 +08001520 if (usecase->type == PCM_CAPTURE) {
1521 struct stream_in *in = usecase->stream.in;
1522 if (in && in->ec_opened) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001523 struct listnode out_devices;
1524 list_init(&out_devices);
1525 platform_set_echo_reference(in->dev, false, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001526 in->ec_opened = false;
1527 }
1528 }
Kunlei Zhanga3c4cb02021-03-05 16:03:54 +08001529 if (usecase->id == adev->fluence_nn_usecase_id) {
1530 platform_set_fluence_nn_state(adev->platform, false);
1531 adev->fluence_nn_usecase_id = USECASE_INVALID;
1532 ALOGD("%s: reset fluence nn capture state", __func__);
1533 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001534 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301535 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301536
1537 if (usecase->type == PCM_CAPTURE) {
1538 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001539 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301540 ALOGD("%s: reset custom mtmx params v1", __func__);
1541 audio_extn_set_custom_mtmx_params_v1(adev, usecase, false);
1542 }
1543 } else {
1544 audio_extn_set_custom_mtmx_params_v2(adev, usecase, false);
1545 }
1546
Weiyin Jiang298ffd92019-06-03 14:29:30 +08001547 if ((usecase->type == PCM_PLAYBACK) &&
1548 (usecase->stream.out != NULL))
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05301549 usecase->stream.out->pspd_coeff_sent = false;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301550
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001551 ALOGV("%s: exit", __func__);
1552 return 0;
1553}
1554
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001555int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001556 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001557{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301558 int i, num_devices = 0;
1559 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001560 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1561
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001562 if (snd_device < SND_DEVICE_MIN ||
1563 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001564 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001565 return -EINVAL;
1566 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001567
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001568 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001569 ALOGE("%s: Invalid sound device returned", __func__);
1570 return -EINVAL;
1571 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001572
1573 adev->snd_dev_ref_cnt[snd_device]++;
1574
1575 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1576 (platform_split_snd_device(adev->platform,
1577 snd_device,
1578 &num_devices,
1579 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001580 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001581 __func__, snd_device, device_name);
Aniket Kumar Lata990de552019-07-11 14:20:23 -07001582 /* Set backend config for A2DP to ensure slimbus configuration
1583 is correct if A2DP is already active and backend is closed
1584 and re-opened */
1585 if (snd_device == SND_DEVICE_OUT_BT_A2DP)
1586 audio_extn_a2dp_set_source_backend_cfg();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001587 return 0;
1588 }
1589
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001590 if (audio_extn_spkr_prot_is_enabled())
1591 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001592
Aalique Grahame22e49102018-12-18 14:23:57 -08001593 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1594
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001595 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1596 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001597 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1598 goto err;
1599 }
1600 audio_extn_dev_arbi_acquire(snd_device);
1601 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001602 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001603 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001604 goto err;
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001605 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001606 } else if (platform_split_snd_device(adev->platform,
1607 snd_device,
1608 &num_devices,
1609 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301610 for (i = 0; i < num_devices; i++) {
1611 enable_snd_device(adev, new_snd_devices[i]);
1612 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001613 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001614 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001615 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301616
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001617 /* enable island and power mode on supported device */
1618 if (platform_get_island_cfg_on_device(adev->platform, snd_device) &&
1619 platform_get_power_mode_on_device(adev->platform, snd_device)) {
1620 platform_set_island_cfg_on_device(adev, snd_device, true);
1621 platform_set_power_mode_on_device(adev, snd_device, true);
Kunlei Zhang91c4b332020-07-20 17:53:14 +08001622 if (voice_is_lte_call_active(adev) &&
1623 (snd_device >= SND_DEVICE_IN_BEGIN &&
1624 snd_device < SND_DEVICE_IN_END))
1625 platform_set_tx_lpi_mode(adev->platform, true);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001626 ALOGD("%s: enable island cfg and power mode on: %s",
1627 __func__, device_name);
1628 }
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301629
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301630 if (SND_DEVICE_OUT_BT_A2DP == snd_device) {
Ramjee Singh2d2944a2021-12-14 14:13:41 +05301631
1632 struct audio_usecase *usecase;
1633 struct listnode *node;
1634 /* Disable SCO Devices and enable handset mic for active input stream */
1635 list_for_each(node, &adev->usecase_list) {
1636 usecase = node_to_item(node, struct audio_usecase, list);
1637 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
1638 is_sco_in_device_type(&usecase->stream.in->device_list)) {
1639 ALOGD("a2dp resumed, switch bt sco mic to handset mic");
1640 reassign_device_list(&usecase->stream.in->device_list,
1641 AUDIO_DEVICE_IN_BUILTIN_MIC, "");
1642 select_devices(adev, usecase->id);
1643 }
1644 }
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301645 if (audio_extn_a2dp_start_playback() < 0) {
1646 ALOGE(" fail to configure A2dp Source control path ");
1647 goto err;
1648 } else {
1649 adev->a2dp_started = true;
1650 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001651 }
Florian Pfister1a84f312018-07-19 14:38:18 +02001652
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001653 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1654 (audio_extn_a2dp_start_capture() < 0)) {
1655 ALOGE(" fail to configure A2dp Sink control path ");
1656 goto err;
1657 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301658
Mingshu Pang7be5b1d2020-03-04 15:24:38 +08001659 if ((SND_DEVICE_OUT_BT_SCO_SWB == snd_device) ||
1660 (SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC == snd_device) ||
1661 (SND_DEVICE_IN_BT_SCO_MIC_SWB == snd_device)) {
1662 if (!adev->bt_sco_on || (audio_extn_sco_start_configuration() < 0)) {
1663 ALOGE(" fail to configure sco control path ");
1664 goto err;
1665 }
Zhou Song12c29502019-03-16 10:37:18 +08001666 }
1667
Zhou Song331c8e52019-08-26 14:16:12 +08001668 configure_btsco_sample_rate(snd_device);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001669 /* due to the possibility of calibration overwrite between listen
1670 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001671 audio_extn_sound_trigger_update_device_status(snd_device,
1672 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301673 audio_extn_listen_update_device_status(snd_device,
1674 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001675 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001676 audio_extn_sound_trigger_update_device_status(snd_device,
1677 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301678 audio_extn_listen_update_device_status(snd_device,
1679 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001680 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001681 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001682 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001683 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301684
1685 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1686 !adev->native_playback_enabled &&
1687 audio_is_true_native_stream_active(adev)) {
1688 ALOGD("%s: %d: napb: enabling native mode in hardware",
1689 __func__, __LINE__);
1690 audio_route_apply_and_update_path(adev->audio_route,
1691 "true-native-mode");
1692 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301693 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301694 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1695 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001696 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001697 ALOGD("%s: init ec ref loopback", __func__);
1698 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1699 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001700 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001701 return 0;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001702err:
1703 adev->snd_dev_ref_cnt[snd_device]--;
1704 return -EINVAL;;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001705}
1706
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001707int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001708 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001709{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301710 int i, num_devices = 0;
1711 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001712 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1713
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001714 if (snd_device < SND_DEVICE_MIN ||
1715 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001716 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001717 return -EINVAL;
1718 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001719
1720 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1721 ALOGE("%s: Invalid sound device returned", __func__);
1722 return -EINVAL;
1723 }
1724
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001725 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1726 ALOGE("%s: device ref cnt is already 0", __func__);
1727 return -EINVAL;
1728 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001729
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001730 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001731
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001732
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001733 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001734 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301735
Aalique Grahame22e49102018-12-18 14:23:57 -08001736 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1737
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001738 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1739 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001740 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001741
1742 // when speaker device is disabled, reset swap.
1743 // will be renabled on usecase start
1744 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001745 } else if (platform_split_snd_device(adev->platform,
1746 snd_device,
1747 &num_devices,
1748 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301749 for (i = 0; i < num_devices; i++) {
1750 disable_snd_device(adev, new_snd_devices[i]);
1751 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001752 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001753 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001754 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001755 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001756
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301757 if (snd_device == SND_DEVICE_OUT_BT_A2DP) {
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301758 audio_extn_a2dp_stop_playback();
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301759 adev->a2dp_started = false;
1760 } else if (snd_device == SND_DEVICE_IN_BT_A2DP)
Florian Pfister1a84f312018-07-19 14:38:18 +02001761 audio_extn_a2dp_stop_capture();
Zhou Songd6d71752019-05-21 18:08:51 +08001762 else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001763 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
Ashish Jain81eb2a82015-05-13 10:52:34 +05301764 adev->is_channel_status_set = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001765 else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301766 adev->native_playback_enabled) {
1767 ALOGD("%s: %d: napb: disabling native mode in hardware",
1768 __func__, __LINE__);
1769 audio_route_reset_and_update_path(adev->audio_route,
1770 "true-native-mode");
1771 adev->native_playback_enabled = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001772 } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301773 adev->asrc_mode_enabled) {
1774 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301775 disable_asrc_mode(adev);
1776 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001777 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301778 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001779 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001780 ALOGD("%s: deinit ec ref loopback", __func__);
1781 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1782 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001783
1784 audio_extn_utils_release_snd_device(snd_device);
1785 } else {
1786 if (platform_split_snd_device(adev->platform,
1787 snd_device,
1788 &num_devices,
1789 new_snd_devices) == 0) {
1790 for (i = 0; i < num_devices; i++) {
1791 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1792 }
1793 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001794 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001795
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001796 return 0;
1797}
1798
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001799/*
1800 legend:
1801 uc - existing usecase
1802 new_uc - new usecase
1803 d1, d11, d2 - SND_DEVICE enums
1804 a1, a2 - corresponding ANDROID device enums
1805 B1, B2 - backend strings
1806
1807case 1
1808 uc->dev d1 (a1) B1
1809 new_uc->dev d1 (a1), d2 (a2) B1, B2
1810
1811 resolution: disable and enable uc->dev on d1
1812
1813case 2
1814 uc->dev d1 (a1) B1
1815 new_uc->dev d11 (a1) B1
1816
1817 resolution: need to switch uc since d1 and d11 are related
1818 (e.g. speaker and voice-speaker)
1819 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1820
1821case 3
1822 uc->dev d1 (a1) B1
1823 new_uc->dev d2 (a2) B2
1824
1825 resolution: no need to switch uc
1826
1827case 4
1828 uc->dev d1 (a1) B1
1829 new_uc->dev d2 (a2) B1
1830
1831 resolution: disable enable uc-dev on d2 since backends match
1832 we cannot enable two streams on two different devices if they
1833 share the same backend. e.g. if offload is on speaker device using
1834 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1835 using the same backend, offload must also be switched to voice-handset.
1836
1837case 5
1838 uc->dev d1 (a1) B1
1839 new_uc->dev d1 (a1), d2 (a2) B1
1840
1841 resolution: disable enable uc-dev on d2 since backends match
1842 we cannot enable two streams on two different devices if they
1843 share the same backend.
1844
1845case 6
1846 uc->dev d1 (a1) B1
1847 new_uc->dev d2 (a1) B2
1848
1849 resolution: no need to switch
1850
1851case 7
1852 uc->dev d1 (a1), d2 (a2) B1, B2
1853 new_uc->dev d1 (a1) B1
1854
1855 resolution: no need to switch
1856
Zhou Song4ba65882018-07-09 14:48:07 +08001857case 8
1858 uc->dev d1 (a1) B1
1859 new_uc->dev d11 (a1), d2 (a2) B1, B2
1860 resolution: compared to case 1, for this case, d1 and d11 are related
1861 then need to do the same as case 2 to siwtch to new uc
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301862
1863case 9
1864 uc->dev d1 (a1), d2(a2) B1 B2
1865 new_uc->dev d1 (a1), d22 (a2) B1, B2
1866 resolution: disable enable uc-dev on d2 since backends match
1867 we cannot enable two streams on two different devices if they
1868 share the same backend. This is special case for combo use case
1869 with a2dp and sco devices which uses same backend.
1870 e.g. speaker-a2dp and speaker-btsco
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001871*/
1872static snd_device_t derive_playback_snd_device(void * platform,
1873 struct audio_usecase *uc,
1874 struct audio_usecase *new_uc,
1875 snd_device_t new_snd_device)
1876{
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001877 struct listnode a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001878
1879 snd_device_t d1 = uc->out_snd_device;
1880 snd_device_t d2 = new_snd_device;
1881
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001882 list_init(&a1);
1883 list_init(&a2);
1884
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301885 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301886 case TRANSCODE_LOOPBACK_RX :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001887 assign_devices(&a1, &uc->stream.inout->out_config.device_list);
1888 assign_devices(&a2, &new_uc->stream.inout->out_config.device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301889 break;
1890 default :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001891 assign_devices(&a1, &uc->stream.out->device_list);
1892 assign_devices(&a2, &new_uc->stream.out->device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301893 break;
1894 }
1895
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001896 // Treat as a special case when a1 and a2 are not disjoint
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001897 if (!compare_devices(&a1, &a2) &&
1898 compare_devices_for_any_match(&a1 ,&a2)) {
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001899 snd_device_t d3[2];
1900 int num_devices = 0;
1901 int ret = platform_split_snd_device(platform,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001902 list_length(&a1) > 1 ? d1 : d2,
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001903 &num_devices,
1904 d3);
1905 if (ret < 0) {
1906 if (ret != -ENOSYS) {
1907 ALOGW("%s failed to split snd_device %d",
1908 __func__,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001909 list_length(&a1) > 1 ? d1 : d2);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001910 }
1911 goto end;
1912 }
1913
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001914 if (platform_check_backends_match(d3[0], d3[1])) {
1915 return d2; // case 5
1916 } else {
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301917 if ((list_length(&a1) > 1) && (list_length(&a2) > 1) &&
1918 platform_check_backends_match(d1, d2))
1919 return d2; //case 9
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001920 if (list_length(&a1) > 1)
Samyak Jaind826b502019-07-17 16:16:42 +05301921 return d1; //case 7
Garmond Leungb9eeba42018-09-18 11:10:41 -07001922 // check if d1 is related to any of d3's
1923 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001924 return d1; // case 1
1925 else
1926 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001927 }
1928 } else {
1929 if (platform_check_backends_match(d1, d2)) {
1930 return d2; // case 2, 4
1931 } else {
1932 return d1; // case 6, 3
1933 }
1934 }
1935
1936end:
1937 return d2; // return whatever was calculated before.
1938}
1939
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001940static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301941 struct audio_usecase *uc_info,
1942 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001943{
1944 struct listnode *node;
1945 struct audio_usecase *usecase;
1946 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301947 snd_device_t uc_derive_snd_device;
1948 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001949 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1950 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001951 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301952 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001953 /*
1954 * This function is to make sure that all the usecases that are active on
1955 * the hardware codec backend are always routed to any one device that is
1956 * handled by the hardware codec.
1957 * For example, if low-latency and deep-buffer usecases are currently active
1958 * on speaker and out_set_parameters(headset) is received on low-latency
1959 * output, then we have to make sure deep-buffer is also switched to headset,
1960 * because of the limitation that both the devices cannot be enabled
1961 * at the same time as they share the same backend.
1962 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001963 /*
1964 * This call is to check if we need to force routing for a particular stream
1965 * If there is a backend configuration change for the device when a
1966 * new stream starts, then ADM needs to be closed and re-opened with the new
1967 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001968 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001969 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001970 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1971 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301972 /* For a2dp device reconfigure all active sessions
1973 * with new AFE encoder format based on a2dp state
1974 */
1975 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301976 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device ||
1977 SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP == snd_device) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301978 audio_extn_a2dp_is_force_device_switch()) {
1979 force_routing = true;
1980 force_restart_session = true;
1981 }
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001982
1983 /*
1984 * Island cfg and power mode config needs to set before AFE port start.
1985 * Set force routing in case of voice device was enable before.
1986 */
1987 if (uc_info->type == VOICE_CALL &&
1988 voice_extn_is_voice_power_mode_supported() &&
Kunlei Zhang67cc7072020-12-18 17:16:49 +08001989 is_supported_conc_usecase_for_power_mode_call(adev) &&
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001990 platform_check_and_update_island_power_status(adev->platform,
1991 uc_info,
1992 snd_device)) {
1993 force_routing = true;
1994 ALOGD("%s:becf: force routing %d for power mode supported device",
1995 __func__, force_routing);
1996 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301997 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1998
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001999 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002000 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002001 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002002 for (i = 0; i < AUDIO_USECASE_MAX; i++)
2003 switch_device[i] = false;
2004
2005 list_for_each(node, &adev->usecase_list) {
2006 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08002007
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05302008 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
2009 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302010 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05302011 platform_get_snd_device_name(usecase->out_snd_device),
2012 platform_check_backends_match(snd_device, usecase->out_snd_device));
Rahul Sharma99770982019-03-06 17:05:26 +05302013 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
2014 (usecase->type != PCM_PASSTHROUGH)) {
Ashish Jain6a65b352017-03-21 17:24:40 +05302015 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
2016 usecase, uc_info, snd_device);
2017 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002018 (is_codec_backend_out_device_type(&usecase->device_list) ||
2019 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
2020 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_DEVICE) ||
2021 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_HEADSET) ||
2022 is_a2dp_out_device_type(&usecase->device_list) ||
2023 is_sco_out_device_type(&usecase->device_list)) &&
Ashish Jain6a65b352017-03-21 17:24:40 +05302024 ((force_restart_session) ||
2025 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05302026 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
2027 __func__, use_case_table[usecase->id],
2028 platform_get_snd_device_name(usecase->out_snd_device));
2029 disable_audio_route(adev, usecase);
2030 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05302031 /* Enable existing usecase on derived playback device */
2032 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05302033 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05302034 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002035 }
2036 }
2037
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302038 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
2039 num_uc_to_switch);
2040
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002041 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07002042 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002043
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05302044 /* Make sure the previous devices to be disabled first and then enable the
2045 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002046 list_for_each(node, &adev->usecase_list) {
2047 usecase = node_to_item(node, struct audio_usecase, list);
2048 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08002049 /* Check if output sound device to be switched can be split and if any
2050 of the split devices match with derived sound device */
2051 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
2052 &num_devices, split_snd_devices) == 0) {
2053 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
2054 for (i = 0; i < num_devices; i++) {
2055 /* Disable devices that do not match with derived sound device */
2056 if (split_snd_devices[i] != derive_snd_device[usecase->id])
2057 disable_snd_device(adev, split_snd_devices[i]);
2058 }
2059 } else {
2060 disable_snd_device(adev, usecase->out_snd_device);
2061 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002062 }
2063 }
2064
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07002065 list_for_each(node, &adev->usecase_list) {
2066 usecase = node_to_item(node, struct audio_usecase, list);
2067 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08002068 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
2069 &num_devices, split_snd_devices) == 0) {
2070 /* Enable derived sound device only if it does not match with
2071 one of the split sound devices. This is because the matching
2072 sound device was not disabled */
2073 bool should_enable = true;
2074 for (i = 0; i < num_devices; i++) {
2075 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
2076 should_enable = false;
2077 break;
2078 }
2079 }
2080 if (should_enable)
2081 enable_snd_device(adev, derive_snd_device[usecase->id]);
2082 } else {
2083 enable_snd_device(adev, derive_snd_device[usecase->id]);
2084 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07002085 }
2086 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002087
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002088 /* Re-route all the usecases on the shared backend other than the
2089 specified usecase to new snd devices */
2090 list_for_each(node, &adev->usecase_list) {
2091 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05302092 /* Update the out_snd_device only before enabling the audio route */
2093 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05302094 usecase->out_snd_device = derive_snd_device[usecase->id];
Lakshman Chaluvarajuab7e5572020-10-28 19:29:23 +05302095 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
2096 use_case_table[usecase->id],
2097 platform_get_snd_device_name(usecase->out_snd_device));
2098 /* Update voc calibration before enabling Voice/VoIP route */
2099 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL)
2100 status = platform_switch_voice_call_device_post(adev->platform,
2101 usecase->out_snd_device,
2102 platform_get_input_snd_device(
2103 adev->platform, NULL,
2104 &uc_info->device_list,
2105 usecase->type));
2106 enable_audio_route(adev, usecase);
2107 if (usecase->stream.out && usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
2108 out_set_voip_volume(&usecase->stream.out->stream,
2109 usecase->stream.out->volume_l,
2110 usecase->stream.out->volume_r);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05302111 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002112 }
2113 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002114 }
2115}
2116
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302117static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002118 struct audio_usecase *uc_info,
2119 snd_device_t snd_device)
2120{
2121 struct listnode *node;
2122 struct audio_usecase *usecase;
2123 bool switch_device[AUDIO_USECASE_MAX];
2124 int i, num_uc_to_switch = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002125 int backend_check_cond = is_codec_backend_out_device_type(&uc_info->device_list);
kunleiz5cd52b82016-11-07 17:22:52 +08002126 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002127
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302128 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
2129 snd_device);
2130 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05302131
2132 /*
2133 * Make sure out devices is checked against out codec backend device and
2134 * also in devices against in codec backend. Checking out device against in
2135 * codec backend or vice versa causes issues.
2136 */
2137 if (uc_info->type == PCM_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002138 backend_check_cond = is_codec_backend_in_device_type(&uc_info->device_list);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08002139
2140 /*
2141 * Island cfg and power mode config needs to set before AFE port start.
2142 * Set force routing in case of voice device was enable before.
2143 */
2144
2145 if (uc_info->type == VOICE_CALL &&
2146 voice_extn_is_voice_power_mode_supported() &&
Kunlei Zhang67cc7072020-12-18 17:16:49 +08002147 is_supported_conc_usecase_for_power_mode_call(adev) &&
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08002148 platform_check_and_update_island_power_status(adev->platform,
2149 uc_info,
2150 snd_device)) {
2151 force_routing = true;
2152 ALOGD("%s:becf: force routing %d for power mode supported device",
2153 __func__, force_routing);
2154 }
2155
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002156 /*
2157 * This function is to make sure that all the active capture usecases
2158 * are always routed to the same input sound device.
2159 * For example, if audio-record and voice-call usecases are currently
2160 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
2161 * is received for voice call then we have to make sure that audio-record
2162 * usecase is also switched to earpiece i.e. voice-dmic-ef,
2163 * because of the limitation that two devices cannot be enabled
2164 * at the same time if they share the same backend.
2165 */
2166 for (i = 0; i < AUDIO_USECASE_MAX; i++)
2167 switch_device[i] = false;
2168
2169 list_for_each(node, &adev->usecase_list) {
2170 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05302171 /*
2172 * TODO: Enhance below condition to handle BT sco/USB multi recording
2173 */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302174
2175 bool capture_uc_needs_routing = usecase->type != PCM_PLAYBACK && (usecase != uc_info &&
2176 (usecase->in_snd_device != snd_device || force_routing));
2177 bool call_proxy_snd_device = platform_is_call_proxy_snd_device(snd_device) ||
2178 platform_is_call_proxy_snd_device(usecase->in_snd_device);
2179 if (capture_uc_needs_routing && !call_proxy_snd_device &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002180 ((backend_check_cond &&
2181 (is_codec_backend_in_device_type(&usecase->device_list) ||
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08002182 (usecase->type == VOIP_CALL))) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08002183 ((uc_info->type == VOICE_CALL &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002184 is_single_device_type_equal(&usecase->device_list,
2185 AUDIO_DEVICE_IN_VOICE_CALL)) ||
Anver sadhique4fdc6992022-01-21 12:26:28 +05302186 platform_check_all_backends_match(snd_device,\
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002187 usecase->in_snd_device))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07002188 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05302189 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..",
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002190 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07002191 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002192 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002193 switch_device[usecase->id] = true;
2194 num_uc_to_switch++;
2195 }
2196 }
2197
2198 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07002199 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002200
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05302201 /* Make sure the previous devices to be disabled first and then enable the
2202 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002203 list_for_each(node, &adev->usecase_list) {
2204 usecase = node_to_item(node, struct audio_usecase, list);
2205 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002206 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08002207 }
2208 }
2209
2210 list_for_each(node, &adev->usecase_list) {
2211 usecase = node_to_item(node, struct audio_usecase, list);
2212 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002213 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002214 }
2215 }
2216
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002217 /* Re-route all the usecases on the shared backend other than the
2218 specified usecase to new snd devices */
2219 list_for_each(node, &adev->usecase_list) {
2220 usecase = node_to_item(node, struct audio_usecase, list);
2221 /* Update the in_snd_device only before enabling the audio route */
2222 if (switch_device[usecase->id] ) {
2223 usecase->in_snd_device = snd_device;
Lakshman Chaluvarajuab7e5572020-10-28 19:29:23 +05302224 /* Update voc calibration before enabling Voice/VoIP route */
2225 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
2226 snd_device_t voip_snd_device;
2227 voip_snd_device = platform_get_output_snd_device(adev->platform,
2228 usecase->stream.out,
2229 usecase->type);
2230 status = platform_switch_voice_call_device_post(adev->platform,
2231 voip_snd_device,
2232 usecase->in_snd_device);
kunleiz5cd52b82016-11-07 17:22:52 +08002233 }
Lakshman Chaluvarajuab7e5572020-10-28 19:29:23 +05302234 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002235 }
2236 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002237 }
2238}
2239
Mingming Yin3a941d42016-02-17 18:08:05 -08002240static void reset_hdmi_sink_caps(struct stream_out *out) {
2241 int i = 0;
2242
2243 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
2244 out->supported_channel_masks[i] = 0;
2245 }
2246 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
2247 out->supported_formats[i] = 0;
2248 }
2249 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
2250 out->supported_sample_rates[i] = 0;
2251 }
2252}
2253
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002254/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08002255static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002256{
Mingming Yin3a941d42016-02-17 18:08:05 -08002257 int ret = 0, i = 0, j = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002258 int channels = platform_edid_get_max_channels_v2(out->dev->platform,
2259 out->extconn.cs.controller,
2260 out->extconn.cs.stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002261
Mingming Yin3a941d42016-02-17 18:08:05 -08002262 reset_hdmi_sink_caps(out);
2263
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002264 /* Cache ext disp type */
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002265 ret = platform_get_ext_disp_type_v2(adev->platform,
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002266 out->extconn.cs.controller,
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002267 out->extconn.cs.stream);
2268 if(ret < 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002269 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07002270 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002271 }
2272
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002273 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002274 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08002275 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002276 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08002277 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
2278 case 6:
2279 ALOGV("%s: HDMI supports 5.1 channels", __func__);
2280 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
2281 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
2282 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
2283 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
2284 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002285 break;
2286 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08002287 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002288 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002289 break;
2290 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002291
2292 // check channel format caps
2293 i = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002294 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_AC3,
2295 out->extconn.cs.controller,
2296 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002297 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
2298 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
2299 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
2300 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
2301 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
2302 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
2303 }
2304
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002305 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD,
2306 out->extconn.cs.controller,
2307 out->extconn.cs.stream)) {
Ben Romberger1aaaf862017-04-06 17:49:46 -07002308 ALOGV(":%s HDMI supports TRUE HD format", __func__);
2309 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
2310 }
2311
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002312 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS,
2313 out->extconn.cs.controller,
2314 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002315 ALOGV(":%s HDMI supports DTS format", __func__);
2316 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
2317 }
2318
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002319 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS_HD,
2320 out->extconn.cs.controller,
2321 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002322 ALOGV(":%s HDMI supports DTS HD format", __func__);
2323 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
2324 }
2325
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002326 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_IEC61937,
2327 out->extconn.cs.controller,
2328 out->extconn.cs.stream)) {
Naresh Tanniru928f0862017-04-07 16:44:23 -07002329 ALOGV(":%s HDMI supports IEC61937 format", __func__);
2330 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
2331 }
2332
Mingming Yin3a941d42016-02-17 18:08:05 -08002333
2334 // check sample rate caps
2335 i = 0;
2336 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002337 if (platform_is_edid_supported_sample_rate_v2(out->dev->platform, out_hdmi_sample_rates[j],
2338 out->extconn.cs.controller,
2339 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002340 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
2341 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
2342 }
2343 }
2344
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002345 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002346}
2347
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002348static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
2349 uint32_t *supported_sample_rates __unused,
2350 uint32_t max_rates __unused)
2351{
2352 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
2353 supported_sample_rates,
2354 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05302355 ssize_t i = 0;
2356
2357 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002358 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
2359 supported_sample_rates[i]);
2360 }
2361 return count;
2362}
2363
2364static inline int read_usb_sup_channel_masks(bool is_playback,
2365 audio_channel_mask_t *supported_channel_masks,
2366 uint32_t max_masks)
2367{
2368 int channels = audio_extn_usb_get_max_channels(is_playback);
2369 int channel_count;
2370 uint32_t num_masks = 0;
2371 if (channels > MAX_HIFI_CHANNEL_COUNT)
2372 channels = MAX_HIFI_CHANNEL_COUNT;
2373
2374 if (is_playback) {
Eric Laurent68a87112019-05-01 18:07:29 -07002375 // start from 2 channels as framework currently doesn't support mono.
2376 if (channels >= FCC_2) {
2377 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(FCC_2);
2378 }
2379 for (channel_count = FCC_2;
2380 channel_count <= channels && num_masks < max_masks;
2381 ++channel_count) {
2382 supported_channel_masks[num_masks++] =
2383 audio_channel_mask_for_index_assignment_from_count(channel_count);
2384 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002385 } else {
vincenttewf51c94e2019-05-07 10:28:53 +08002386 // For capture we report all supported channel masks from 1 channel up.
2387 channel_count = MIN_CHANNEL_COUNT;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002388 // audio_channel_in_mask_from_count() does the right conversion to either positional or
2389 // indexed mask
Eric Laurent68a87112019-05-01 18:07:29 -07002390 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
2391 audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
2392 if (channel_count <= FCC_2) {
2393 mask = audio_channel_in_mask_from_count(channel_count);
2394 supported_channel_masks[num_masks++] = mask;
2395 }
2396 const audio_channel_mask_t index_mask =
2397 audio_channel_mask_for_index_assignment_from_count(channel_count);
2398 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
2399 supported_channel_masks[num_masks++] = index_mask;
2400 }
2401 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002402 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302403
vincenttewf51c94e2019-05-07 10:28:53 +08002404 for (size_t i = 0; i < num_masks; ++i) {
2405 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
2406 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302407 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002408 return num_masks;
2409}
2410
2411static inline int read_usb_sup_formats(bool is_playback __unused,
2412 audio_format_t *supported_formats,
2413 uint32_t max_formats __unused)
2414{
2415 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
2416 switch (bitwidth) {
2417 case 24:
2418 // XXX : usb.c returns 24 for s24 and s24_le?
2419 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
2420 break;
2421 case 32:
2422 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
2423 break;
2424 case 16:
2425 default :
2426 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
2427 break;
2428 }
2429 ALOGV("%s: %s supported format %d", __func__,
2430 is_playback ? "P" : "C", bitwidth);
2431 return 1;
2432}
2433
2434static inline int read_usb_sup_params_and_compare(bool is_playback,
2435 audio_format_t *format,
2436 audio_format_t *supported_formats,
2437 uint32_t max_formats,
2438 audio_channel_mask_t *mask,
2439 audio_channel_mask_t *supported_channel_masks,
2440 uint32_t max_masks,
2441 uint32_t *rate,
2442 uint32_t *supported_sample_rates,
2443 uint32_t max_rates) {
2444 int ret = 0;
2445 int num_formats;
2446 int num_masks;
2447 int num_rates;
2448 int i;
2449
2450 num_formats = read_usb_sup_formats(is_playback, supported_formats,
2451 max_formats);
2452 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
2453 max_masks);
2454
2455 num_rates = read_usb_sup_sample_rates(is_playback,
2456 supported_sample_rates, max_rates);
2457
2458#define LUT(table, len, what, dflt) \
2459 for (i=0; i<len && (table[i] != what); i++); \
2460 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
2461
2462 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
2463 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
2464 LUT(supported_sample_rates, num_rates, *rate, 0);
2465
2466#undef LUT
2467 return ret < 0 ? -EINVAL : 0; // HACK TBD
2468}
2469
Alexy Josephb1379942016-01-29 15:49:38 -08002470audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002471 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002472{
2473 struct audio_usecase *usecase;
2474 struct listnode *node;
2475
2476 list_for_each(node, &adev->usecase_list) {
2477 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002478 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002479 ALOGV("%s: usecase id %d", __func__, usecase->id);
2480 return usecase->id;
2481 }
2482 }
2483 return USECASE_INVALID;
2484}
2485
Alexy Josephb1379942016-01-29 15:49:38 -08002486struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002487 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002488{
2489 struct audio_usecase *usecase;
2490 struct listnode *node;
2491
2492 list_for_each(node, &adev->usecase_list) {
2493 usecase = node_to_item(node, struct audio_usecase, list);
2494 if (usecase->id == uc_id)
2495 return usecase;
2496 }
2497 return NULL;
2498}
2499
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302500/*
2501 * is a true native playback active
2502 */
2503bool audio_is_true_native_stream_active(struct audio_device *adev)
2504{
2505 bool active = false;
2506 int i = 0;
2507 struct listnode *node;
2508
2509 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
2510 ALOGV("%s:napb: not in true mode or non hdphones device",
2511 __func__);
2512 active = false;
2513 goto exit;
2514 }
2515
2516 list_for_each(node, &adev->usecase_list) {
2517 struct audio_usecase *uc;
2518 uc = node_to_item(node, struct audio_usecase, list);
2519 struct stream_out *curr_out =
2520 (struct stream_out*) uc->stream.out;
2521
2522 if (curr_out && PCM_PLAYBACK == uc->type) {
2523 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
2524 "(%d) device %s", __func__, i++, use_case_table[uc->id],
2525 uc->id, curr_out->sample_rate,
2526 curr_out->bit_width,
2527 platform_get_snd_device_name(uc->out_snd_device));
2528
2529 if (is_offload_usecase(uc->id) &&
2530 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
2531 active = true;
2532 ALOGD("%s:napb:native stream detected", __func__);
2533 }
2534 }
2535 }
2536exit:
2537 return active;
2538}
2539
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002540uint32_t adev_get_dsp_bit_width_enforce_mode()
2541{
2542 if (adev == NULL) {
2543 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
2544 return 0;
2545 }
2546 return adev->dsp_bit_width_enforce_mode;
2547}
2548
2549static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
2550{
2551 char value[PROPERTY_VALUE_MAX];
2552 int trial;
2553 uint32_t dsp_bit_width_enforce_mode = 0;
2554
2555 if (!mixer) {
2556 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
2557 __func__);
2558 return 0;
2559 }
2560
2561 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
2562 value, NULL) > 0) {
2563 trial = atoi(value);
2564 switch (trial) {
2565 case 16:
2566 dsp_bit_width_enforce_mode = 16;
2567 break;
2568 case 24:
2569 dsp_bit_width_enforce_mode = 24;
2570 break;
2571 case 32:
2572 dsp_bit_width_enforce_mode = 32;
2573 break;
2574 default:
2575 dsp_bit_width_enforce_mode = 0;
2576 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
2577 break;
2578 }
2579 }
2580
2581 return dsp_bit_width_enforce_mode;
2582}
2583
2584static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
2585 uint32_t enforce_mode,
2586 bool enable)
2587{
2588 struct mixer_ctl *ctl = NULL;
2589 const char *mixer_ctl_name = "ASM Bit Width";
2590 uint32_t asm_bit_width_mode = 0;
2591
2592 if (enforce_mode == 0) {
2593 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
2594 return;
2595 }
2596
2597 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
2598 if (!ctl) {
2599 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2600 __func__, mixer_ctl_name);
2601 return;
2602 }
2603
2604 if (enable)
2605 asm_bit_width_mode = enforce_mode;
2606 else
2607 asm_bit_width_mode = 0;
2608
2609 ALOGV("%s DSP bit width feature status is %d width=%d",
2610 __func__, enable, asm_bit_width_mode);
2611 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2612 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2613 asm_bit_width_mode);
2614
2615 return;
2616}
2617
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302618/*
2619 * if native DSD playback active
2620 */
2621bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2622{
2623 bool active = false;
2624 struct listnode *node = NULL;
2625 struct audio_usecase *uc = NULL;
2626 struct stream_out *curr_out = NULL;
2627
2628 list_for_each(node, &adev->usecase_list) {
2629 uc = node_to_item(node, struct audio_usecase, list);
2630 curr_out = (struct stream_out*) uc->stream.out;
2631
2632 if (curr_out && PCM_PLAYBACK == uc->type &&
2633 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2634 active = true;
2635 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302636 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302637 }
2638 }
2639 return active;
2640}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302641
2642static bool force_device_switch(struct audio_usecase *usecase)
2643{
2644 bool ret = false;
2645 bool is_it_true_mode = false;
2646
Zhou Song30f2c3e2018-02-08 14:02:15 +08002647 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302648 usecase->type == TRANSCODE_LOOPBACK_RX ||
2649 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002650 return false;
2651 }
2652
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002653 if(usecase->stream.out == NULL) {
2654 ALOGE("%s: stream.out is NULL", __func__);
2655 return false;
2656 }
2657
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302658 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002659 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002660 (compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADSET) ||
2661 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADPHONE))) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302662 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2663 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2664 (!is_it_true_mode && adev->native_playback_enabled)){
2665 ret = true;
2666 ALOGD("napb: time to toggle native mode");
2667 }
2668 }
2669
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302670 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302671 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2672 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002673 if(is_a2dp_out_device_type(&usecase->stream.out->device_list) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302674 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302675 ALOGD("Force a2dp device switch to update new encoder config");
2676 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002677 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302678
Florian Pfister1a84f312018-07-19 14:38:18 +02002679 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302680 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2681 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002682 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302683 return ret;
2684}
2685
Aalique Grahame22e49102018-12-18 14:23:57 -08002686static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2687{
2688 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2689}
2690
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302691bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2692{
2693 bool ret=false;
2694 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
Zhou Song5657f492019-08-07 11:30:39 +08002695 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
2696 out_snd_device == SND_DEVICE_OUT_BT_SCO_SWB) ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302697 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2698 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
Zhou Song5657f492019-08-07 11:30:39 +08002699 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302700 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
Mingshu Pang16093502020-04-20 11:21:16 +08002701 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC ||
2702 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC)
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302703 ret = true;
2704
2705 return ret;
2706}
2707
2708bool is_a2dp_device(snd_device_t out_snd_device)
2709{
2710 bool ret=false;
2711 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2712 ret = true;
2713
2714 return ret;
2715}
2716
2717bool is_bt_soc_on(struct audio_device *adev)
2718{
2719 struct mixer_ctl *ctl;
2720 char *mixer_ctl_name = "BT SOC status";
2721 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2722 bool bt_soc_status = true;
2723 if (!ctl) {
2724 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2725 __func__, mixer_ctl_name);
2726 /*This is to ensure we dont break targets which dont have the kernel change*/
2727 return true;
2728 }
2729 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2730 ALOGD("BT SOC status: %d",bt_soc_status);
2731 return bt_soc_status;
2732}
2733
Zhou Song331c8e52019-08-26 14:16:12 +08002734static int configure_btsco_sample_rate(snd_device_t snd_device)
2735{
2736 struct mixer_ctl *ctl = NULL;
2737 struct mixer_ctl *ctl_sr_rx = NULL, *ctl_sr_tx = NULL, *ctl_sr = NULL;
2738 char *rate_str = NULL;
2739 bool is_rx_dev = true;
2740
2741 if (is_btsco_device(snd_device, snd_device)) {
2742 ctl_sr_tx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate TX");
2743 ctl_sr_rx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate RX");
2744 if (!ctl_sr_tx || !ctl_sr_rx) {
2745 ctl_sr = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate");
2746 if (!ctl_sr)
2747 return -ENOSYS;
2748 }
2749
2750 switch (snd_device) {
2751 case SND_DEVICE_OUT_BT_SCO:
2752 rate_str = "KHZ_8";
2753 break;
2754 case SND_DEVICE_IN_BT_SCO_MIC_NREC:
2755 case SND_DEVICE_IN_BT_SCO_MIC:
2756 rate_str = "KHZ_8";
2757 is_rx_dev = false;
2758 break;
2759 case SND_DEVICE_OUT_BT_SCO_WB:
2760 rate_str = "KHZ_16";
2761 break;
2762 case SND_DEVICE_IN_BT_SCO_MIC_WB_NREC:
2763 case SND_DEVICE_IN_BT_SCO_MIC_WB:
2764 rate_str = "KHZ_16";
2765 is_rx_dev = false;
2766 break;
2767 default:
2768 return 0;
2769 }
2770
2771 ctl = (ctl_sr == NULL) ? (is_rx_dev ? ctl_sr_rx : ctl_sr_tx) : ctl_sr;
2772 if (mixer_ctl_set_enum_by_string(ctl, rate_str) != 0)
2773 return -ENOSYS;
2774 }
2775 return 0;
2776}
2777
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302778int out_standby_l(struct audio_stream *stream);
2779
Eric Laurent637e2d42018-11-15 12:24:31 -08002780struct stream_in *adev_get_active_input(const struct audio_device *adev)
2781{
2782 struct listnode *node;
2783 struct stream_in *last_active_in = NULL;
2784
2785 /* Get last added active input.
2786 * TODO: We may use a priority mechanism to pick highest priority active source */
2787 list_for_each(node, &adev->usecase_list)
2788 {
2789 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2790 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL)
2791 last_active_in = usecase->stream.in;
2792 }
2793
2794 return last_active_in;
2795}
2796
2797struct stream_in *get_voice_communication_input(const struct audio_device *adev)
2798{
2799 struct listnode *node;
2800
2801 /* First check active inputs with voice communication source and then
2802 * any input if audio mode is in communication */
2803 list_for_each(node, &adev->usecase_list)
2804 {
2805 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2806 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
2807 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
2808 return usecase->stream.in;
2809 }
2810 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION)
2811 return adev_get_active_input(adev);
2812
2813 return NULL;
2814}
2815
Carter Hsu2e429db2019-05-14 18:50:52 +08002816/*
2817 * Aligned with policy.h
2818 */
2819static inline int source_priority(int inputSource)
2820{
2821 switch (inputSource) {
2822 case AUDIO_SOURCE_VOICE_COMMUNICATION:
2823 return 9;
2824 case AUDIO_SOURCE_CAMCORDER:
2825 return 8;
2826 case AUDIO_SOURCE_VOICE_PERFORMANCE:
2827 return 7;
2828 case AUDIO_SOURCE_UNPROCESSED:
2829 return 6;
2830 case AUDIO_SOURCE_MIC:
2831 return 5;
2832 case AUDIO_SOURCE_ECHO_REFERENCE:
2833 return 4;
2834 case AUDIO_SOURCE_FM_TUNER:
2835 return 3;
2836 case AUDIO_SOURCE_VOICE_RECOGNITION:
2837 return 2;
2838 case AUDIO_SOURCE_HOTWORD:
2839 return 1;
2840 default:
2841 break;
2842 }
2843 return 0;
2844}
2845
2846static struct stream_in *get_priority_input(struct audio_device *adev)
2847{
2848 struct listnode *node;
2849 struct audio_usecase *usecase;
2850 int last_priority = 0, priority;
2851 struct stream_in *priority_in = NULL;
2852 struct stream_in *in;
2853
2854 list_for_each(node, &adev->usecase_list) {
2855 usecase = node_to_item(node, struct audio_usecase, list);
2856 if (usecase->type == PCM_CAPTURE) {
2857 in = usecase->stream.in;
2858 if (!in)
2859 continue;
2860 priority = source_priority(in->source);
2861
2862 if (priority > last_priority) {
2863 last_priority = priority;
2864 priority_in = in;
2865 }
2866 }
2867 }
2868 return priority_in;
2869}
2870
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002871int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002872{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002873 snd_device_t out_snd_device = SND_DEVICE_NONE;
2874 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002875 struct audio_usecase *usecase = NULL;
2876 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002877 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002878 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302879 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002880 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002881 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002882
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302883 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2884
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002885 usecase = get_usecase_from_list(adev, uc_id);
2886 if (usecase == NULL) {
2887 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2888 return -EINVAL;
2889 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002890
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002891 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002892 (usecase->type == VOIP_CALL) ||
Derek Chena30a5f42019-12-03 11:17:09 -05002893 (usecase->type == PCM_HFP_CALL)||
Fei Tongaffdf732020-02-20 20:39:05 +08002894 (usecase->type == ICC_CALL) ||
2895 (usecase->type == SYNTH_LOOPBACK)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302896 if(usecase->stream.out == NULL) {
2897 ALOGE("%s: stream.out is NULL", __func__);
2898 return -EINVAL;
2899 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002900 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS)) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002901 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev,
2902 uc_id);
2903 in_snd_device = audio_extn_auto_hal_get_input_snd_device(adev,
2904 uc_id);
2905 } else {
2906 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302907 usecase->stream.out, usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002908 in_snd_device = platform_get_input_snd_device(adev->platform,
2909 NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302910 &usecase->stream.out->device_list,
2911 usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002912 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002913 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302914 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302915 if (usecase->stream.inout == NULL) {
2916 ALOGE("%s: stream.inout is NULL", __func__);
2917 return -EINVAL;
2918 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002919 assign_devices(&stream_out.device_list, &usecase->stream.inout->out_config.device_list);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302920 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2921 stream_out.format = usecase->stream.inout->out_config.format;
2922 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
Jaideep Sharma477917f2020-03-13 18:13:33 +05302923 out_snd_device = platform_get_output_snd_device(adev->platform, &stream_out, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002924 assign_devices(&usecase->device_list,
2925 &usecase->stream.inout->out_config.device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302926 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2927 if (usecase->stream.inout == NULL) {
2928 ALOGE("%s: stream.inout is NULL", __func__);
2929 return -EINVAL;
2930 }
Manisha Agarwal03297972020-04-17 15:36:55 +05302931 struct listnode out_devices;
2932 list_init(&out_devices);
2933 in_snd_device = platform_get_input_snd_device(adev->platform, NULL,
2934 &out_devices, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002935 assign_devices(&usecase->device_list,
2936 &usecase->stream.inout->in_config.device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002937 } else {
2938 /*
2939 * If the voice call is active, use the sound devices of voice call usecase
2940 * so that it would not result any device switch. All the usecases will
2941 * be switched to new device when select_devices() is called for voice call
2942 * usecase. This is to avoid switching devices for voice call when
2943 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002944 * choose voice call device only if the use case device is
2945 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002946 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002947 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002948 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002949 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002950 if ((vc_usecase) && ((is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2951 is_codec_backend_out_device_type(&usecase->device_list)) ||
2952 (is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2953 is_codec_backend_in_device_type(&usecase->device_list)) ||
2954 is_single_device_type_equal(&vc_usecase->device_list,
2955 AUDIO_DEVICE_OUT_HEARING_AID) ||
2956 is_single_device_type_equal(&usecase->device_list,
Robert Lee8a6aaf32019-09-20 16:40:19 +08002957 AUDIO_DEVICE_IN_VOICE_CALL) ||
2958 (is_single_device_type_equal(&usecase->device_list,
Gautam Manam8fa06162021-09-24 10:41:29 +05302959 AUDIO_DEVICE_IN_BUILTIN_MIC) &&
2960 is_single_device_type_equal(&vc_usecase->device_list,
2961 AUDIO_DEVICE_OUT_USB_HEADSET)) ||
2962 (is_single_device_type_equal(&usecase->device_list,
Robert Lee8a6aaf32019-09-20 16:40:19 +08002963 AUDIO_DEVICE_IN_USB_HEADSET) &&
2964 is_single_device_type_equal(&vc_usecase->device_list,
Kamalakar Yalasiri5edba852021-01-28 14:52:38 +05302965 AUDIO_DEVICE_OUT_USB_HEADSET))||
Gautam Manamf4002142021-09-13 22:05:56 +05302966 (is_single_device_type_equal(&usecase->device_list,
2967 AUDIO_DEVICE_IN_USB_HEADSET) &&
2968 is_codec_backend_out_device_type(&vc_usecase->device_list)) ||
Kamalakar Yalasiri5edba852021-01-28 14:52:38 +05302969 (is_single_device_type_equal(&usecase->device_list,
2970 AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) &&
2971 is_codec_backend_out_device_type(&vc_usecase->device_list)))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002972 in_snd_device = vc_usecase->in_snd_device;
2973 out_snd_device = vc_usecase->out_snd_device;
2974 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002975 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002976 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002977 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002978 if ((voip_usecase != NULL) &&
2979 (usecase->type == PCM_PLAYBACK) &&
2980 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002981 out_snd_device_backend_match = platform_check_backends_match(
2982 voip_usecase->out_snd_device,
2983 platform_get_output_snd_device(
2984 adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302985 usecase->stream.out, usecase->type));
yidongh02ef86f2017-04-21 15:36:04 +08002986 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002987 if ((voip_usecase) && (is_codec_backend_out_device_type(&voip_usecase->device_list) &&
2988 (is_codec_backend_out_device_type(&usecase->device_list) ||
2989 is_codec_backend_in_device_type(&usecase->device_list)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002990 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002991 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002992 in_snd_device = voip_usecase->in_snd_device;
2993 out_snd_device = voip_usecase->out_snd_device;
2994 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002995 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002996 hfp_ucid = audio_extn_hfp_get_usecase();
2997 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002998 if ((hfp_usecase) && is_codec_backend_out_device_type(&hfp_usecase->device_list)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002999 in_snd_device = hfp_usecase->in_snd_device;
3000 out_snd_device = hfp_usecase->out_snd_device;
3001 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003002 }
3003 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05303004 if (usecase->stream.out == NULL) {
3005 ALOGE("%s: stream.out is NULL", __func__);
3006 return -EINVAL;
3007 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003008 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003009 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003010 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003011 struct stream_out *voip_out = adev->primary_output;
3012 struct stream_in *voip_in = get_voice_communication_input(adev);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003013 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS))
Guodong Hu267bdf82019-08-12 19:22:32 +08003014 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev, uc_id);
3015 else
3016 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05303017 usecase->stream.out,
3018 usecase->type);
kunleizdcf967a2018-08-07 17:09:11 +08003019 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizdcf967a2018-08-07 17:09:11 +08003020
Eric Laurent637e2d42018-11-15 12:24:31 -08003021 if (voip_usecase)
3022 voip_out = voip_usecase->stream.out;
3023
3024 if (usecase->stream.out == voip_out && voip_in != NULL)
3025 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003026 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003027 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05303028 if (usecase->stream.in == NULL) {
3029 ALOGE("%s: stream.in is NULL", __func__);
3030 return -EINVAL;
3031 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003032 assign_devices(&usecase->device_list, &usecase->stream.in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003033 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003034 if (in_snd_device == SND_DEVICE_NONE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003035 struct listnode out_devices;
Eric Laurent637e2d42018-11-15 12:24:31 -08003036 struct stream_in *voip_in = get_voice_communication_input(adev);
Carter Hsu2e429db2019-05-14 18:50:52 +08003037 struct stream_in *priority_in = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08003038
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003039 list_init(&out_devices);
Eric Laurent637e2d42018-11-15 12:24:31 -08003040 if (voip_in != NULL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003041 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
3042 USECASE_AUDIO_PLAYBACK_VOIP);
3043
Carter Hsu2e429db2019-05-14 18:50:52 +08003044 usecase->stream.in->enable_ec_port = false;
3045
Zhou Song503196b2021-07-23 17:31:05 +08003046 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY ||
3047 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY2) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003048 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_TELEPHONY_TX, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08003049 } else if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003050 assign_devices(&out_devices, &voip_usecase->stream.out->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08003051 } else if (adev->primary_output &&
3052 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003053 assign_devices(&out_devices, &adev->primary_output->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08003054 } else {
3055 /* forcing speaker o/p device to get matching i/p pair
3056 in case o/p is not routed from same primary HAL */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003057 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08003058 }
Carter Hsu2e429db2019-05-14 18:50:52 +08003059 priority_in = voip_in;
3060 } else {
3061 /* get the input with the highest priority source*/
3062 priority_in = get_priority_input(adev);
3063
Susan Wang727dd6b2021-03-26 11:28:59 -04003064 if (!priority_in ||
3065 audio_extn_auto_hal_overwrite_priority_for_auto(usecase->stream.in))
Carter Hsu2e429db2019-05-14 18:50:52 +08003066 priority_in = usecase->stream.in;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003067 }
Huicheng Liu1404ba12020-09-11 01:03:25 -04003068 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_IN_BUS)){
3069 in_snd_device = audio_extn_auto_hal_get_snd_device_for_car_audio_stream(priority_in->car_audio_stream);
3070 }
3071 else
3072 in_snd_device = platform_get_input_snd_device(adev->platform,
3073 priority_in,
3074 &out_devices,
3075 usecase->type);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003076 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003077 }
3078 }
3079
3080 if (out_snd_device == usecase->out_snd_device &&
3081 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05303082
3083 if (!force_device_switch(usecase))
3084 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003085 }
3086
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003087 if (!compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS) &&
Guodong Hu267bdf82019-08-12 19:22:32 +08003088 ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003089 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready()))) {
Guodong Hu267bdf82019-08-12 19:22:32 +08003090 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
3091 return 0;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303092 }
3093
Aalique Grahame22e49102018-12-18 14:23:57 -08003094 if (out_snd_device != SND_DEVICE_NONE &&
3095 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
3096 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
3097 __func__,
3098 use_case_table[uc_id],
3099 adev->last_logged_snd_device[uc_id][0],
3100 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
3101 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
3102 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
3103 -1,
3104 out_snd_device,
3105 platform_get_snd_device_name(out_snd_device),
3106 platform_get_snd_device_acdb_id(out_snd_device));
3107 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
3108 }
3109 if (in_snd_device != SND_DEVICE_NONE &&
3110 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
3111 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
3112 __func__,
3113 use_case_table[uc_id],
3114 adev->last_logged_snd_device[uc_id][1],
3115 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
3116 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
3117 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
3118 -1,
3119 in_snd_device,
3120 platform_get_snd_device_name(in_snd_device),
3121 platform_get_snd_device_acdb_id(in_snd_device));
3122 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
3123 }
3124
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003125
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003126 /*
3127 * Limitation: While in call, to do a device switch we need to disable
3128 * and enable both RX and TX devices though one of them is same as current
3129 * device.
3130 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07003131 if ((usecase->type == VOICE_CALL) &&
3132 (usecase->in_snd_device != SND_DEVICE_NONE) &&
3133 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07003134 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07003135 }
3136
3137 if (((usecase->type == VOICE_CALL) ||
3138 (usecase->type == VOIP_CALL)) &&
3139 (usecase->out_snd_device != SND_DEVICE_NONE)) {
3140 /* Disable sidetone only if voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303141 if (voice_is_call_state_active_in_call(adev) ||
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07003142 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07003143 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003144
3145 /* Disable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303146 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003147 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08003148 }
3149
Aalique Grahame22e49102018-12-18 14:23:57 -08003150 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
3151 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003152 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303153 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08003154 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
3155 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
3156 else
3157 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303158 }
3159
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003160 /* Disable current sound devices */
3161 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003162 disable_audio_route(adev, usecase);
3163 disable_snd_device(adev, usecase->out_snd_device);
Gautam Manam274f4752021-09-24 10:58:49 +05303164 if (usecase->id == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
3165 disable_snd_device(adev, SND_DEVICE_OUT_HAPTICS);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003166 }
3167
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003168 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003169 disable_audio_route(adev, usecase);
3170 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003171 }
3172
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08003173 /* Applicable only on the targets that has external modem.
3174 * New device information should be sent to modem before enabling
3175 * the devices to reduce in-call device switch time.
3176 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07003177 if ((usecase->type == VOICE_CALL) &&
3178 (usecase->in_snd_device != SND_DEVICE_NONE) &&
3179 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08003180 status = platform_switch_voice_call_enable_device_config(adev->platform,
3181 out_snd_device,
3182 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07003183 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08003184
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003185 /* Enable new sound devices */
3186 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08003187 check_usecases_codec_backend(adev, usecase, out_snd_device);
Saurav Kumarc1411662020-10-14 10:50:45 +05303188 check_and_configure_headphone(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05303189 if (platform_check_codec_asrc_support(adev->platform))
3190 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003191 enable_snd_device(adev, out_snd_device);
Zhou Songd9bd9302020-08-04 16:34:45 +08003192 /* Enable haptics device for haptic usecase */
3193 if (usecase->id == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
3194 enable_snd_device(adev, SND_DEVICE_OUT_HAPTICS);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003195 }
3196
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07003197 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303198 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003199 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07003200 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003201
Lakshman Chaluvarajuab7e5572020-10-28 19:29:23 +05303202 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL)
Eric Laurentb23d5282013-05-14 15:27:20 -07003203 status = platform_switch_voice_call_device_post(adev->platform,
3204 out_snd_device,
3205 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08003206
sangwoo170731f2013-06-08 15:36:36 +09003207 usecase->in_snd_device = in_snd_device;
3208 usecase->out_snd_device = out_snd_device;
3209
Dhananjay Kumard6d32152016-10-13 16:11:03 +05303210 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
3211 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05303212 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003213 if ((24 == usecase->stream.out->bit_width) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003214 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_SPEAKER)) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003215 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3216 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
3217 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
3218 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
3219 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
3220 /*
3221 * To best utlize DSP, check if the stream sample rate is supported/multiple of
3222 * configured device sample rate, if not update the COPP rate to be equal to the
3223 * device sample rate, else open COPP at stream sample rate
3224 */
3225 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
3226 usecase->stream.out->sample_rate,
3227 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05303228 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
Preetam Singh Ranawat590d0432019-09-30 14:39:47 +05303229 out_snd_device != SND_DEVICE_OUT_HEADPHONES &&
3230 out_snd_device != SND_DEVICE_OUT_HEADPHONES_HIFI_FILTER &&
Ashish Jain4826f6c2017-02-06 13:33:20 +05303231 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003232 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
3233 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +05303234 if (!(compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS) && ((usecase->stream.out->flags &
3235 (audio_output_flags_t)AUDIO_OUTPUT_FLAG_SYS_NOTIFICATION) || (usecase->stream.out->flags &
3236 (audio_output_flags_t)AUDIO_OUTPUT_FLAG_PHONE)))) {
3237 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3238 }
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003239 }
Weiyin Jiangcdece202019-07-08 16:13:16 +08003240 }
3241 enable_audio_route(adev, usecase);
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003242
Shalini Manjunatha5e610912020-12-29 13:02:25 +05303243 if (uc_id == USECASE_AUDIO_PLAYBACK_VOIP) {
3244 struct stream_in *voip_in = get_voice_communication_input(adev);
3245 struct audio_usecase *voip_in_usecase = NULL;
3246 voip_in_usecase = get_usecase_from_list(adev, USECASE_AUDIO_RECORD_VOIP);
3247 if (voip_in != NULL &&
3248 voip_in_usecase != NULL &&
3249 !(out_snd_device == AUDIO_DEVICE_OUT_SPEAKER ||
3250 out_snd_device == AUDIO_DEVICE_OUT_SPEAKER_SAFE) &&
3251 (voip_in_usecase->in_snd_device ==
3252 platform_get_input_snd_device(adev->platform, voip_in,
3253 &usecase->stream.out->device_list,usecase->type))) {
3254 /*
3255 * if VOIP TX is enabled before VOIP RX, needs to re-route the TX path
3256 * for enabling echo-reference-voip with correct port
3257 */
3258 ALOGD("%s: VOIP TX is enabled before VOIP RX,needs to re-route the TX path",__func__);
3259 disable_audio_route(adev, voip_in_usecase);
3260 disable_snd_device(adev, voip_in_usecase->in_snd_device);
3261 enable_snd_device(adev, voip_in_usecase->in_snd_device);
3262 enable_audio_route(adev, voip_in_usecase);
3263 }
3264 }
Ramjee Singhcdf67af2021-09-29 14:20:27 +05303265 if (voice_extn_compress_voip_is_active(adev)) {
3266 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
3267 USECASE_COMPRESS_VOIP_CALL);
3268 /*
3269 * If only compress voip input is opened voip out will be primary out.
3270 * Need to consider re-routing to select correct i/p pair
3271 */
3272 if ((voip_usecase != NULL) &&
3273 (usecase->type == PCM_PLAYBACK) &&
3274 (usecase->stream.out == voip_usecase->stream.out)) {
3275 in_snd_device = platform_get_input_snd_device(adev->platform,
3276 NULL,
3277 &usecase->stream.out->device_list,
3278 usecase->type);
3279 if (voip_usecase->in_snd_device != in_snd_device ) {
3280 ALOGD("%s:Re routing compress voip tx snd device matching voip rx pair",
3281 __func__);
3282 disable_audio_route(adev, voip_usecase);
3283 disable_snd_device(adev, voip_usecase->in_snd_device);
3284 voip_usecase->in_snd_device = in_snd_device;
3285 voip_usecase->out_snd_device = usecase->out_snd_device;
3286 /* Route all TX usecase to Compress voip BE */
3287 check_usecases_capture_codec_backend(adev, voip_usecase, in_snd_device);
3288 enable_snd_device(adev, in_snd_device);
3289 /* Send Voice related calibration for RX /TX pair */
3290 status = platform_switch_voice_call_device_post(adev->platform,
3291 out_snd_device,
3292 in_snd_device);
3293 enable_audio_route(adev, voip_usecase);
3294 }
3295 }
3296 }
Shalini Manjunatha5e610912020-12-29 13:02:25 +05303297
3298
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08003299 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08003300
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003301 /* If input stream is already running then effect needs to be
3302 applied on the new input device that's being enabled here. */
Eric Laurent637e2d42018-11-15 12:24:31 -08003303 if (in_snd_device != SND_DEVICE_NONE)
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003304 check_and_enable_effect(adev);
3305
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003306 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003307 /* Enable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303308 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003309 voice_check_and_update_aanc_path(adev, out_snd_device, true);
3310
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003311 /* Enable sidetone only if other voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303312 if (voice_is_call_state_active_in_call(adev) ||
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003313 voice_extn_compress_voip_is_started(adev))
3314 voice_set_sidetone(adev, out_snd_device, true);
3315 }
3316
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003317 /* Applicable only on the targets that has external modem.
3318 * Enable device command should be sent to modem only after
3319 * enabling voice call mixer controls
3320 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07003321 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003322 status = platform_switch_voice_call_usecase_route_post(adev->platform,
3323 out_snd_device,
3324 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303325
3326 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003327 struct stream_in *in = adev_get_active_input(adev);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303328 if (usecase->type == VOIP_CALL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003329 if (in != NULL && !in->standby) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303330 if (is_bt_soc_on(adev) == false){
3331 ALOGD("BT SCO MIC disconnected while in connection");
Eric Laurent637e2d42018-11-15 12:24:31 -08003332 if (in->pcm != NULL)
3333 pcm_stop(in->pcm);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303334 }
3335 }
3336 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
3337 && usecase->stream.out->started) {
3338 if (is_bt_soc_on(adev) == false) {
3339 ALOGD("BT SCO/A2DP disconnected while in connection");
3340 out_standby_l(&usecase->stream.out->stream.common);
3341 }
3342 }
3343 } else if ((usecase->stream.out != NULL) &&
3344 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05303345 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
3346 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Weiyin Jiang0d373242019-07-25 13:18:17 +08003347 (usecase->type != PCM_CAPTURE) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303348 usecase->stream.out->started) {
3349 if (is_bt_soc_on(adev) == false) {
3350 ALOGD("BT SCO/A2dp disconnected while in connection");
3351 out_standby_l(&usecase->stream.out->stream.common);
3352 }
3353 }
3354 }
3355
Yung Ti Su70cb8242018-06-22 17:38:47 +08003356 if (usecase->type != PCM_CAPTURE && usecase == voip_usecase) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003357 struct stream_out *voip_out = voip_usecase->stream.out;
3358 audio_extn_utils_send_app_type_gain(adev,
3359 voip_out->app_type_cfg.app_type,
3360 &voip_out->app_type_cfg.gain[0]);
3361 }
3362
Ajender Reddyb940b832021-07-07 11:51:42 +05303363 ALOGD("%s: done",__func__);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303364
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003365 return status;
3366}
3367
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003368static int stop_input_stream(struct stream_in *in)
3369{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303370 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003371 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05303372
3373 if (in == NULL) {
3374 ALOGE("%s: stream_in ptr is NULL", __func__);
3375 return -EINVAL;
3376 }
3377
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003378 struct audio_device *adev = in->dev;
Carter Hsu2e429db2019-05-14 18:50:52 +08003379 struct stream_in *priority_in = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003380
Eric Laurent994a6932013-07-17 11:51:42 -07003381 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003382 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003383 uc_info = get_usecase_from_list(adev, in->usecase);
3384 if (uc_info == NULL) {
3385 ALOGE("%s: Could not find the usecase (%d) in the list",
3386 __func__, in->usecase);
3387 return -EINVAL;
3388 }
3389
Carter Hsu2e429db2019-05-14 18:50:52 +08003390 priority_in = get_priority_input(adev);
3391
Derek Chenea197282019-01-07 17:35:01 -08003392 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3393 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003394
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003395 /* Close in-call recording streams */
3396 voice_check_and_stop_incall_rec_usecase(adev, in);
3397
Eric Laurent150dbfe2013-02-27 14:31:02 -08003398 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003399 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003400
3401 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003402 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003403
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003404 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303405 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_PRIMARY);
3406
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003407 list_remove(&uc_info->list);
3408 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003409
Carter Hsu2e429db2019-05-14 18:50:52 +08003410 if (priority_in == in) {
3411 priority_in = get_priority_input(adev);
Sujin Panicker110f7942021-08-26 17:01:22 +05303412 if (priority_in) {
3413 if (is_usb_in_device_type(&priority_in->device_list)) {
3414 if (audio_extn_usb_connected(NULL))
3415 select_devices(adev, priority_in->usecase);
3416 } else {
3417 select_devices(adev, priority_in->usecase);
3418 }
3419 }
Carter Hsu2e429db2019-05-14 18:50:52 +08003420 }
3421
Vatsal Buchac09ae062018-11-14 13:25:08 +05303422 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07003423 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003424 return ret;
3425}
3426
3427int start_input_stream(struct stream_in *in)
3428{
3429 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08003430 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003431 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05303432
3433 if (in == NULL) {
3434 ALOGE("%s: stream_in ptr is NULL", __func__);
3435 return -EINVAL;
3436 }
3437
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003438 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07003439 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07003440 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003441
Mingming Yin2664a5b2015-09-03 10:53:11 -07003442 if (get_usecase_from_list(adev, usecase) == NULL)
3443 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303444 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
3445 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003446
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303447 if (CARD_STATUS_OFFLINE == in->card_status||
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05003448 CARD_STATUS_OFFLINE == adev->card_status ||
3449 POWER_POLICY_STATUS_OFFLINE == adev->in_power_policy) {
3450 ALOGW("in->card_status or adev->card_status or adev->input_power offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303451 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303452 goto error_config;
3453 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303454
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003455 if (is_sco_in_device_type(&in->device_list)) {
Lakshman Chaluvaraju87f53aa2021-02-02 15:50:11 +05303456 if (!adev->bt_sco_on || audio_extn_a2dp_source_is_ready()) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303457 ALOGE("%s: SCO profile is not ready, return error", __func__);
3458 ret = -EIO;
3459 goto error_config;
3460 }
3461 }
3462
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003463 /* Check if source matches incall recording usecase criteria */
3464 ret = voice_check_and_set_incall_rec_usecase(adev, in);
3465 if (ret)
3466 goto error_config;
3467 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07003468 ALOGV("%s: usecase(%d)", __func__, in->usecase);
3469
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303470 if (audio_extn_cin_attached_usecase(in))
3471 audio_extn_cin_acquire_usecase(in);
3472
Mingming Yin2664a5b2015-09-03 10:53:11 -07003473 if (get_usecase_from_list(adev, in->usecase) != NULL) {
3474 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
3475 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Weiyin Jiang38c0e612020-09-10 16:10:51 +08003476 ret = -EINVAL;
3477 goto error_config;
Mingming Yin2664a5b2015-09-03 10:53:11 -07003478 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003479
Eric Laurentb23d5282013-05-14 15:27:20 -07003480 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003481 if (in->pcm_device_id < 0) {
3482 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
3483 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08003484 ret = -EINVAL;
3485 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003486 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003487
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003488 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003489
3490 if (!uc_info) {
3491 ret = -ENOMEM;
3492 goto error_config;
3493 }
3494
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003495 uc_info->id = in->usecase;
3496 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003497 uc_info->stream.in = in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003498 list_init(&uc_info->device_list);
3499 assign_devices(&uc_info->device_list, &in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003500 uc_info->in_snd_device = SND_DEVICE_NONE;
3501 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003502
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003503 list_add_tail(&adev->usecase_list, &uc_info->list);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003504 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303505 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3506 adev->perf_lock_opts,
3507 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003508 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003509
Derek Chenea197282019-01-07 17:35:01 -08003510 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3511 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003512
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05303513 android_atomic_acquire_cas(true, false, &(in->capture_stopped));
3514
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303515 if (audio_extn_cin_attached_usecase(in)) {
Manish Dewangan46e07982018-12-13 18:18:59 +05303516 ret = audio_extn_cin_open_input_stream(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303517 if (ret)
3518 goto error_open;
3519 else
3520 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003521 }
3522
Haynes Mathew George16081042017-05-31 17:16:49 -07003523 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003524 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003525 ALOGE("%s: pcm stream not ready", __func__);
3526 goto error_open;
3527 }
3528 ret = pcm_start(in->pcm);
3529 if (ret < 0) {
3530 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3531 goto error_open;
3532 }
3533 } else {
3534 unsigned int flags = PCM_IN | PCM_MONOTONIC;
3535 unsigned int pcm_open_retry_count = 0;
3536
Zhou Song62ea0282020-03-22 19:53:01 +08003537 if ((in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) ||
3538 (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003539 flags |= PCM_MMAP | PCM_NOIRQ;
3540 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
3541 } else if (in->realtime) {
3542 flags |= PCM_MMAP | PCM_NOIRQ;
3543 }
3544
Garmond Leunge2433c32017-09-28 21:51:22 -07003545 if (audio_extn_ffv_get_stream() == in) {
3546 ALOGD("%s: ffv stream, update pcm config", __func__);
3547 audio_extn_ffv_update_pcm_config(&config);
3548 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003549 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3550 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3551
3552 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003553 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07003554 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07003555 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003556 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303557 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303558 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3559 adev->card_status = CARD_STATUS_OFFLINE;
3560 in->card_status = CARD_STATUS_OFFLINE;
3561 ret = -EIO;
3562 goto error_open;
3563 }
3564
Haynes Mathew George16081042017-05-31 17:16:49 -07003565 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3566 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3567 if (in->pcm != NULL) {
3568 pcm_close(in->pcm);
3569 in->pcm = NULL;
3570 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003571 if (pcm_open_retry_count == 0) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003572 ret = -EIO;
3573 goto error_open;
3574 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003575 pcm_open_retry_count--;
Haynes Mathew George16081042017-05-31 17:16:49 -07003576 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3577 continue;
3578 }
3579 break;
3580 }
3581
3582 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003583 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07003584 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003585 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003586 if (ret < 0) {
3587 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3588 pcm_close(in->pcm);
3589 in->pcm = NULL;
3590 goto error_open;
3591 }
3592 register_in_stream(in);
3593 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003594 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07003595 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003596 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003597 if (ret < 0) {
3598 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003599 pcm_close(in->pcm);
3600 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003601 goto error_open;
3602 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003603 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003604 }
3605
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003606 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07003607 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
3608 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003609
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003610 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303611 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
3612
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303613done_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003614 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303615 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Manisha Agarwal4c2402e2020-10-21 12:02:57 +05303616 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303617 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003618 return ret;
3619
3620error_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003621 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303622 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003623 stop_input_stream(in);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003624
Eric Laurentc8400632013-02-14 19:04:54 -08003625error_config:
Weiyin Jiang38c0e612020-09-10 16:10:51 +08003626 if (audio_extn_cin_attached_usecase(in))
3627 audio_extn_cin_close_input_stream(in);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303628 /*
3629 * sleep 50ms to allow sufficient time for kernel
3630 * drivers to recover incases like SSR.
3631 */
3632 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003633 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303634 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003635 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003636}
3637
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003638void lock_input_stream(struct stream_in *in)
3639{
3640 pthread_mutex_lock(&in->pre_lock);
3641 pthread_mutex_lock(&in->lock);
3642 pthread_mutex_unlock(&in->pre_lock);
3643}
3644
3645void lock_output_stream(struct stream_out *out)
3646{
3647 pthread_mutex_lock(&out->pre_lock);
3648 pthread_mutex_lock(&out->lock);
3649 pthread_mutex_unlock(&out->pre_lock);
3650}
3651
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003652/* must be called with out->lock locked */
3653static int send_offload_cmd_l(struct stream_out* out, int command)
3654{
3655 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
3656
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003657 if (!cmd) {
3658 ALOGE("failed to allocate mem for command 0x%x", command);
3659 return -ENOMEM;
3660 }
3661
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003662 ALOGVV("%s %d", __func__, command);
3663
3664 cmd->cmd = command;
3665 list_add_tail(&out->offload_cmd_list, &cmd->node);
3666 pthread_cond_signal(&out->offload_cond);
3667 return 0;
3668}
3669
Gautam Manam14c198b2020-12-24 14:08:04 +05303670/* must be called with out->lock */
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003671static void stop_compressed_output_l(struct stream_out *out)
3672{
Gautam Manam14c198b2020-12-24 14:08:04 +05303673 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003674 out->offload_state = OFFLOAD_STATE_IDLE;
Gautam Manam14c198b2020-12-24 14:08:04 +05303675 pthread_mutex_unlock(&out->latch_lock);
Weiyin Jiang906db3c2021-03-02 13:17:04 +08003676
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003677 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003678 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003679 if (out->compr != NULL) {
3680 compress_stop(out->compr);
3681 while (out->offload_thread_blocked) {
3682 pthread_cond_wait(&out->cond, &out->lock);
3683 }
3684 }
3685}
3686
Varun Balaraje49253e2017-07-06 19:48:56 +05303687bool is_interactive_usecase(audio_usecase_t uc_id)
3688{
3689 unsigned int i;
3690 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
3691 if (uc_id == interactive_usecases[i])
3692 return true;
3693 }
3694 return false;
3695}
3696
3697static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
3698{
3699 audio_usecase_t ret_uc = USECASE_INVALID;
3700 unsigned int intract_uc_index;
3701 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3702
3703 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
3704 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
3705 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
3706 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
3707 ret_uc = interactive_usecases[intract_uc_index];
3708 break;
3709 }
3710 }
3711
3712 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
3713 return ret_uc;
3714}
3715
3716static void free_interactive_usecase(struct audio_device *adev,
3717 audio_usecase_t uc_id)
3718{
3719 unsigned int interact_uc_index;
3720 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3721
3722 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
3723 if (interactive_usecases[interact_uc_index] == uc_id) {
3724 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
3725 break;
3726 }
3727 }
3728 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
3729}
3730
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003731bool is_offload_usecase(audio_usecase_t uc_id)
3732{
3733 unsigned int i;
3734 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
3735 if (uc_id == offload_usecases[i])
3736 return true;
3737 }
3738 return false;
3739}
3740
Dhananjay Kumarac341582017-02-23 23:42:25 +05303741static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003742{
vivek mehta446c3962015-09-14 10:57:35 -07003743 audio_usecase_t ret_uc = USECASE_INVALID;
3744 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003745 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003746 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05303747 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07003748 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
3749 else
3750 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003751
vivek mehta446c3962015-09-14 10:57:35 -07003752 pthread_mutex_lock(&adev->lock);
3753 if (get_usecase_from_list(adev, ret_uc) != NULL)
3754 ret_uc = USECASE_INVALID;
3755 pthread_mutex_unlock(&adev->lock);
3756
3757 return ret_uc;
3758 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003759
3760 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003761 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3762 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3763 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3764 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003765 break;
3766 }
3767 }
vivek mehta446c3962015-09-14 10:57:35 -07003768
3769 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3770 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003771}
3772
3773static void free_offload_usecase(struct audio_device *adev,
3774 audio_usecase_t uc_id)
3775{
vivek mehta446c3962015-09-14 10:57:35 -07003776 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003777 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003778
3779 if (!adev->multi_offload_enable)
3780 return;
3781
3782 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3783 if (offload_usecases[offload_uc_index] == uc_id) {
3784 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003785 break;
3786 }
3787 }
3788 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3789}
3790
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003791static void *offload_thread_loop(void *context)
3792{
3793 struct stream_out *out = (struct stream_out *) context;
3794 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003795 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003796
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003797 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08003798 set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003799 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3800
3801 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003802 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003803 out->offload_state = OFFLOAD_STATE_IDLE;
3804 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003805 for (;;) {
3806 struct offload_cmd *cmd = NULL;
3807 stream_callback_event_t event;
3808 bool send_callback = false;
3809
3810 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3811 __func__, list_empty(&out->offload_cmd_list),
3812 out->offload_state);
3813 if (list_empty(&out->offload_cmd_list)) {
3814 ALOGV("%s SLEEPING", __func__);
3815 pthread_cond_wait(&out->offload_cond, &out->lock);
3816 ALOGV("%s RUNNING", __func__);
3817 continue;
3818 }
3819
3820 item = list_head(&out->offload_cmd_list);
3821 cmd = node_to_item(item, struct offload_cmd, node);
3822 list_remove(item);
3823
3824 ALOGVV("%s STATE %d CMD %d out->compr %p",
3825 __func__, out->offload_state, cmd->cmd, out->compr);
3826
3827 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3828 free(cmd);
3829 break;
3830 }
3831
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003832 // allow OFFLOAD_CMD_ERROR reporting during standby
3833 // this is needed to handle failures during compress_open
3834 // Note however that on a pause timeout, the stream is closed
3835 // and no offload usecase will be active. Therefore this
3836 // special case is needed for compress_open failures alone
3837 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3838 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003839 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003840 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003841 pthread_cond_signal(&out->cond);
3842 continue;
3843 }
3844 out->offload_thread_blocked = true;
3845 pthread_mutex_unlock(&out->lock);
3846 send_callback = false;
3847 switch(cmd->cmd) {
3848 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003849 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003850 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003851 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003852 send_callback = true;
3853 event = STREAM_CBK_EVENT_WRITE_READY;
3854 break;
3855 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003856 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303857 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003858 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303859 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003860 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303861 if (ret < 0)
3862 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303863 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303864 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003865 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003866 else
3867 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003868 if (-ENETRESET != ret && !(-EINTR == ret &&
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05003869 (CARD_STATUS_OFFLINE == out->card_status ||
3870 POWER_POLICY_STATUS_OFFLINE == adev->out_power_policy))) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303871 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303872 pthread_mutex_lock(&out->lock);
3873 out->send_new_metadata = 1;
3874 out->send_next_track_params = true;
3875 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303876 event = STREAM_CBK_EVENT_DRAIN_READY;
3877 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3878 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303879 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003880 break;
3881 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003882 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003883 ret = compress_drain(out->compr);
3884 ALOGD("copl(%p):out of compress_drain", out);
3885 // EINTR check avoids drain interruption due to SSR
3886 if (-ENETRESET != ret && !(-EINTR == ret &&
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05003887 (CARD_STATUS_OFFLINE == out->card_status ||
3888 POWER_POLICY_STATUS_OFFLINE == adev->out_power_policy))) {
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003889 send_callback = true;
3890 event = STREAM_CBK_EVENT_DRAIN_READY;
3891 } else
3892 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003893 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303894 case OFFLOAD_CMD_ERROR:
3895 ALOGD("copl(%p): sending error callback to AF", out);
3896 send_callback = true;
3897 event = STREAM_CBK_EVENT_ERROR;
3898 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003899 default:
3900 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3901 break;
3902 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003903 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003904 out->offload_thread_blocked = false;
3905 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003906 if (send_callback && out->client_callback) {
3907 ALOGVV("%s: sending client_callback event %d", __func__, event);
3908 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003909 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003910 free(cmd);
3911 }
3912
3913 pthread_cond_signal(&out->cond);
3914 while (!list_empty(&out->offload_cmd_list)) {
3915 item = list_head(&out->offload_cmd_list);
3916 list_remove(item);
3917 free(node_to_item(item, struct offload_cmd, node));
3918 }
3919 pthread_mutex_unlock(&out->lock);
3920
3921 return NULL;
3922}
3923
3924static int create_offload_callback_thread(struct stream_out *out)
3925{
3926 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3927 list_init(&out->offload_cmd_list);
3928 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3929 offload_thread_loop, out);
3930 return 0;
3931}
3932
3933static int destroy_offload_callback_thread(struct stream_out *out)
3934{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003935 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003936 stop_compressed_output_l(out);
3937 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3938
3939 pthread_mutex_unlock(&out->lock);
3940 pthread_join(out->offload_thread, (void **) NULL);
3941 pthread_cond_destroy(&out->offload_cond);
3942
3943 return 0;
3944}
3945
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003946static int stop_output_stream(struct stream_out *out)
3947{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303948 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003949 struct audio_usecase *uc_info;
3950 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003951 bool has_voip_usecase =
3952 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003953
Eric Laurent994a6932013-07-17 11:51:42 -07003954 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003955 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003956 uc_info = get_usecase_from_list(adev, out->usecase);
3957 if (uc_info == NULL) {
3958 ALOGE("%s: Could not find the usecase (%d) in the list",
3959 __func__, out->usecase);
3960 return -EINVAL;
3961 }
3962
Zhou Songbaddf9f2020-11-20 13:57:39 +08003963 out->a2dp_muted = false;
3964
Derek Chenea197282019-01-07 17:35:01 -08003965 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3966 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003967
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003968 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303969 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003970 if (adev->visualizer_stop_output != NULL)
3971 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003972
3973 audio_extn_dts_remove_state_notifier_node(out->usecase);
3974
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003975 if (adev->offload_effects_stop_output != NULL)
3976 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07003977 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3978 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3979 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003980 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003981
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003982 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3983 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003984 voice_set_device_mute_flag(adev, false);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003985 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003986
Eric Laurent150dbfe2013-02-27 14:31:02 -08003987 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003988 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003989
3990 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003991 disable_snd_device(adev, uc_info->out_snd_device);
Zhou Songd9bd9302020-08-04 16:34:45 +08003992 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
3993 disable_snd_device(adev, SND_DEVICE_OUT_HAPTICS);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003994
Aalique Grahame22e49102018-12-18 14:23:57 -08003995 audio_extn_extspk_update(adev->extspk);
3996
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003997 if (is_offload_usecase(out->usecase)) {
3998 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3999 adev->dsp_bit_width_enforce_mode,
4000 false);
4001 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004002 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07004003 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
4004 false);
4005
4006 if (ret != 0)
4007 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
4008 /* default service interval was successfully updated,
4009 reopen USB backend with new service interval */
4010 ret = 0;
4011 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08004012
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004013 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304014 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004015 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304016 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004017 ALOGV("Disable passthrough , reset mixer to pcm");
4018 /* NO_PASSTHROUGH */
Meng Wang4c32fb42020-01-16 17:57:11 +08004019#ifdef AUDIO_GKI_ENABLED
4020 /* out->compr_config.codec->reserved[0] is for compr_passthr */
4021 out->compr_config.codec->reserved[0] = 0;
4022#else
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004023 out->compr_config.codec->compr_passthr = 0;
Meng Wang4c32fb42020-01-16 17:57:11 +08004024#endif
Mingming Yin21854652016-04-13 11:54:02 -07004025 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004026 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
4027 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07004028
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304029 /* Must be called after removing the usecase from list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004030 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL))
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05304031 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304032
Manish Dewangan21a850a2017-08-14 12:03:55 +05304033 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07004034 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
4035 if (ret < 0)
4036 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
4037 }
4038
Zhou Song642ec432020-12-23 16:11:10 +08004039 /* trigger voip input to reroute when voip output changes to hearing aid */
Aalique Grahame22e49102018-12-18 14:23:57 -08004040 if (has_voip_usecase ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004041 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08004042 struct listnode *node;
4043 struct audio_usecase *usecase;
4044 list_for_each(node, &adev->usecase_list) {
4045 usecase = node_to_item(node, struct audio_usecase, list);
Zhou Song642ec432020-12-23 16:11:10 +08004046 if (usecase->type == PCM_PLAYBACK || usecase == uc_info ||
4047 (usecase->type == PCM_CAPTURE &&
Revathi Uddarajud9f23d92020-07-27 10:55:06 +05304048 usecase->id != USECASE_AUDIO_RECORD_VOIP &&
Zhou Song642ec432020-12-23 16:11:10 +08004049 usecase->id != USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY))
Aalique Grahame22e49102018-12-18 14:23:57 -08004050 continue;
4051
4052 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
4053 __func__, usecase->id, use_case_table[usecase->id],
4054 out->usecase, use_case_table[out->usecase]);
4055 select_devices(adev, usecase->id);
4056 }
4057 }
4058
Garmond Leung5fd0b552018-04-17 11:56:12 -07004059 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07004060 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004061 return ret;
4062}
4063
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004064struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
4065 unsigned int flags, unsigned int pcm_open_retry_count,
4066 struct pcm_config *config)
4067{
4068 struct pcm* pcm = NULL;
4069
4070 while (1) {
4071 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
4072 if (pcm == NULL || !pcm_is_ready(pcm)) {
4073 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
4074 if (pcm != NULL) {
4075 pcm_close(pcm);
4076 pcm = NULL;
4077 }
Weiyin Jiang72197252019-10-09 11:49:32 +08004078 if (pcm_open_retry_count == 0)
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004079 return NULL;
4080
Weiyin Jiang72197252019-10-09 11:49:32 +08004081 pcm_open_retry_count--;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004082 usleep(PROXY_OPEN_WAIT_TIME * 1000);
4083 continue;
4084 }
4085 break;
4086 }
4087
4088 if (pcm_is_ready(pcm)) {
4089 int ret = pcm_prepare(pcm);
4090 if (ret < 0) {
4091 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
4092 pcm_close(pcm);
4093 pcm = NULL;
4094 }
4095 }
4096
4097 return pcm;
4098}
4099
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004100int start_output_stream(struct stream_out *out)
4101{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004102 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004103 struct audio_usecase *uc_info;
4104 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004105 char mixer_ctl_name[128];
4106 struct mixer_ctl *ctl = NULL;
4107 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304108 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004109 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004110
Haynes Mathew George380745d2017-10-04 15:27:45 -07004111 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004112 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
4113 ret = -EINVAL;
4114 goto error_config;
4115 }
4116
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004117 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304118 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004119 get_device_types(&out->device_list), is_haptic_usecase);
4120
4121 bool is_speaker_active = compare_device_type(&out->device_list,
4122 AUDIO_DEVICE_OUT_SPEAKER);
4123 bool is_speaker_safe_active = compare_device_type(&out->device_list,
4124 AUDIO_DEVICE_OUT_SPEAKER_SAFE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304125
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304126 if (CARD_STATUS_OFFLINE == out->card_status ||
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05004127 CARD_STATUS_OFFLINE == adev->card_status ||
4128 POWER_POLICY_STATUS_OFFLINE == adev->out_power_policy) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304129 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05304130 ret = -EIO;
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004131 goto error_fatal;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304132 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05304133
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004134 //Update incall music usecase to reflect correct voice session
4135 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
4136 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
4137 if (ret != 0) {
4138 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
4139 __func__, ret);
4140 goto error_config;
4141 }
4142 }
4143
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004144 if (is_a2dp_out_device_type(&out->device_list)) {
Florian Pfister1a84f312018-07-19 14:38:18 +02004145 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004146 if (is_speaker_active || is_speaker_safe_active) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304147 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304148 } else {
Zhou Songd01e7a22020-09-23 22:49:01 +08004149 if (!is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304150 ALOGE("%s: A2DP profile is not ready, return error", __func__);
4151 ret = -EAGAIN;
4152 goto error_config;
4153 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304154 }
4155 }
4156 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004157 if (is_sco_out_device_type(&out->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304158 if (!adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004159 if (is_speaker_active) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304160 //combo usecase just by pass a2dp
4161 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004162 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304163 } else {
4164 ALOGE("%s: SCO profile is not ready, return error", __func__);
4165 ret = -EAGAIN;
4166 goto error_config;
4167 }
4168 }
4169 }
4170
Eric Laurentb23d5282013-05-14 15:27:20 -07004171 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004172 if (out->pcm_device_id < 0) {
4173 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
4174 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004175 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004176 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004177 }
4178
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004179 if (is_haptic_usecase) {
Meng Wang51d8c2a2020-04-27 15:23:21 +08004180 adev->haptic_pcm_device_id = platform_get_pcm_device_id(
4181 USECASE_AUDIO_PLAYBACK_HAPTICS, PCM_PLAYBACK);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004182 if (adev->haptic_pcm_device_id < 0) {
4183 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
4184 __func__, adev->haptic_pcm_device_id, out->usecase);
4185 ret = -EINVAL;
4186 goto error_config;
4187 }
4188 }
4189
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004190 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004191
4192 if (!uc_info) {
4193 ret = -ENOMEM;
4194 goto error_config;
4195 }
4196
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004197 uc_info->id = out->usecase;
4198 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004199 uc_info->stream.out = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004200 list_init(&uc_info->device_list);
4201 assign_devices(&uc_info->device_list, &out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004202 uc_info->in_snd_device = SND_DEVICE_NONE;
4203 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07004204
4205 /* This must be called before adding this usecase to the list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004206 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07004207 audio_extn_usb_check_and_set_svc_int(uc_info, true);
4208 /* USB backend is not reopened immediately.
4209 This is eventually done as part of select_devices */
4210 }
4211
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004212 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004213
Wei Wangf7ca6c92017-11-21 14:51:20 -08004214 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304215 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4216 adev->perf_lock_opts,
4217 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304218
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004219 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05304220 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304221 if (audio_extn_passthru_is_enabled() &&
4222 audio_extn_passthru_is_passthrough_stream(out)) {
4223 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304224 }
4225 }
4226
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004227 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02004228 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304229 if (!a2dp_combo) {
4230 check_a2dp_restore_l(adev, out, false);
4231 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004232 struct listnode dev;
4233 list_init(&dev);
4234 assign_devices(&dev, &out->device_list);
4235 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4236 reassign_device_list(&out->device_list,
4237 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aalique Grahame22e49102018-12-18 14:23:57 -08004238 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004239 reassign_device_list(&out->device_list,
4240 AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304241 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004242 assign_devices(&out->device_list, &dev);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304243 }
4244 } else {
Revathi Uddarajub26e3932020-06-10 14:51:02 +05304245 select_devices(adev, out->usecase);
4246 if (is_a2dp_out_device_type(&out->device_list) &&
4247 !adev->a2dp_started) {
4248 if (is_speaker_active || is_speaker_safe_active) {
4249 struct listnode dev;
4250 list_init(&dev);
4251 assign_devices(&dev, &out->device_list);
4252 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4253 reassign_device_list(&out->device_list,
4254 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
4255 else
4256 reassign_device_list(&out->device_list,
4257 AUDIO_DEVICE_OUT_SPEAKER, "");
4258 select_devices(adev, out->usecase);
4259 assign_devices(&out->device_list, &dev);
4260 } else {
4261 ret = -EINVAL;
4262 goto error_open;
4263 }
4264 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304265 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004266
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004267 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
4268 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07004269 voice_set_device_mute_flag(adev, true);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004270 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07004271
Derek Chenea197282019-01-07 17:35:01 -08004272 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
4273 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08004274
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004275 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
4276 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07004277
4278 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07004279 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07004280 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4281 ALOGE("%s: pcm stream not ready", __func__);
4282 goto error_open;
4283 }
4284 ret = pcm_start(out->pcm);
4285 if (ret < 0) {
4286 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
4287 goto error_open;
4288 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07004289 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07004290 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004291 unsigned int flags = PCM_OUT;
4292 unsigned int pcm_open_retry_count = 0;
4293 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
4294 flags |= PCM_MMAP | PCM_NOIRQ;
4295 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004296 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08004297 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004298 } else
4299 flags |= PCM_MONOTONIC;
4300
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004301 if ((adev->vr_audio_mode_enabled) &&
4302 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
4303 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4304 "PCM_Dev %d Topology", out->pcm_device_id);
4305 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4306 if (!ctl) {
4307 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
4308 __func__, mixer_ctl_name);
4309 } else {
4310 //if success use ULLPP
4311 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
4312 __func__, mixer_ctl_name, out->pcm_device_id);
4313 //There is a still a possibility that some sessions
4314 // that request for FAST|RAW when 3D audio is active
4315 //can go through ULLPP. Ideally we expects apps to
4316 //listen to audio focus and stop concurrent playback
4317 //Also, we will look for mode flag (voice_in_communication)
4318 //before enabling the realtime flag.
4319 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
4320 }
4321 }
4322
Vatsal Bucha3f39f222021-06-29 16:16:55 +05304323 platform_set_stream_channel_map(adev->platform, out->channel_mask,
4324 out->pcm_device_id, -1, &out->channel_map_param.channel_map[0]);
Surendar Karka91fa3682018-07-02 18:12:12 +05304325
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004326 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
4327 flags, pcm_open_retry_count,
4328 &(out->config));
4329 if (out->pcm == NULL) {
4330 ret = -EIO;
4331 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004332 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004333
4334 if (is_haptic_usecase) {
4335 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
4336 adev->haptic_pcm_device_id,
4337 flags, pcm_open_retry_count,
4338 &(adev->haptics_config));
4339 // failure to open haptics pcm shouldnt stop audio,
4340 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07004341
4342 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
4343 ALOGD("%s: enable haptic audio synchronization", __func__);
4344 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
4345 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004346 }
4347
Zhou Song2b8f28f2017-09-11 10:51:38 +08004348 // apply volume for voip playback after path is set up
4349 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
4350 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05304351 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
4352 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304353 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
4354 out->apply_volume = false;
Derek Chenf13dd492018-11-13 14:53:51 -08004355 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
4356 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Krishna Kishor Jha10ad39f2022-02-21 17:02:47 +05304357#ifdef SOFT_VOLUME
4358 out_set_soft_volume_params(&out->stream);
4359#endif
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304360 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004361 } else {
Zhou Song79929fe2020-01-20 17:57:43 +08004362 /*
4363 * set custom channel map if:
4364 * 1. neither mono nor stereo clips i.e. channels > 2 OR
4365 * 2. custom channel map has been set by client
4366 * else default channel map of FC/FR/FL can always be set to DSP
4367 */
4368 if (popcount(out->channel_mask) > 2 || out->channel_map_param.channel_map[0])
4369 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Weiyin Jiang810a80d2021-01-18 16:04:31 +08004370 out->pcm_device_id, -1, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08004371 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
4372 adev->dsp_bit_width_enforce_mode,
4373 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004374 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07004375 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004376 out->compr = compress_open(adev->snd_card,
4377 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004378 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004379 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05304380 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05304381 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
4382 adev->card_status = CARD_STATUS_OFFLINE;
4383 out->card_status = CARD_STATUS_OFFLINE;
4384 ret = -EIO;
4385 goto error_open;
4386 }
4387
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004388 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004389 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004390 compress_close(out->compr);
4391 out->compr = NULL;
4392 ret = -EIO;
4393 goto error_open;
4394 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304395 /* compress_open sends params of the track, so reset the flag here */
4396 out->is_compr_metadata_avail = false;
4397
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004398 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004399 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07004400
Fred Oh3f43e742015-03-04 18:42:34 -08004401 /* Since small bufs uses blocking writes, a write will be blocked
4402 for the default max poll time (20s) in the event of an SSR.
4403 Reduce the poll time to observe and deal with SSR faster.
4404 */
Ashish Jain5106d362016-05-11 19:23:33 +05304405 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08004406 compress_set_max_poll_wait(out->compr, 1000);
4407 }
4408
Manish Dewangan69426c82017-01-30 17:35:36 +05304409 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05304410 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05304411
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004412 audio_extn_dts_create_state_notifier_node(out->usecase);
4413 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4414 popcount(out->channel_mask),
4415 out->playback_started);
4416
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004417#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304418 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004419 audio_extn_dolby_send_ddp_endp_params(adev);
4420#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05304421 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
4422 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004423 if (adev->visualizer_start_output != NULL)
4424 adev->visualizer_start_output(out->handle, out->pcm_device_id);
4425 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05304426 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004427 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004428 }
Derek Chenf13dd492018-11-13 14:53:51 -08004429
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004430 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf13dd492018-11-13 14:53:51 -08004431 /* Update cached volume from media to offload/direct stream */
4432 struct listnode *node = NULL;
4433 list_for_each(node, &adev->active_outputs_list) {
4434 streams_output_ctxt_t *out_ctxt = node_to_item(node,
4435 streams_output_ctxt_t,
4436 list);
4437 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
4438 out->volume_l = out_ctxt->output->volume_l;
4439 out->volume_r = out_ctxt->output->volume_r;
4440 }
4441 }
4442 out_set_compr_volume(&out->stream,
4443 out->volume_l, out->volume_r);
4444 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004445 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004446
4447 if (ret == 0) {
4448 register_out_stream(out);
4449 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07004450 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4451 ALOGE("%s: pcm stream not ready", __func__);
4452 goto error_open;
4453 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004454 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004455 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004456 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004457 if (ret < 0)
4458 goto error_open;
4459 }
4460 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004461 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304462 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Jaideep Sharma0fa53812020-09-17 09:00:11 +05304463 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004464
vivek mehtad15d2bf2019-05-17 13:35:10 -07004465 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
4466 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4467 audio_low_latency_hint_start();
4468 }
4469
Manish Dewangan21a850a2017-08-14 12:03:55 +05304470 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07004471 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07004472 if (ret < 0)
4473 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
4474 }
4475
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004476 // consider a scenario where on pause lower layers are tear down.
4477 // so on resume, swap mixer control need to be sent only when
4478 // backend is active, hence rather than sending from enable device
4479 // sending it from start of streamtream
4480
4481 platform_set_swap_channels(adev, true);
4482
Haynes Mathew George380745d2017-10-04 15:27:45 -07004483 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304484 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004485 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004486error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004487 if (adev->haptic_pcm) {
4488 pcm_close(adev->haptic_pcm);
4489 adev->haptic_pcm = NULL;
4490 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004491 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304492 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004493 stop_output_stream(out);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004494error_fatal:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05304495 /*
4496 * sleep 50ms to allow sufficient time for kernel
4497 * drivers to recover incases like SSR.
4498 */
4499 usleep(50000);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004500error_config:
Haynes Mathew George380745d2017-10-04 15:27:45 -07004501 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304502 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004503 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004504}
4505
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004506static int check_input_parameters(uint32_t sample_rate,
4507 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08004508 int channel_count,
4509 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004510{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004511 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004512
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304513 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
4514 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
4515 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07004516 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02004517 !audio_extn_compr_cap_format_supported(format) &&
4518 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004519 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004520
Aalique Grahame22e49102018-12-18 14:23:57 -08004521 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
4522 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
4523 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
4524 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
4525 return -EINVAL;
4526 }
4527
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004528 switch (channel_count) {
4529 case 1:
4530 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304531 case 3:
4532 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004533 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07004534 case 8:
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05304535 case 10:
4536 case 12:
4537 case 14:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004538 break;
4539 default:
4540 ret = -EINVAL;
4541 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004542
4543 switch (sample_rate) {
4544 case 8000:
4545 case 11025:
4546 case 12000:
4547 case 16000:
4548 case 22050:
4549 case 24000:
4550 case 32000:
4551 case 44100:
4552 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004553 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304554 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004555 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304556 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004557 break;
4558 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004559 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004560 }
4561
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004562 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004563}
4564
Naresh Tanniru04f71882018-06-26 17:46:22 +05304565
4566/** Add a value in a list if not already present.
4567 * @return true if value was successfully inserted or already present,
4568 * false if the list is full and does not contain the value.
4569 */
4570static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
4571 for (size_t i = 0; i < list_length; i++) {
4572 if (list[i] == value) return true; // value is already present
4573 if (list[i] == 0) { // no values in this slot
4574 list[i] = value;
4575 return true; // value inserted
4576 }
4577 }
4578 return false; // could not insert value
4579}
4580
4581/** Add channel_mask in supported_channel_masks if not already present.
4582 * @return true if channel_mask was successfully inserted or already present,
4583 * false if supported_channel_masks is full and does not contain channel_mask.
4584 */
4585static void register_channel_mask(audio_channel_mask_t channel_mask,
4586 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
4587 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
4588 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
4589}
4590
4591/** Add format in supported_formats if not already present.
4592 * @return true if format was successfully inserted or already present,
4593 * false if supported_formats is full and does not contain format.
4594 */
4595static void register_format(audio_format_t format,
4596 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
4597 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
4598 "%s: stream can not declare supporting its format %x", __func__, format);
4599}
4600/** Add sample_rate in supported_sample_rates if not already present.
4601 * @return true if sample_rate was successfully inserted or already present,
4602 * false if supported_sample_rates is full and does not contain sample_rate.
4603 */
4604static void register_sample_rate(uint32_t sample_rate,
4605 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
4606 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
4607 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
4608}
4609
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004610static inline uint32_t lcm(uint32_t num1, uint32_t num2)
4611{
4612 uint32_t high = num1, low = num2, temp = 0;
4613
4614 if (!num1 || !num2)
4615 return 0;
4616
4617 if (num1 < num2) {
4618 high = num2;
4619 low = num1;
4620 }
4621
4622 while (low != 0) {
4623 temp = low;
4624 low = high % low;
4625 high = temp;
4626 }
4627 return (num1 * num2)/high;
4628}
4629
4630static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
4631{
4632 uint32_t remainder = 0;
4633
4634 if (!multiplier)
4635 return num;
4636
4637 remainder = num % multiplier;
4638 if (remainder)
4639 num += (multiplier - remainder);
4640
4641 return num;
4642}
4643
Aalique Grahame22e49102018-12-18 14:23:57 -08004644static size_t get_stream_buffer_size(size_t duration_ms,
4645 uint32_t sample_rate,
4646 audio_format_t format,
4647 int channel_count,
4648 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004649{
4650 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004651 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004652
Aalique Grahame22e49102018-12-18 14:23:57 -08004653 size = (sample_rate * duration_ms) / 1000;
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +05304654 if (is_low_latency){
4655 switch(sample_rate) {
4656 case 48000:
4657 size = 240;
4658 break;
4659 case 32000:
4660 size = 160;
4661 break;
4662 case 24000:
4663 size = 120;
4664 break;
4665 case 16000:
4666 size = 80;
4667 break;
4668 case 8000:
4669 size = 40;
4670 break;
4671 default:
4672 size = 240;
4673 }
4674 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304675
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004676 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08004677 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004678
Ralf Herzbd08d632018-09-28 15:50:49 +02004679 /* make sure the size is multiple of 32 bytes and additionally multiple of
4680 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004681 * At 48 kHz mono 16-bit PCM:
4682 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
4683 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004684 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004685 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004686 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07004687
4688 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004689}
4690
Aalique Grahame22e49102018-12-18 14:23:57 -08004691static size_t get_input_buffer_size(uint32_t sample_rate,
4692 audio_format_t format,
4693 int channel_count,
4694 bool is_low_latency)
4695{
4696 /* Don't know if USB HIFI in this context so use true to be conservative */
4697 if (check_input_parameters(sample_rate, format, channel_count,
4698 true /*is_usb_hifi */) != 0)
4699 return 0;
4700
4701 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4702 sample_rate,
4703 format,
4704 channel_count,
4705 is_low_latency);
4706}
4707
Derek Chenf6318be2017-06-12 17:16:24 -04004708size_t get_output_period_size(uint32_t sample_rate,
4709 audio_format_t format,
4710 int channel_count,
4711 int duration /*in millisecs*/)
Ashish Jain058165c2016-09-28 23:18:48 +05304712{
4713 size_t size = 0;
4714 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
4715
4716 if ((duration == 0) || (sample_rate == 0) ||
4717 (bytes_per_sample == 0) || (channel_count == 0)) {
4718 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
4719 bytes_per_sample, channel_count);
4720 return -EINVAL;
4721 }
4722
4723 size = (sample_rate *
4724 duration *
4725 bytes_per_sample *
4726 channel_count) / 1000;
4727 /*
4728 * To have same PCM samples for all channels, the buffer size requires to
4729 * be multiple of (number of channels * bytes per sample)
4730 * For writes to succeed, the buffer must be written at address which is multiple of 32
4731 */
4732 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
4733
4734 return (size/(channel_count * bytes_per_sample));
4735}
4736
Zhou Song48453a02018-01-10 17:50:59 +08004737static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05304738{
4739 uint64_t actual_frames_rendered = 0;
Weiyin Jiang4813da12020-05-28 00:37:28 +08004740 uint64_t written_frames = 0;
4741 uint64_t kernel_frames = 0;
4742 uint64_t dsp_frames = 0;
4743 uint64_t signed_frames = 0;
4744 size_t kernel_buffer_size = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304745
4746 /* This adjustment accounts for buffering after app processor.
4747 * It is based on estimated DSP latency per use case, rather than exact.
4748 */
George Gao9ba8a142020-07-23 14:30:03 -07004749 dsp_frames = platform_render_latency(out) *
Weiyin Jiang4813da12020-05-28 00:37:28 +08004750 out->sample_rate / 1000000LL;
Ashish Jain5106d362016-05-11 19:23:33 +05304751
Zhou Song48453a02018-01-10 17:50:59 +08004752 pthread_mutex_lock(&out->position_query_lock);
Weiyin Jiang4813da12020-05-28 00:37:28 +08004753 written_frames = out->written /
4754 (audio_bytes_per_sample(out->hal_ip_format) * popcount(out->channel_mask));
4755
Ashish Jain5106d362016-05-11 19:23:33 +05304756 /* not querying actual state of buffering in kernel as it would involve an ioctl call
4757 * which then needs protection, this causes delay in TS query for pcm_offload usecase
4758 * hence only estimate.
4759 */
Weiyin Jiang4813da12020-05-28 00:37:28 +08004760 kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
4761 kernel_frames = kernel_buffer_size /
4762 (audio_bytes_per_sample(out->hal_op_format) * popcount(out->channel_mask));
Ashish Jain5106d362016-05-11 19:23:33 +05304763
Weiyin Jiang4813da12020-05-28 00:37:28 +08004764 if (written_frames >= (kernel_frames + dsp_frames))
4765 signed_frames = written_frames - kernel_frames - dsp_frames;
Ashish Jain5106d362016-05-11 19:23:33 +05304766
Zhou Song48453a02018-01-10 17:50:59 +08004767 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05304768 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08004769 if (timestamp != NULL )
4770 *timestamp = out->writeAt;
4771 } else if (timestamp != NULL) {
4772 clock_gettime(CLOCK_MONOTONIC, timestamp);
4773 }
4774 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304775
Weiyin Jiang4813da12020-05-28 00:37:28 +08004776 ALOGVV("%s signed frames %lld written frames %lld kernel frames %lld dsp frames %lld",
4777 __func__, signed_frames, written_frames, kernel_frames, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05304778
4779 return actual_frames_rendered;
4780}
4781
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004782static uint32_t out_get_sample_rate(const struct audio_stream *stream)
4783{
4784 struct stream_out *out = (struct stream_out *)stream;
4785
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004786 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004787}
4788
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004789static int out_set_sample_rate(struct audio_stream *stream __unused,
4790 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004791{
4792 return -ENOSYS;
4793}
4794
4795static size_t out_get_buffer_size(const struct audio_stream *stream)
4796{
4797 struct stream_out *out = (struct stream_out *)stream;
4798
Varun Balaraje49253e2017-07-06 19:48:56 +05304799 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05304800 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05304801 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304802 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4803 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
4804 else
4805 return out->compr_config.fragment_size;
4806 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004807 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304808 else if (is_offload_usecase(out->usecase) &&
4809 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304810 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004811
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004812 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004813 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004814}
4815
4816static uint32_t out_get_channels(const struct audio_stream *stream)
4817{
4818 struct stream_out *out = (struct stream_out *)stream;
4819
4820 return out->channel_mask;
4821}
4822
4823static audio_format_t out_get_format(const struct audio_stream *stream)
4824{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004825 struct stream_out *out = (struct stream_out *)stream;
4826
4827 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004828}
4829
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004830static int out_set_format(struct audio_stream *stream __unused,
4831 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004832{
4833 return -ENOSYS;
4834}
4835
4836static int out_standby(struct audio_stream *stream)
4837{
4838 struct stream_out *out = (struct stream_out *)stream;
4839 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07004840 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004841
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304842 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4843 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004844
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004845 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004846 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004847 if (adev->adm_deregister_stream)
4848 adev->adm_deregister_stream(adev->adm_data, out->handle);
4849
Weiyin Jiang280ea742020-09-08 20:28:22 +08004850 if (is_offload_usecase(out->usecase)) {
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004851 stop_compressed_output_l(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08004852 }
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004853
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004854 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004855 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004856 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4857 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304858 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08004859 pthread_mutex_unlock(&adev->lock);
4860 pthread_mutex_unlock(&out->lock);
4861 ALOGD("VOIP output entered standby");
4862 return 0;
4863 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004864 if (out->pcm) {
4865 pcm_close(out->pcm);
4866 out->pcm = NULL;
4867 }
Meng Wanga09da002020-04-20 12:56:04 +08004868 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4869 if (adev->haptic_pcm) {
4870 pcm_close(adev->haptic_pcm);
4871 adev->haptic_pcm = NULL;
4872 }
4873
4874 if (adev->haptic_buffer != NULL) {
4875 free(adev->haptic_buffer);
4876 adev->haptic_buffer = NULL;
4877 adev->haptic_buffer_size = 0;
4878 }
4879 adev->haptic_pcm_device_id = 0;
4880 }
4881
Haynes Mathew George16081042017-05-31 17:16:49 -07004882 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4883 do_stop = out->playback_started;
4884 out->playback_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07004885
4886 if (out->mmap_shared_memory_fd >= 0) {
4887 ALOGV("%s: closing mmap_shared_memory_fd = %d",
4888 __func__, out->mmap_shared_memory_fd);
4889 close(out->mmap_shared_memory_fd);
4890 out->mmap_shared_memory_fd = -1;
4891 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004892 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004893 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004894 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304895 out->send_next_track_params = false;
4896 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004897 out->gapless_mdata.encoder_delay = 0;
4898 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004899 if (out->compr != NULL) {
4900 compress_close(out->compr);
4901 out->compr = NULL;
4902 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004903 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004904 if (do_stop) {
4905 stop_output_stream(out);
4906 }
Lakshman Chaluvaraju06677b42019-06-24 10:04:52 +05304907 // if fm is active route on selected device in UI
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004908 audio_extn_fm_route_on_selected_device(adev, &out->device_list);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004909 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004910 }
4911 pthread_mutex_unlock(&out->lock);
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07004912 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004913 return 0;
4914}
4915
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304916static int out_on_error(struct audio_stream *stream)
4917{
4918 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004919 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304920
4921 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004922 // always send CMD_ERROR for offload streams, this
4923 // is needed e.g. when SSR happens within compress_open
4924 // since the stream is active, offload_callback_thread is also active.
4925 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
4926 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004927 }
4928 pthread_mutex_unlock(&out->lock);
4929
4930 status = out_standby(&out->stream.common);
4931
4932 lock_output_stream(out);
4933 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004934 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304935 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05304936
4937 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
4938 ALOGD("Setting previous card status if offline");
4939 out->prev_card_status_offline = true;
4940 }
4941
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304942 pthread_mutex_unlock(&out->lock);
4943
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004944 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304945}
4946
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304947/*
Weiyin Jiang280ea742020-09-08 20:28:22 +08004948 * standby implementation without locks, assumes that the callee already
4949 * has taken adev and out lock.
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304950 */
4951int out_standby_l(struct audio_stream *stream)
4952{
4953 struct stream_out *out = (struct stream_out *)stream;
4954 struct audio_device *adev = out->dev;
4955
4956 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4957 stream, out->usecase, use_case_table[out->usecase]);
4958
4959 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07004960 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304961 if (adev->adm_deregister_stream)
4962 adev->adm_deregister_stream(adev->adm_data, out->handle);
4963
Weiyin Jiang280ea742020-09-08 20:28:22 +08004964 if (is_offload_usecase(out->usecase)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304965 stop_compressed_output_l(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08004966 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304967
4968 out->standby = true;
4969 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4970 voice_extn_compress_voip_close_output_stream(stream);
4971 out->started = 0;
4972 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07004973 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304974 return 0;
4975 } else if (!is_offload_usecase(out->usecase)) {
4976 if (out->pcm) {
4977 pcm_close(out->pcm);
4978 out->pcm = NULL;
4979 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004980 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4981 if (adev->haptic_pcm) {
4982 pcm_close(adev->haptic_pcm);
4983 adev->haptic_pcm = NULL;
4984 }
4985
4986 if (adev->haptic_buffer != NULL) {
4987 free(adev->haptic_buffer);
4988 adev->haptic_buffer = NULL;
4989 adev->haptic_buffer_size = 0;
4990 }
4991 adev->haptic_pcm_device_id = 0;
4992 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304993 } else {
4994 ALOGD("copl(%p):standby", out);
4995 out->send_next_track_params = false;
4996 out->is_compr_metadata_avail = false;
4997 out->gapless_mdata.encoder_delay = 0;
4998 out->gapless_mdata.encoder_padding = 0;
4999 if (out->compr != NULL) {
5000 compress_close(out->compr);
5001 out->compr = NULL;
5002 }
5003 }
5004 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005005 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305006 }
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07005007 ALOGV("%s: exit", __func__);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305008 return 0;
5009}
5010
Aalique Grahame22e49102018-12-18 14:23:57 -08005011static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005012{
Aalique Grahame22e49102018-12-18 14:23:57 -08005013 struct stream_out *out = (struct stream_out *)stream;
5014
5015 // We try to get the lock for consistency,
5016 // but it isn't necessary for these variables.
5017 // If we're not in standby, we may be blocked on a write.
5018 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
5019 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
5020 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
Dechen Chai22768452021-07-30 09:29:16 +05305021#ifndef LINUX_ENABLED
Andy Hunga1f48fa2019-07-01 18:14:53 -07005022 char buffer[256]; // for statistics formatting
5023 if (!is_offload_usecase(out->usecase)) {
5024 simple_stats_to_string(&out->fifo_underruns, buffer, sizeof(buffer));
5025 dprintf(fd, " Fifo frame underruns: %s\n", buffer);
5026 }
5027
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005028 if (out->start_latency_ms.n > 0) {
5029 simple_stats_to_string(&out->start_latency_ms, buffer, sizeof(buffer));
5030 dprintf(fd, " Start latency ms: %s\n", buffer);
5031 }
Dechen Chai22768452021-07-30 09:29:16 +05305032#endif
Aalique Grahame22e49102018-12-18 14:23:57 -08005033 if (locked) {
5034 pthread_mutex_unlock(&out->lock);
5035 }
5036
Dechen Chai22768452021-07-30 09:29:16 +05305037#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -08005038 // dump error info
5039 (void)error_log_dump(
5040 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Dechen Chai22768452021-07-30 09:29:16 +05305041#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005042 return 0;
5043}
5044
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005045static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
5046{
5047 int ret = 0;
5048 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08005049
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005050 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08005051 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005052 return -EINVAL;
5053 }
5054
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05305055 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08005056
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005057 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
5058 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05305059 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005060 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005061 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
5062 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05305063 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005064 }
5065
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005066 ALOGV("%s new encoder delay %u and padding %u", __func__,
5067 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
5068
5069 return 0;
5070}
5071
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005072static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
5073{
5074 return out == adev->primary_output || out == adev->voice_tx_output;
5075}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005076
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305077// note: this call is safe only if the stream_cb is
5078// removed first in close_output_stream (as is done now).
5079static void out_snd_mon_cb(void * stream, struct str_parms * parms)
5080{
5081 if (!stream || !parms)
5082 return;
5083
5084 struct stream_out *out = (struct stream_out *)stream;
5085 struct audio_device *adev = out->dev;
5086
5087 card_status_t status;
5088 int card;
5089 if (parse_snd_card_status(parms, &card, &status) < 0)
5090 return;
5091
5092 pthread_mutex_lock(&adev->lock);
5093 bool valid_cb = (card == adev->snd_card);
5094 pthread_mutex_unlock(&adev->lock);
5095
5096 if (!valid_cb)
5097 return;
5098
5099 lock_output_stream(out);
5100 if (out->card_status != status)
5101 out->card_status = status;
5102 pthread_mutex_unlock(&out->lock);
5103
5104 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
5105 use_case_table[out->usecase],
5106 status == CARD_STATUS_OFFLINE ? "offline" : "online");
5107
Aditya Bavanari59ebed42019-02-05 17:44:57 +05305108 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305109 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05305110 if (voice_is_call_state_active(adev) &&
5111 out == adev->primary_output) {
5112 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
5113 pthread_mutex_lock(&adev->lock);
5114 voice_stop_call(adev);
5115 adev->mode = AUDIO_MODE_NORMAL;
5116 pthread_mutex_unlock(&adev->lock);
5117 }
5118 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305119 return;
5120}
5121
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005122int route_output_stream(struct stream_out *out,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005123 struct listnode *devices)
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005124{
5125 struct audio_device *adev = out->dev;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005126 int ret = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005127 struct listnode new_devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005128 bool bypass_a2dp = false;
5129 bool reconfig = false;
5130 unsigned long service_interval = 0;
5131
5132 ALOGD("%s: enter: usecase(%d: %s) devices %x",
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005133 __func__, out->usecase, use_case_table[out->usecase], get_device_types(devices));
5134
5135 list_init(&new_devices);
5136 assign_devices(&new_devices, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005137
5138 lock_output_stream(out);
5139 pthread_mutex_lock(&adev->lock);
5140
5141 /*
5142 * When HDMI cable is unplugged the music playback is paused and
5143 * the policy manager sends routing=0. But the audioflinger continues
5144 * to write data until standby time (3sec). As the HDMI core is
5145 * turned off, the write gets blocked.
5146 * Avoid this by routing audio to speaker until standby.
5147 */
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08005148 if (is_single_device_type_equal(&out->device_list,
5149 AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005150 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005151 !audio_extn_passthru_is_passthrough_stream(out) &&
5152 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005153 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005154 }
5155 /*
5156 * When A2DP is disconnected the
5157 * music playback is paused and the policy manager sends routing=0
5158 * But the audioflinger continues to write data until standby time
5159 * (3sec). As BT is turned off, the write gets blocked.
5160 * Avoid this by routing audio to speaker until standby.
5161 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005162 if (is_a2dp_out_device_type(&out->device_list) &&
5163 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005164 !audio_extn_a2dp_source_is_ready() &&
5165 !adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005166 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005167 }
5168 /*
Weiyin Jiangabedea32020-12-09 12:49:19 +08005169 * When USB headset is disconnected the music playback paused
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005170 * and the policy manager send routing=0. But if the USB is connected
5171 * back before the standby time, AFE is not closed and opened
5172 * when USB is connected back. So routing to speker will guarantee
5173 * AFE reconfiguration and AFE will be opend once USB is connected again
5174 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005175 if (is_usb_out_device_type(&out->device_list) &&
5176 list_empty(&new_devices) &&
5177 !audio_extn_usb_connected(NULL)) {
Sujin Panicker84d953a2020-11-16 17:39:54 +05305178 if (adev->mode == AUDIO_MODE_IN_CALL || adev->mode == AUDIO_MODE_IN_COMMUNICATION)
5179 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_EARPIECE, "");
5180 else
5181 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005182 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005183 /* To avoid a2dp to sco overlapping / BT device improper state
5184 * check with BT lib about a2dp streaming support before routing
5185 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005186 if (is_a2dp_out_device_type(&new_devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005187 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005188 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER) ||
5189 compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005190 //combo usecase just by pass a2dp
5191 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
5192 bypass_a2dp = true;
5193 } else {
5194 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
5195 /* update device to a2dp and don't route as BT returned error
5196 * However it is still possible a2dp routing called because
5197 * of current active device disconnection (like wired headset)
5198 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005199 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005200 pthread_mutex_unlock(&adev->lock);
5201 pthread_mutex_unlock(&out->lock);
5202 goto error;
5203 }
5204 }
5205 }
5206
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005207 // Workaround: If routing to an non existing usb device, fail gracefully
5208 // The routing request will otherwise block during 10 second
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005209 if (is_usb_out_device_type(&new_devices)) {
5210 struct str_parms *parms =
5211 str_parms_create_str(get_usb_device_address(&new_devices));
5212 if (!parms)
5213 goto error;
Weiyin Jiangabedea32020-12-09 12:49:19 +08005214 if (!audio_extn_usb_connected(NULL)) {
5215 ALOGW("%s: ignoring rerouting to non existing USB card", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005216 pthread_mutex_unlock(&adev->lock);
5217 pthread_mutex_unlock(&out->lock);
5218 str_parms_destroy(parms);
5219 ret = -ENOSYS;
5220 goto error;
5221 }
5222 str_parms_destroy(parms);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005223 }
5224
Weiyin Jiang80c8f9a2020-01-10 20:42:08 +08005225 // Workaround: If routing to an non existing hdmi device, fail gracefully
5226 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
5227 (platform_get_edid_info_v2(adev->platform,
5228 out->extconn.cs.controller,
5229 out->extconn.cs.stream) != 0)) {
5230 ALOGW("out_set_parameters() ignoring rerouting to non existing HDMI/DP");
5231 pthread_mutex_unlock(&adev->lock);
5232 pthread_mutex_unlock(&out->lock);
5233 ret = -ENOSYS;
5234 goto error;
5235 }
5236
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005237 /*
5238 * select_devices() call below switches all the usecases on the same
5239 * backend to the new device. Refer to check_usecases_codec_backend() in
5240 * the select_devices(). But how do we undo this?
5241 *
5242 * For example, music playback is active on headset (deep-buffer usecase)
5243 * and if we go to ringtones and select a ringtone, low-latency usecase
5244 * will be started on headset+speaker. As we can't enable headset+speaker
5245 * and headset devices at the same time, select_devices() switches the music
5246 * playback to headset+speaker while starting low-lateny usecase for ringtone.
5247 * So when the ringtone playback is completed, how do we undo the same?
5248 *
5249 * We are relying on the out_set_parameters() call on deep-buffer output,
5250 * once the ringtone playback is ended.
5251 * NOTE: We should not check if the current devices are same as new devices.
5252 * Because select_devices() must be called to switch back the music
5253 * playback to headset.
5254 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005255 if (!list_empty(&new_devices)) {
5256 bool same_dev = compare_devices(&out->device_list, &new_devices);
5257 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005258
5259 if (output_drives_call(adev, out)) {
5260 if (!voice_is_call_state_active(adev)) {
5261 if (adev->mode == AUDIO_MODE_IN_CALL) {
5262 adev->current_call_output = out;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005263 ret = voice_start_call(adev);
5264 }
5265 } else {
Kunlei Zhang253ad102020-10-14 16:21:28 +08005266 platform_is_volume_boost_supported_device(adev->platform, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005267 adev->current_call_output = out;
5268 voice_update_devices_for_all_voice_usecases(adev);
5269 }
5270 }
5271
Mingshu Pang971ff702020-09-09 15:28:22 +08005272 if (is_usb_out_device_type(&out->device_list)) {
5273 service_interval = audio_extn_usb_find_service_interval(false, true /*playback*/);
5274 audio_extn_usb_set_service_interval(true /*playback*/,
5275 service_interval,
5276 &reconfig);
5277 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
5278 }
5279
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005280 if (!out->standby) {
5281 if (!same_dev) {
5282 ALOGV("update routing change");
5283 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
5284 adev->perf_lock_opts,
5285 adev->perf_lock_opts_size);
5286 if (adev->adm_on_routing_change)
5287 adev->adm_on_routing_change(adev->adm_data,
5288 out->handle);
5289 }
5290 if (!bypass_a2dp) {
5291 select_devices(adev, out->usecase);
5292 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005293 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
5294 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005295 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005296 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005297 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005298 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005299 }
5300
5301 if (!same_dev) {
5302 // on device switch force swap, lower functions will make sure
5303 // to check if swap is allowed or not.
5304 platform_set_swap_channels(adev, true);
5305 audio_extn_perf_lock_release(&adev->perf_lock_handle);
5306 }
Zhou Songbaddf9f2020-11-20 13:57:39 +08005307 pthread_mutex_lock(&out->latch_lock);
5308 if (!is_a2dp_out_device_type(&out->device_list) || audio_extn_a2dp_source_is_ready()) {
5309 if (out->a2dp_muted) {
5310 out->a2dp_muted = false;
5311 if (is_offload_usecase(out->usecase))
5312 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5313 else if (out->usecase != USECASE_AUDIO_PLAYBACK_VOIP)
5314 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Weiyin Jiang280ea742020-09-08 20:28:22 +08005315 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005316 }
Zhou Songbaddf9f2020-11-20 13:57:39 +08005317 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP && !out->a2dp_muted)
5318 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
5319 pthread_mutex_unlock(&out->latch_lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005320 }
5321 }
5322
5323 pthread_mutex_unlock(&adev->lock);
5324 pthread_mutex_unlock(&out->lock);
5325
5326 /*handles device and call state changes*/
5327 audio_extn_extspk_update(adev->extspk);
5328
Revathi Uddaraju4255a632021-12-02 05:11:13 -08005329 clear_devices(&new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005330error:
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005331 ALOGV("%s: exit: code(%d)", __func__, ret);
5332 return ret;
5333}
5334
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005335static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
5336{
5337 struct stream_out *out = (struct stream_out *)stream;
5338 struct audio_device *adev = out->dev;
5339 struct str_parms *parms;
5340 char value[32];
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005341 int ret = 0, err;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005342 int ext_controller = -1;
5343 int ext_stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005344
sangwoobc677242013-08-08 16:53:43 +09005345 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005346 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005347 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305348 if (!parms)
5349 goto error;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005350
5351 err = platform_get_controller_stream_from_params(parms, &ext_controller,
5352 &ext_stream);
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08005353 if (err == 0) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005354 out->extconn.cs.controller = ext_controller;
5355 out->extconn.cs.stream = ext_stream;
5356 ALOGD("%s: usecase(%s) new controller/stream (%d/%d)", __func__,
5357 use_case_table[out->usecase], out->extconn.cs.controller,
5358 out->extconn.cs.stream);
5359 }
5360
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005361 if (out == adev->primary_output) {
5362 pthread_mutex_lock(&adev->lock);
5363 audio_extn_set_parameters(adev, parms);
5364 pthread_mutex_unlock(&adev->lock);
5365 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005366 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005367 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005368 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005369
5370 audio_extn_dts_create_state_notifier_node(out->usecase);
5371 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5372 popcount(out->channel_mask),
5373 out->playback_started);
5374
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08005375 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005376 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005377
Surendar Karkaf51b5842018-04-26 11:28:38 +05305378 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
5379 sizeof(value));
5380 if (err >= 0) {
5381 if (!strncmp("true", value, sizeof("true")) || atoi(value))
5382 audio_extn_send_dual_mono_mixing_coefficients(out);
5383 }
5384
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305385 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5386 if (err >= 0) {
5387 strlcpy(out->profile, value, sizeof(out->profile));
5388 ALOGV("updating stream profile with value '%s'", out->profile);
5389 lock_output_stream(out);
5390 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
5391 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005392 &out->device_list, out->flags,
5393 out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305394 out->sample_rate, out->bit_width,
5395 out->channel_mask, out->profile,
5396 &out->app_type_cfg);
5397 pthread_mutex_unlock(&out->lock);
5398 }
5399
Alexy Joseph98988832017-01-13 14:56:59 -08005400 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005401 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
5402 // and vendor.audio.hal.output.suspend.supported is set to true
5403 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08005404 //check suspend parameter only for low latency and if the property
5405 //is enabled
5406 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
5407 ALOGI("%s: got suspend_playback %s", __func__, value);
5408 lock_output_stream(out);
5409 if (!strncmp(value, "false", 5)) {
5410 //suspend_playback=false is supposed to set QOS value back to 75%
5411 //the mixer control sent with value Enable will achieve that
5412 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5413 } else if (!strncmp (value, "true", 4)) {
5414 //suspend_playback=true is supposed to remove QOS value
5415 //resetting the mixer control will set the default value
5416 //for the mixer control which is Disable and this removes the QOS vote
5417 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5418 } else {
5419 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
5420 " got %s", __func__, value);
5421 ret = -1;
5422 }
5423
5424 if (ret != 0) {
5425 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
5426 __func__, out->pm_qos_mixer_path, ret);
5427 }
5428
5429 pthread_mutex_unlock(&out->lock);
5430 }
5431 }
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005432
Alexy Joseph98988832017-01-13 14:56:59 -08005433 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005434 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305435error:
Eric Laurent994a6932013-07-17 11:51:42 -07005436 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005437 return ret;
5438}
5439
Paul McLeana50b7332018-12-17 08:24:21 -07005440static int in_set_microphone_direction(const struct audio_stream_in *stream,
5441 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07005442 struct stream_in *in = (struct stream_in *)stream;
5443
5444 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
5445
5446 in->direction = dir;
5447
5448 if (in->standby)
5449 return 0;
5450
5451 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07005452}
5453
5454static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07005455 struct stream_in *in = (struct stream_in *)stream;
5456
5457 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
5458
5459 if (zoom > 1.0 || zoom < -1.0)
5460 return -EINVAL;
5461
5462 in->zoom = zoom;
5463
5464 if (in->standby)
5465 return 0;
5466
5467 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07005468}
5469
5470
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005471static bool stream_get_parameter_channels(struct str_parms *query,
5472 struct str_parms *reply,
5473 audio_channel_mask_t *supported_channel_masks) {
5474 int ret = -1;
5475 char value[512];
5476 bool first = true;
5477 size_t i, j;
5478
5479 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
5480 ret = 0;
5481 value[0] = '\0';
5482 i = 0;
5483 while (supported_channel_masks[i] != 0) {
5484 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5485 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
5486 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305487 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005488
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305489 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005490 first = false;
5491 break;
5492 }
5493 }
5494 i++;
5495 }
5496 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5497 }
5498 return ret == 0;
5499}
5500
5501static bool stream_get_parameter_formats(struct str_parms *query,
5502 struct str_parms *reply,
5503 audio_format_t *supported_formats) {
5504 int ret = -1;
5505 char value[256];
5506 size_t i, j;
5507 bool first = true;
5508
5509 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
5510 ret = 0;
5511 value[0] = '\0';
5512 i = 0;
5513 while (supported_formats[i] != 0) {
5514 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5515 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
5516 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305517 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005518 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305519 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005520 first = false;
5521 break;
5522 }
5523 }
5524 i++;
5525 }
5526 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
5527 }
5528 return ret == 0;
5529}
5530
5531static bool stream_get_parameter_rates(struct str_parms *query,
5532 struct str_parms *reply,
5533 uint32_t *supported_sample_rates) {
5534
5535 int i;
5536 char value[256];
5537 int ret = -1;
5538 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
5539 ret = 0;
5540 value[0] = '\0';
5541 i=0;
5542 int cursor = 0;
5543 while (supported_sample_rates[i]) {
5544 int avail = sizeof(value) - cursor;
5545 ret = snprintf(value + cursor, avail, "%s%d",
5546 cursor > 0 ? "|" : "",
5547 supported_sample_rates[i]);
5548 if (ret < 0 || ret >= avail) {
5549 // if cursor is at the last element of the array
5550 // overwrite with \0 is duplicate work as
5551 // snprintf already put a \0 in place.
5552 // else
5553 // we had space to write the '|' at value[cursor]
5554 // (which will be overwritten) or no space to fill
5555 // the first element (=> cursor == 0)
5556 value[cursor] = '\0';
5557 break;
5558 }
5559 cursor += ret;
5560 ++i;
5561 }
5562 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
5563 value);
5564 }
5565 return ret >= 0;
5566}
5567
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005568static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
5569{
5570 struct stream_out *out = (struct stream_out *)stream;
5571 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005572 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005573 char value[256];
5574 struct str_parms *reply = str_parms_create();
5575 size_t i, j;
5576 int ret;
5577 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005578
5579 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005580 if (reply) {
5581 str_parms_destroy(reply);
5582 }
5583 if (query) {
5584 str_parms_destroy(query);
5585 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005586 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
5587 return NULL;
5588 }
5589
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005590 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005591 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
5592 if (ret >= 0) {
5593 value[0] = '\0';
5594 i = 0;
5595 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005596 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5597 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005598 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005599 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005600 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005601 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005602 first = false;
5603 break;
5604 }
5605 }
5606 i++;
5607 }
5608 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5609 str = str_parms_to_str(reply);
5610 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005611 voice_extn_out_get_parameters(out, query, reply);
5612 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005613 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005614
Alexy Joseph62142aa2015-11-16 15:10:34 -08005615
5616 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
5617 if (ret >= 0) {
5618 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05305619 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
5620 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08005621 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305622 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005623 } else {
5624 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05305625 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005626 }
5627 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005628 if (str)
5629 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08005630 str = str_parms_to_str(reply);
5631 }
5632
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005633 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
5634 if (ret >= 0) {
5635 value[0] = '\0';
5636 i = 0;
5637 first = true;
5638 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005639 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5640 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005641 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005642 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005643 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005644 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005645 first = false;
5646 break;
5647 }
5648 }
5649 i++;
5650 }
5651 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005652 if (str)
5653 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005654 str = str_parms_to_str(reply);
5655 }
Mingming Yin3a941d42016-02-17 18:08:05 -08005656
5657 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
5658 if (ret >= 0) {
5659 value[0] = '\0';
5660 i = 0;
5661 first = true;
5662 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005663 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
5664 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005665 if (!first) {
5666 strlcat(value, "|", sizeof(value));
5667 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005668 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08005669 first = false;
5670 break;
5671 }
5672 }
5673 i++;
5674 }
5675 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
5676 if (str)
5677 free(str);
5678 str = str_parms_to_str(reply);
5679 }
5680
Alexy Joseph98988832017-01-13 14:56:59 -08005681 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
5682 //only low latency track supports suspend_resume
5683 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005684 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08005685 if (str)
5686 free(str);
5687 str = str_parms_to_str(reply);
5688 }
5689
5690
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005691 str_parms_destroy(query);
5692 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07005693 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005694 return str;
5695}
5696
5697static uint32_t out_get_latency(const struct audio_stream_out *stream)
5698{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005699 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005700 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08005701 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005702
Alexy Josephaa54c872014-12-03 02:46:47 -08005703 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05305704 lock_output_stream(out);
5705 latency = audio_extn_utils_compress_get_dsp_latency(out);
5706 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005707 } else if ((out->realtime) ||
5708 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005709 // since the buffer won't be filled up faster than realtime,
5710 // return a smaller number
5711 if (out->config.rate)
5712 period_ms = (out->af_period_multiplier * out->config.period_size *
5713 1000) / (out->config.rate);
5714 else
5715 period_ms = 0;
George Gao9ba8a142020-07-23 14:30:03 -07005716 latency = period_ms + platform_render_latency(out) / 1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005717 } else {
5718 latency = (out->config.period_count * out->config.period_size * 1000) /
Mingshu Pangf69a88d2021-04-30 16:14:39 +08005719 (out->config.rate);
pavanisra2d95d82022-02-09 18:55:58 +05305720 if (out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5721 out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY)
Mingshu Pangf69a88d2021-04-30 16:14:39 +08005722 latency += platform_render_latency(out)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005723 }
5724
Zhou Songd2537a02020-06-11 22:04:46 +08005725 if (!out->standby && is_a2dp_out_device_type(&out->device_list))
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08005726 latency += audio_extn_a2dp_get_encoder_latency();
5727
Anish Kumar50ebcbf2014-12-09 04:01:39 +05305728 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08005729 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005730}
5731
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305732static float AmpToDb(float amplification)
5733{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305734 float db = DSD_VOLUME_MIN_DB;
5735 if (amplification > 0) {
5736 db = 20 * log10(amplification);
5737 if(db < DSD_VOLUME_MIN_DB)
5738 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305739 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305740 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305741}
5742
Krishna Kishor Jha10ad39f2022-02-21 17:02:47 +05305743#ifdef SOFT_VOLUME
5744static int out_set_soft_volume_params(struct audio_stream_out *stream)
5745{
5746 struct stream_out *out = (struct stream_out *)stream;
5747 int ret = 0;
5748 char mixer_ctl_name[128];
5749 struct audio_device *adev = out->dev;
5750 struct mixer_ctl *ctl = NULL;
5751 struct soft_step_volume_params *volume_params = NULL;
5752
5753 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5754 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Soft Vol Params", pcm_device_id);
5755 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5756 if (!ctl) {
5757 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5758 return -EINVAL;
5759 }
5760
5761 volume_params =(struct soft_step_volume_params * ) malloc(sizeof(struct soft_step_volume_params));
5762 if (volume_params == NULL){
5763 ALOGE("%s : malloc is failed for volume params", __func__);
5764 return -EINVAL;
5765 } else {
5766 ret = platform_get_soft_step_volume_params(volume_params,out->usecase);
5767 if (ret < 0) {
5768 ALOGE("%s : platform_get_soft_step_volume_params is fialed", __func__);
5769 return -EINVAL;
5770 }
5771
5772 }
5773 ret = mixer_ctl_set_array(ctl, volume_params, sizeof(struct soft_step_volume_params)/sizeof(int));
5774 if (ret < 0) {
5775 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
5776 return -EINVAL;
5777 }
5778 return 0;
5779}
5780#endif
5781
Arun Mirpuri5d170872019-03-26 13:21:31 -07005782static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
5783 float right)
5784{
5785 struct stream_out *out = (struct stream_out *)stream;
5786 long volume = 0;
5787 char mixer_ctl_name[128] = "";
5788 struct audio_device *adev = out->dev;
5789 struct mixer_ctl *ctl = NULL;
5790 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5791 PCM_PLAYBACK);
5792
5793 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5794 "Playback %d Volume", pcm_device_id);
5795 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5796 if (!ctl) {
5797 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5798 __func__, mixer_ctl_name);
5799 return -EINVAL;
5800 }
5801 if (left != right)
5802 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
5803 __func__, left, right);
5804 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
5805 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
5806 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
5807 __func__, mixer_ctl_name, volume);
5808 return -EINVAL;
5809 }
5810 return 0;
5811}
5812
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305813static int out_set_compr_volume(struct audio_stream_out *stream, float left,
5814 float right)
5815{
5816 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305817 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305818 char mixer_ctl_name[128];
5819 struct audio_device *adev = out->dev;
5820 struct mixer_ctl *ctl;
5821 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5822 PCM_PLAYBACK);
5823
5824 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5825 "Compress Playback %d Volume", pcm_device_id);
5826 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5827 if (!ctl) {
5828 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5829 __func__, mixer_ctl_name);
5830 return -EINVAL;
5831 }
5832 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
5833 __func__, mixer_ctl_name, left, right);
5834 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
5835 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
5836 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5837
5838 return 0;
5839}
5840
Zhou Song2b8f28f2017-09-11 10:51:38 +08005841static int out_set_voip_volume(struct audio_stream_out *stream, float left,
5842 float right)
5843{
5844 struct stream_out *out = (struct stream_out *)stream;
5845 char mixer_ctl_name[] = "App Type Gain";
5846 struct audio_device *adev = out->dev;
5847 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305848 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08005849
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07005850 if (!is_valid_volume(left, right)) {
5851 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
5852 __func__, left, right);
5853 return -EINVAL;
5854 }
5855
Zhou Song2b8f28f2017-09-11 10:51:38 +08005856 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5857 if (!ctl) {
5858 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5859 __func__, mixer_ctl_name);
5860 return -EINVAL;
5861 }
5862
5863 set_values[0] = 0; //0: Rx Session 1:Tx Session
5864 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305865 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
5866 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005867
5868 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
5869 return 0;
5870}
5871
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305872static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
5873 float right)
5874{
5875 struct stream_out *out = (struct stream_out *)stream;
5876 /* Volume control for pcm playback */
5877 if (left != right) {
5878 return -EINVAL;
5879 } else {
5880 char mixer_ctl_name[128];
5881 struct audio_device *adev = out->dev;
5882 struct mixer_ctl *ctl;
5883 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5884 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
5885 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5886 if (!ctl) {
5887 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5888 return -EINVAL;
5889 }
5890
5891 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
5892 int ret = mixer_ctl_set_value(ctl, 0, volume);
5893 if (ret < 0) {
5894 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
5895 return -EINVAL;
5896 }
5897
5898 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
5899
5900 return 0;
5901 }
5902}
5903
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005904static int out_set_volume(struct audio_stream_out *stream, float left,
5905 float right)
5906{
Eric Laurenta9024de2013-04-04 09:19:12 -07005907 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005908 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305909 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005910
Arun Mirpuri5d170872019-03-26 13:21:31 -07005911 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07005912 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
5913 /* only take left channel into account: the API is for stereo anyway */
5914 out->muted = (left == 0.0f);
5915 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005916 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305917 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005918 /*
5919 * Set mute or umute on HDMI passthrough stream.
5920 * Only take left channel into account.
5921 * Mute is 0 and unmute 1
5922 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305923 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305924 } else if (out->format == AUDIO_FORMAT_DSD){
5925 char mixer_ctl_name[128] = "DSD Volume";
5926 struct audio_device *adev = out->dev;
5927 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5928
5929 if (!ctl) {
5930 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5931 __func__, mixer_ctl_name);
5932 return -EINVAL;
5933 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05305934 volume[0] = (long)(AmpToDb(left));
5935 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305936 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5937 return 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005938 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS) &&
Derek Chendf05eea2019-08-01 13:57:49 -07005939 (out->car_audio_stream == CAR_AUDIO_STREAM_MEDIA)) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005940 ALOGD("%s: Overriding offload set volume for media bus stream", __func__);
5941 struct listnode *node = NULL;
5942 list_for_each(node, &adev->active_outputs_list) {
5943 streams_output_ctxt_t *out_ctxt = node_to_item(node,
5944 streams_output_ctxt_t,
5945 list);
5946 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
5947 out->volume_l = out_ctxt->output->volume_l;
5948 out->volume_r = out_ctxt->output->volume_r;
5949 }
5950 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08005951 pthread_mutex_lock(&out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +08005952 if (!out->a2dp_muted) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005953 ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5954 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08005955 pthread_mutex_unlock(&out->latch_lock);
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005956 return ret;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005957 } else {
Weiyin Jiang280ea742020-09-08 20:28:22 +08005958 pthread_mutex_lock(&out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +08005959 ALOGV("%s: compress mute %d", __func__, out->a2dp_muted);
5960 if (!out->a2dp_muted)
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305961 ret = out_set_compr_volume(stream, left, right);
5962 out->volume_l = left;
5963 out->volume_r = right;
Weiyin Jiang280ea742020-09-08 20:28:22 +08005964 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305965 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005966 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005967 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005968 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
5969 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Songbaddf9f2020-11-20 13:57:39 +08005970 pthread_mutex_lock(&out->latch_lock);
Aalique Grahame22e49102018-12-18 14:23:57 -08005971 if (!out->standby) {
5972 audio_extn_utils_send_app_type_gain(out->dev,
5973 out->app_type_cfg.app_type,
5974 &out->app_type_cfg.gain[0]);
Zhou Songbaddf9f2020-11-20 13:57:39 +08005975 if (!out->a2dp_muted)
5976 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08005977 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08005978 out->volume_l = left;
5979 out->volume_r = right;
Zhou Songbaddf9f2020-11-20 13:57:39 +08005980 pthread_mutex_unlock(&out->latch_lock);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005981 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005982 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5983 ALOGV("%s: MMAP set volume called", __func__);
5984 if (!out->standby)
5985 ret = out_set_mmap_volume(stream, left, right);
5986 out->volume_l = left;
5987 out->volume_r = right;
5988 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305989 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05305990 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5991 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Zhou Songbaddf9f2020-11-20 13:57:39 +08005992 pthread_mutex_lock(&out->latch_lock);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305993 /* Volume control for pcm playback */
Zhou Songbaddf9f2020-11-20 13:57:39 +08005994 if (!out->standby && !out->a2dp_muted)
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305995 ret = out_set_pcm_volume(stream, left, right);
5996 else
5997 out->apply_volume = true;
5998
5999 out->volume_l = left;
6000 out->volume_r = right;
Zhou Songbaddf9f2020-11-20 13:57:39 +08006001 pthread_mutex_unlock(&out->latch_lock);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05306002 return ret;
Derek Chenf13dd492018-11-13 14:53:51 -08006003 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
6004 ALOGV("%s: bus device set volume called", __func__);
Zhou Songbaddf9f2020-11-20 13:57:39 +08006005 pthread_mutex_lock(&out->latch_lock);
6006 if (!out->standby && !out->a2dp_muted)
Derek Chenf13dd492018-11-13 14:53:51 -08006007 ret = out_set_pcm_volume(stream, left, right);
6008 out->volume_l = left;
6009 out->volume_r = right;
Zhou Songbaddf9f2020-11-20 13:57:39 +08006010 pthread_mutex_unlock(&out->latch_lock);
Derek Chenf13dd492018-11-13 14:53:51 -08006011 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07006012 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006013
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006014 return -ENOSYS;
6015}
6016
Zhou Songc9672822017-08-16 16:01:39 +08006017static void update_frames_written(struct stream_out *out, size_t bytes)
6018{
6019 size_t bpf = 0;
6020
6021 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
6022 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
6023 bpf = 1;
6024 else if (!is_offload_usecase(out->usecase))
6025 bpf = audio_bytes_per_sample(out->format) *
6026 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08006027
6028 pthread_mutex_lock(&out->position_query_lock);
6029 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08006030 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08006031 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
6032 }
6033 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08006034}
6035
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006036int split_and_write_audio_haptic_data(struct stream_out *out,
6037 const void *buffer, size_t bytes_to_write)
6038{
6039 struct audio_device *adev = out->dev;
6040
6041 int ret = 0;
6042 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
6043 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
6044 size_t frame_size = channel_count * bytes_per_sample;
6045 size_t frame_count = bytes_to_write / frame_size;
6046
6047 bool force_haptic_path =
6048 property_get_bool("vendor.audio.test_haptic", false);
6049
6050 // extract Haptics data from Audio buffer
6051 bool alloc_haptic_buffer = false;
6052 int haptic_channel_count = adev->haptics_config.channels;
6053 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
6054 size_t audio_frame_size = frame_size - haptic_frame_size;
6055 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
6056
6057 if (adev->haptic_buffer == NULL) {
6058 alloc_haptic_buffer = true;
6059 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
6060 free(adev->haptic_buffer);
6061 adev->haptic_buffer_size = 0;
6062 alloc_haptic_buffer = true;
6063 }
6064
6065 if (alloc_haptic_buffer) {
6066 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08006067 if(adev->haptic_buffer == NULL) {
6068 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
6069 return -ENOMEM;
6070 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006071 adev->haptic_buffer_size = total_haptic_buffer_size;
6072 }
6073
6074 size_t src_index = 0, aud_index = 0, hap_index = 0;
6075 uint8_t *audio_buffer = (uint8_t *)buffer;
6076 uint8_t *haptic_buffer = adev->haptic_buffer;
6077
6078 // This is required for testing only. This works for stereo data only.
6079 // One channel is fed to audio stream and other to haptic stream for testing.
6080 if (force_haptic_path)
6081 audio_frame_size = haptic_frame_size = bytes_per_sample;
6082
6083 for (size_t i = 0; i < frame_count; i++) {
6084 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
6085 audio_frame_size);
6086 aud_index += audio_frame_size;
6087 src_index += audio_frame_size;
6088
6089 if (adev->haptic_pcm)
6090 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
6091 haptic_frame_size);
6092 hap_index += haptic_frame_size;
6093 src_index += haptic_frame_size;
6094
6095 // This is required for testing only.
6096 // Discard haptic channel data.
6097 if (force_haptic_path)
6098 src_index += haptic_frame_size;
6099 }
6100
6101 // write to audio pipeline
6102 ret = pcm_write(out->pcm, (void *)audio_buffer,
6103 frame_count * audio_frame_size);
6104
6105 // write to haptics pipeline
6106 if (adev->haptic_pcm)
6107 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
6108 frame_count * haptic_frame_size);
6109
6110 return ret;
6111}
6112
Aalique Grahame22e49102018-12-18 14:23:57 -08006113#ifdef NO_AUDIO_OUT
6114static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
6115 const void *buffer __unused, size_t bytes)
6116{
6117 struct stream_out *out = (struct stream_out *)stream;
6118
6119 /* No Output device supported other than BT for playback.
6120 * Sleep for the amount of buffer duration
6121 */
6122 lock_output_stream(out);
6123 usleep(bytes * 1000000 / audio_stream_out_frame_size(
6124 (const struct audio_stream_out *)&out->stream) /
6125 out_get_sample_rate(&out->stream.common));
6126 pthread_mutex_unlock(&out->lock);
6127 return bytes;
6128}
6129#endif
6130
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006131static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
6132 size_t bytes)
6133{
6134 struct stream_out *out = (struct stream_out *)stream;
6135 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07006136 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05306137 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006138 const size_t frame_size = audio_stream_out_frame_size(stream);
6139 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05306140 struct audio_usecase *usecase = NULL;
Meng Wang4c32fb42020-01-16 17:57:11 +08006141 uint32_t compr_passthr = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006142
Haynes Mathew George380745d2017-10-04 15:27:45 -07006143 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006144 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306145
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05006146 if (CARD_STATUS_OFFLINE == out->card_status ||
6147 POWER_POLICY_STATUS_OFFLINE == adev->out_power_policy) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08006148
Dhananjay Kumarac341582017-02-23 23:42:25 +05306149 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306150 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05306151 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
6152 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006153 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05306154 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05306155 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05306156 ALOGD(" %s: sound card is not active/SSR state", __func__);
6157 ret= -EIO;
6158 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306159 }
6160 }
6161
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306162 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05306163 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05306164 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306165 goto exit;
6166 }
6167
Haynes Mathew George16081042017-05-31 17:16:49 -07006168 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
6169 ret = -EINVAL;
6170 goto exit;
6171 }
6172
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006173 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306174 !out->is_iec61937_info_available) {
6175
6176 if (!audio_extn_passthru_is_passthrough_stream(out)) {
6177 out->is_iec61937_info_available = true;
6178 } else if (audio_extn_passthru_is_enabled()) {
6179 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05306180 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05306181
6182 if((out->format == AUDIO_FORMAT_DTS) ||
6183 (out->format == AUDIO_FORMAT_DTS_HD)) {
6184 ret = audio_extn_passthru_update_dts_stream_configuration(out,
6185 buffer, bytes);
6186 if (ret) {
6187 if (ret != -ENOSYS) {
6188 out->is_iec61937_info_available = false;
6189 ALOGD("iec61937 transmission info not yet updated retry");
6190 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306191 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05306192 /* if stream has started and after that there is
6193 * stream config change (iec transmission config)
6194 * then trigger select_device to update backend configuration.
6195 */
6196 out->stream_config_changed = true;
6197 pthread_mutex_lock(&adev->lock);
6198 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306199 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08006200 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306201 ret = -EINVAL;
6202 goto exit;
6203 }
Manish Dewangan671a4202017-08-18 17:30:46 +05306204 pthread_mutex_unlock(&adev->lock);
6205 out->stream_config_changed = false;
6206 out->is_iec61937_info_available = true;
6207 }
6208 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05306209
Meng Wang4c32fb42020-01-16 17:57:11 +08006210#ifdef AUDIO_GKI_ENABLED
6211 /* out->compr_config.codec->reserved[0] is for compr_passthr */
6212 compr_passthr = out->compr_config.codec->reserved[0];
6213#else
6214 compr_passthr = out->compr_config.codec->compr_passthr;
6215#endif
6216
Garmond Leung317cbf12017-09-13 16:20:50 -07006217 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Meng Wang4c32fb42020-01-16 17:57:11 +08006218 (compr_passthr == PASSTHROUGH) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05306219 (out->is_iec61937_info_available == true)) {
6220 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
6221 ret = -EINVAL;
6222 goto exit;
6223 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05306224 }
6225 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306226
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006227 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02006228 (audio_extn_a2dp_source_is_suspended())) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006229 if (!(compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER) ||
6230 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Zhou Songd01e7a22020-09-23 22:49:01 +08006231 if (!is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306232 ret = -EIO;
6233 goto exit;
6234 }
6235 }
6236 }
6237
Weiyin Jiangabedea32020-12-09 12:49:19 +08006238 if (is_usb_out_device_type(&out->device_list) &&
6239 !audio_extn_usb_connected(NULL)) {
6240 ret = -EIO;
6241 goto exit;
6242 }
6243
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006244 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07006245 out->standby = false;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006246 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
6247
Eric Laurent150dbfe2013-02-27 14:31:02 -08006248 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006249 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
6250 ret = voice_extn_compress_voip_start_output_stream(out);
6251 else
6252 ret = start_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006253 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006254 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07006255 out->standby = true;
Weiyin Jiangac2bae82020-07-29 17:23:53 +08006256 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006257 goto exit;
6258 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306259 out->started = 1;
Andy Hunga1f48fa2019-07-01 18:14:53 -07006260 out->last_fifo_valid = false; // we're coming out of standby, last_fifo isn't valid.
Weiyin Jiangac2bae82020-07-29 17:23:53 +08006261
6262 if ((last_known_cal_step != -1) && (adev->platform != NULL)) {
vivek mehtab72d08d2016-04-29 03:16:47 -07006263 ALOGD("%s: retry previous failed cal level set", __func__);
Weiyin Jiangac2bae82020-07-29 17:23:53 +08006264 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05306265 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07006266 }
Weiyin Jiangac2bae82020-07-29 17:23:53 +08006267 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306268
6269 if ((out->is_iec61937_info_available == true) &&
6270 (audio_extn_passthru_is_passthrough_stream(out))&&
6271 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
6272 ret = -EINVAL;
6273 goto exit;
6274 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05306275 if (out->set_dual_mono)
6276 audio_extn_send_dual_mono_mixing_coefficients(out);
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006277
Dechen Chai22768452021-07-30 09:29:16 +05306278#ifndef LINUX_ENABLED
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006279 // log startup time in ms.
6280 simple_stats_log(
6281 &out->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Dechen Chai22768452021-07-30 09:29:16 +05306282#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006283 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006284
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006285 if (adev->is_channel_status_set == false &&
6286 compare_device_type(&out->device_list,
6287 AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Alexy Josephb1379942016-01-29 15:49:38 -08006288 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05306289 adev->is_channel_status_set = true;
6290 }
6291
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05306292 if ((adev->use_old_pspd_mix_ctrl == true) &&
6293 (out->pspd_coeff_sent == false)) {
6294 /*
6295 * Need to resend pspd coefficients after stream started for
6296 * older kernel version as it does not save the coefficients
6297 * and also stream has to be started for coeff to apply.
6298 */
6299 usecase = get_usecase_from_list(adev, out->usecase);
6300 if (usecase != NULL) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05306301 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05306302 out->pspd_coeff_sent = true;
6303 }
6304 }
6305
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006306 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08006307 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006308 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006309 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006310 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
6311 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05306312 if (out->send_next_track_params && out->is_compr_metadata_avail) {
6313 ALOGD("copl(%p):send next track params in gapless", out);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08006314 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05306315 out->send_next_track_params = false;
6316 out->is_compr_metadata_avail = false;
6317 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006318 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05306319 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306320 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006321
Ashish Jain83a6cc22016-06-28 14:34:17 +05306322 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05306323 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05306324 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05306325 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006326 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05306327 return -EINVAL;
6328 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05306329 audio_format_t dst_format = out->hal_op_format;
6330 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306331
Dieter Luecking5d57def2018-09-07 14:23:37 +02006332 /* prevent division-by-zero */
6333 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
6334 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
6335 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
6336 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05306337 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006338 ATRACE_END();
6339 return -EINVAL;
6340 }
6341
Ashish Jainf1eaa582016-05-23 20:54:24 +05306342 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
6343 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
6344
Ashish Jain83a6cc22016-06-28 14:34:17 +05306345 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05306346 dst_format,
6347 buffer,
6348 src_format,
6349 frames);
6350
Ashish Jain83a6cc22016-06-28 14:34:17 +05306351 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05306352 bytes_to_write);
6353
6354 /*Convert written bytes in audio flinger format*/
6355 if (ret > 0)
6356 ret = ((ret * format_to_bitwidth_table[out->format]) /
6357 format_to_bitwidth_table[dst_format]);
6358 }
6359 } else
6360 ret = compress_write(out->compr, buffer, bytes);
6361
Zhou Songc9672822017-08-16 16:01:39 +08006362 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
6363 update_frames_written(out, bytes);
6364
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306365 if (ret < 0)
6366 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08006367 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05306368 /*msg to cb thread only if non blocking write is enabled*/
6369 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05306370 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006371 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05306372 } else if (-ENETRESET == ret) {
6373 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306374 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05306375 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05306376 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006377 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05306378 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006379 }
Ashish Jain5106d362016-05-11 19:23:33 +05306380
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05306381 /* Call compr start only when non-zero bytes of data is there to be rendered */
6382 if (!out->playback_started && ret > 0) {
6383 int status = compress_start(out->compr);
6384 if (status < 0) {
6385 ret = status;
6386 ALOGE("%s: compr start failed with err %d", __func__, errno);
6387 goto exit;
6388 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07006389 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006390 out->playback_started = 1;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006391 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006392 out->offload_state = OFFLOAD_STATE_PLAYING;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006393 pthread_mutex_unlock(&out->latch_lock);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006394
6395 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6396 popcount(out->channel_mask),
6397 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006398 }
6399 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006400 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006401 return ret;
6402 } else {
6403 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006404 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006405 if (out->muted)
6406 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006407 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
6408 __func__, frames, frame_size, bytes_to_write);
6409
Aalique Grahame22e49102018-12-18 14:23:57 -08006410 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07006411 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
6412 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
6413 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006414 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
6415 int16_t *src = (int16_t *)buffer;
6416 int16_t *dst = (int16_t *)buffer;
6417
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006418 LOG_ALWAYS_FATAL_IF(channel_count > 2 ||
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006419 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08006420 "out_write called for %s use case with wrong properties",
6421 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006422
6423 /*
6424 * FIXME: this can be removed once audio flinger mixer supports
6425 * mono output
6426 */
6427
6428 /*
6429 * Code below goes over each frame in the buffer and adds both
6430 * L and R samples and then divides by 2 to convert to mono
6431 */
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006432 if (channel_count == 2) {
6433 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
6434 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
6435 }
6436 bytes_to_write /= 2;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006437 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006438 }
Andy Hunga1f48fa2019-07-01 18:14:53 -07006439
6440 // Note: since out_get_presentation_position() is called alternating with out_write()
6441 // by AudioFlinger, we can check underruns using the prior timestamp read.
6442 // (Alternately we could check if the buffer is empty using pcm_get_htimestamp().
6443 if (out->last_fifo_valid) {
6444 // compute drain to see if there is an underrun.
6445 const int64_t current_ns = systemTime(SYSTEM_TIME_MONOTONIC); // sys call
Dhananjay Kumara4429632020-07-11 02:53:37 +05306446 int64_t time_diff_ns = current_ns - out->last_fifo_time_ns;
6447 int64_t frames_by_time =
6448 ((time_diff_ns > 0) && (time_diff_ns < (INT64_MAX / out->config.rate))) ?
6449 (time_diff_ns * out->config.rate / NANOS_PER_SECOND) : 0;
Andy Hunga1f48fa2019-07-01 18:14:53 -07006450 const int64_t underrun = frames_by_time - out->last_fifo_frames_remaining;
6451
6452 if (underrun > 0) {
Dechen Chai22768452021-07-30 09:29:16 +05306453#ifndef LINUX_ENABLED
Andy Hunga1f48fa2019-07-01 18:14:53 -07006454 simple_stats_log(&out->fifo_underruns, underrun);
Dechen Chai22768452021-07-30 09:29:16 +05306455#endif
Andy Hunga1f48fa2019-07-01 18:14:53 -07006456
6457 ALOGW("%s: underrun(%lld) "
6458 "frames_by_time(%lld) > out->last_fifo_frames_remaining(%lld)",
6459 __func__,
6460 (long long)out->fifo_underruns.n,
6461 (long long)frames_by_time,
6462 (long long)out->last_fifo_frames_remaining);
6463 }
6464 out->last_fifo_valid = false; // we're writing below, mark fifo info as stale.
6465 }
6466
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306467 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006468
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006469 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006470
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006471 if (out->config.rate)
6472 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
6473 out->config.rate;
6474
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006475 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006476 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
6477
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006478 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006479 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006480 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306481 out->convert_buffer != NULL) {
6482
6483 memcpy_by_audio_format(out->convert_buffer,
6484 out->hal_op_format,
6485 buffer,
6486 out->hal_ip_format,
6487 out->config.period_size * out->config.channels);
6488
6489 ret = pcm_write(out->pcm, out->convert_buffer,
6490 (out->config.period_size *
6491 out->config.channels *
6492 format_to_bitwidth_table[out->hal_op_format]));
6493 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05306494 /*
6495 * To avoid underrun in DSP when the application is not pumping
6496 * data at required rate, check for the no. of bytes and ignore
6497 * pcm_write if it is less than actual buffer size.
6498 * It is a work around to a change in compress VOIP driver.
6499 */
6500 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
6501 bytes < (out->config.period_size * out->config.channels *
6502 audio_bytes_per_sample(out->format))) {
6503 size_t voip_buf_size =
6504 out->config.period_size * out->config.channels *
6505 audio_bytes_per_sample(out->format);
6506 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
6507 __func__, bytes, voip_buf_size);
6508 usleep(((uint64_t)voip_buf_size - bytes) *
6509 1000000 / audio_stream_out_frame_size(stream) /
6510 out_get_sample_rate(&out->stream.common));
6511 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006512 } else {
6513 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
6514 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
6515 else
6516 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
6517 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306518 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006519
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006520 release_out_focus(out);
6521
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306522 if (ret < 0)
6523 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08006524 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05306525 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006526 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006527 }
6528
6529exit:
Zhou Songc9672822017-08-16 16:01:39 +08006530 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306531 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306532 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306533 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006534 pthread_mutex_unlock(&out->lock);
6535
6536 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006537 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08006538 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306539 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306540 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306541 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306542 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306543 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306544 out->standby = true;
6545 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306546 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006547 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
6548 /* prevent division-by-zero */
6549 uint32_t stream_size = audio_stream_out_frame_size(stream);
6550 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006551
Dieter Luecking5d57def2018-09-07 14:23:37 +02006552 if ((stream_size == 0) || (srate == 0)) {
6553 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
6554 ATRACE_END();
6555 return -EINVAL;
6556 }
6557 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
6558 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006559 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05306560 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006561 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006562 return ret;
6563 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006564 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07006565 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006566 return bytes;
6567}
6568
6569static int out_get_render_position(const struct audio_stream_out *stream,
6570 uint32_t *dsp_frames)
6571{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006572 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08006573
6574 if (dsp_frames == NULL)
6575 return -EINVAL;
6576
6577 *dsp_frames = 0;
6578 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08006579 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05306580
6581 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
6582 * this operation and adev_close_output_stream(where out gets reset).
6583 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05306584 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006585 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05306586 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006587 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05306588 return 0;
6589 }
6590
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006591 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05306592 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306593 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006594 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306595 if (ret < 0)
6596 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006597 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05306598 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006599 }
Naresh Tanniru80659832014-06-04 18:17:56 +05306600 if (-ENETRESET == ret) {
6601 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306602 out->card_status = CARD_STATUS_OFFLINE;
6603 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306604 } else if(ret < 0) {
6605 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306606 ret = -EINVAL;
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05006607 } else if (out->card_status == CARD_STATUS_OFFLINE ||
6608 adev->out_power_policy == POWER_POLICY_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05306609 /*
6610 * Handle corner case where compress session is closed during SSR
6611 * and timestamp is queried
6612 */
6613 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306614 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306615 } else if (out->prev_card_status_offline) {
6616 ALOGE("ERROR: previously sound card was offline,return error");
6617 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306618 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306619 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006620 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05306621 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306622 pthread_mutex_unlock(&out->lock);
6623 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08006624 } else if (audio_is_linear_pcm(out->format)) {
6625 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006626 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08006627 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006628 } else
6629 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006630}
6631
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006632static int out_add_audio_effect(const struct audio_stream *stream __unused,
6633 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006634{
6635 return 0;
6636}
6637
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006638static int out_remove_audio_effect(const struct audio_stream *stream __unused,
6639 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006640{
6641 return 0;
6642}
6643
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006644static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
6645 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006646{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05306647 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006648}
6649
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006650static int out_get_presentation_position(const struct audio_stream_out *stream,
6651 uint64_t *frames, struct timespec *timestamp)
6652{
6653 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05306654 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07006655 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006656
Ashish Jain5106d362016-05-11 19:23:33 +05306657 /* below piece of code is not guarded against any lock because audioFliner serializes
6658 * this operation and adev_close_output_stream( where out gets reset).
6659 */
6660 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05306661 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006662 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05306663 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
6664 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
6665 return 0;
6666 }
6667
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006668 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006669
Ashish Jain5106d362016-05-11 19:23:33 +05306670 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
6671 ret = compress_get_tstamp(out->compr, &dsp_frames,
6672 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08006673 // Adjustment accounts for A2dp encoder latency with offload usecases
6674 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006675 if (is_a2dp_out_device_type(&out->device_list)) {
yidongh0515e042017-07-06 15:00:34 +08006676 unsigned long offset =
6677 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
6678 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
6679 }
Ashish Jain5106d362016-05-11 19:23:33 +05306680 ALOGVV("%s rendered frames %ld sample_rate %d",
6681 __func__, dsp_frames, out->sample_rate);
6682 *frames = dsp_frames;
6683 if (ret < 0)
6684 ret = -errno;
6685 if (-ENETRESET == ret) {
6686 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306687 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05306688 ret = -EINVAL;
6689 } else
6690 ret = 0;
6691 /* this is the best we can do */
6692 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07006693 } else {
6694 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08006695 unsigned int avail;
6696 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
George Gao62ebc722019-07-29 16:29:44 -07006697 uint64_t signed_frames = 0;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006698 uint64_t frames_temp = 0;
George Gao62ebc722019-07-29 16:29:44 -07006699
Andy Hunga1f48fa2019-07-01 18:14:53 -07006700 if (out->kernel_buffer_size > avail) {
6701 frames_temp = out->last_fifo_frames_remaining = out->kernel_buffer_size - avail;
6702 } else {
6703 ALOGW("%s: avail:%u > kernel_buffer_size:%zu clamping!",
6704 __func__, avail, out->kernel_buffer_size);
6705 avail = out->kernel_buffer_size;
6706 frames_temp = out->last_fifo_frames_remaining = 0;
6707 }
6708 out->last_fifo_valid = true;
6709 out->last_fifo_time_ns = audio_utils_ns_from_timespec(timestamp);
6710
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006711 if (out->written >= frames_temp)
6712 signed_frames = out->written - frames_temp;
George Gao62ebc722019-07-29 16:29:44 -07006713
Andy Hunga1f48fa2019-07-01 18:14:53 -07006714 ALOGVV("%s: frames:%lld avail:%u kernel_buffer_size:%zu",
6715 __func__, (long long)signed_frames, avail, out->kernel_buffer_size);
6716
Weiyin Jiangd4633762018-03-16 12:05:03 +08006717 // This adjustment accounts for buffering after app processor.
6718 // It is based on estimated DSP latency per use case, rather than exact.
George Gao9ba8a142020-07-23 14:30:03 -07006719 frames_temp = platform_render_latency(out) *
Robert Lee58215542019-07-15 20:55:12 +08006720 out->sample_rate / 1000000LL;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006721 if (signed_frames >= frames_temp)
6722 signed_frames -= frames_temp;
Aniket Kumar Lataff613152017-07-18 18:19:21 -07006723
Weiyin Jiangd4633762018-03-16 12:05:03 +08006724 // Adjustment accounts for A2dp encoder latency with non offload usecases
6725 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006726 if (is_a2dp_out_device_type(&out->device_list)) {
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006727 frames_temp = audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000;
6728 if (signed_frames >= frames_temp)
6729 signed_frames -= frames_temp;
Weiyin Jiangd4633762018-03-16 12:05:03 +08006730 }
6731
6732 // It would be unusual for this value to be negative, but check just in case ...
George Gao62ebc722019-07-29 16:29:44 -07006733 *frames = signed_frames;
6734 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006735 }
Eric Laurenta7a33042019-07-10 16:20:22 -07006736 } else if (out->card_status == CARD_STATUS_OFFLINE ||
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05006737 adev->out_power_policy == POWER_POLICY_STATUS_OFFLINE ||
Eric Laurenta7a33042019-07-10 16:20:22 -07006738 // audioflinger still needs position updates when A2DP is suspended
Jasmine Cha5c2517f2019-09-09 11:07:28 +08006739 (is_a2dp_out_device_type(&out->device_list) && audio_extn_a2dp_source_is_suspended())) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306740 *frames = out->written;
6741 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306742 if (is_offload_usecase(out->usecase))
6743 ret = -EINVAL;
6744 else
6745 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006746 }
6747 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006748 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006749 return ret;
6750}
6751
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006752static int out_set_callback(struct audio_stream_out *stream,
6753 stream_callback_t callback, void *cookie)
6754{
6755 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006756 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006757
6758 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006759 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006760 out->client_callback = callback;
6761 out->client_cookie = cookie;
6762 if (out->adsp_hdlr_stream_handle) {
6763 ret = audio_extn_adsp_hdlr_stream_set_callback(
6764 out->adsp_hdlr_stream_handle,
6765 callback,
6766 cookie);
6767 if (ret)
6768 ALOGW("%s:adsp hdlr callback registration failed %d",
6769 __func__, ret);
6770 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006771 pthread_mutex_unlock(&out->lock);
6772 return 0;
6773}
6774
6775static int out_pause(struct audio_stream_out* stream)
6776{
6777 struct stream_out *out = (struct stream_out *)stream;
6778 int status = -ENOSYS;
6779 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006780 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006781 ALOGD("copl(%p):pause compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306782 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006783 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006784 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006785 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306786 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05306787 status = compress_pause(out->compr);
6788
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006789 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006790
Mingming Yin21854652016-04-13 11:54:02 -07006791 if (audio_extn_passthru_is_active()) {
6792 ALOGV("offload use case, pause passthru");
6793 audio_extn_passthru_on_pause(out);
6794 }
6795
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306796 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006797 audio_extn_dts_notify_playback_state(out->usecase, 0,
6798 out->sample_rate, popcount(out->channel_mask),
6799 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006800 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08006801 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006802 pthread_mutex_unlock(&out->lock);
6803 }
6804 return status;
6805}
6806
6807static int out_resume(struct audio_stream_out* stream)
6808{
6809 struct stream_out *out = (struct stream_out *)stream;
6810 int status = -ENOSYS;
6811 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006812 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006813 ALOGD("copl(%p):resume compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306814 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006815 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006816 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006817 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306818 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306819 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07006820 }
6821 if (!status) {
6822 out->offload_state = OFFLOAD_STATE_PLAYING;
6823 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306824 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006825 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6826 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006827 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08006828 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006829 pthread_mutex_unlock(&out->lock);
6830 }
6831 return status;
6832}
6833
6834static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
6835{
6836 struct stream_out *out = (struct stream_out *)stream;
6837 int status = -ENOSYS;
6838 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006839 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006840 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006841 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
6842 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
6843 else
6844 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
6845 pthread_mutex_unlock(&out->lock);
6846 }
6847 return status;
6848}
6849
6850static int out_flush(struct audio_stream_out* stream)
6851{
6852 struct stream_out *out = (struct stream_out *)stream;
6853 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006854 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006855 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006856 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006857 pthread_mutex_lock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006858 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
Gautam Manam14c198b2020-12-24 14:08:04 +05306859 pthread_mutex_unlock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006860 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006861 } else {
6862 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
Gautam Manam14c198b2020-12-24 14:08:04 +05306863 pthread_mutex_unlock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006864 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08006865 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006866 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006867 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006868 return 0;
6869 }
6870 return -ENOSYS;
6871}
6872
Haynes Mathew George16081042017-05-31 17:16:49 -07006873static int out_stop(const struct audio_stream_out* stream)
6874{
6875 struct stream_out *out = (struct stream_out *)stream;
6876 struct audio_device *adev = out->dev;
6877 int ret = -ENOSYS;
6878
6879 ALOGV("%s", __func__);
6880 pthread_mutex_lock(&adev->lock);
6881 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6882 out->playback_started && out->pcm != NULL) {
6883 pcm_stop(out->pcm);
6884 ret = stop_output_stream(out);
6885 out->playback_started = false;
6886 }
6887 pthread_mutex_unlock(&adev->lock);
6888 return ret;
6889}
6890
6891static int out_start(const struct audio_stream_out* stream)
6892{
6893 struct stream_out *out = (struct stream_out *)stream;
6894 struct audio_device *adev = out->dev;
6895 int ret = -ENOSYS;
6896
6897 ALOGV("%s", __func__);
6898 pthread_mutex_lock(&adev->lock);
6899 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6900 !out->playback_started && out->pcm != NULL) {
6901 ret = start_output_stream(out);
6902 if (ret == 0) {
6903 out->playback_started = true;
6904 }
6905 }
6906 pthread_mutex_unlock(&adev->lock);
6907 return ret;
6908}
6909
6910/*
6911 * Modify config->period_count based on min_size_frames
6912 */
6913static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
6914{
6915 int periodCountRequested = (min_size_frames + config->period_size - 1)
6916 / config->period_size;
6917 int periodCount = MMAP_PERIOD_COUNT_MIN;
6918
6919 ALOGV("%s original config.period_size = %d config.period_count = %d",
6920 __func__, config->period_size, config->period_count);
6921
6922 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
6923 periodCount *= 2;
6924 }
6925 config->period_count = periodCount;
6926
6927 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
6928}
6929
Phil Burkfe17efd2019-03-25 10:23:35 -07006930// Read offset for the positional timestamp from a persistent vendor property.
6931// This is to workaround apparent inaccuracies in the timing information that
6932// is used by the AAudio timing model. The inaccuracies can cause glitches.
6933static int64_t get_mmap_out_time_offset() {
6934 const int32_t kDefaultOffsetMicros = 0;
6935 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006936 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07006937 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
6938 return mmap_time_offset_micros * (int64_t)1000;
6939}
6940
Haynes Mathew George16081042017-05-31 17:16:49 -07006941static int out_create_mmap_buffer(const struct audio_stream_out *stream,
6942 int32_t min_size_frames,
6943 struct audio_mmap_buffer_info *info)
6944{
6945 struct stream_out *out = (struct stream_out *)stream;
6946 struct audio_device *adev = out->dev;
6947 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07006948 unsigned int offset1 = 0;
6949 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006950 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006951 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006952 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07006953
Arun Mirpuri5d170872019-03-26 13:21:31 -07006954 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306955 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07006956 pthread_mutex_lock(&adev->lock);
6957
Sharad Sanglec6f32552018-05-04 16:15:38 +05306958 if (CARD_STATUS_OFFLINE == out->card_status ||
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05006959 CARD_STATUS_OFFLINE == adev->card_status ||
6960 POWER_POLICY_STATUS_OFFLINE == adev->out_power_policy) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306961 ALOGW("out->card_status or adev->card_status offline, try again");
6962 ret = -EIO;
6963 goto exit;
6964 }
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306965 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07006966 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
6967 ret = -EINVAL;
6968 goto exit;
6969 }
6970 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
6971 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
6972 ret = -ENOSYS;
6973 goto exit;
6974 }
6975 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
6976 if (out->pcm_device_id < 0) {
6977 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6978 __func__, out->pcm_device_id, out->usecase);
6979 ret = -EINVAL;
6980 goto exit;
6981 }
6982
6983 adjust_mmap_period_count(&out->config, min_size_frames);
6984
Arun Mirpuri5d170872019-03-26 13:21:31 -07006985 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006986 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
6987 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
6988 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306989 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306990 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6991 out->card_status = CARD_STATUS_OFFLINE;
6992 adev->card_status = CARD_STATUS_OFFLINE;
6993 ret = -EIO;
6994 goto exit;
6995 }
6996
Haynes Mathew George16081042017-05-31 17:16:49 -07006997 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
6998 step = "open";
6999 ret = -ENODEV;
7000 goto exit;
7001 }
7002 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
7003 if (ret < 0) {
7004 step = "begin";
7005 goto exit;
7006 }
juyuchen626833d2019-06-04 16:48:02 +08007007
7008 info->flags = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007009 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07007010 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07007011 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07007012 ret = platform_get_mmap_data_fd(adev->platform,
7013 out->pcm_device_id, 0 /*playback*/,
7014 &info->shared_memory_fd,
7015 &mmap_size);
7016 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07007017 // Fall back to non exclusive mode
7018 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
7019 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07007020 out->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
7021 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, out->mmap_shared_memory_fd);
7022
Arun Mirpuri5d170872019-03-26 13:21:31 -07007023 if (mmap_size < buffer_size) {
7024 step = "mmap";
7025 goto exit;
7026 }
juyuchen626833d2019-06-04 16:48:02 +08007027 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07007028 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007029 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07007030 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07007031
7032 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
7033 if (ret < 0) {
7034 step = "commit";
7035 goto exit;
7036 }
7037
Phil Burkfe17efd2019-03-25 10:23:35 -07007038 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
7039
Haynes Mathew George16081042017-05-31 17:16:49 -07007040 out->standby = false;
7041 ret = 0;
7042
Arun Mirpuri5d170872019-03-26 13:21:31 -07007043 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07007044 __func__, info->shared_memory_address, info->buffer_size_frames);
7045
7046exit:
7047 if (ret != 0) {
7048 if (out->pcm == NULL) {
7049 ALOGE("%s: %s - %d", __func__, step, ret);
7050 } else {
7051 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
7052 pcm_close(out->pcm);
7053 out->pcm = NULL;
7054 }
7055 }
7056 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05307057 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07007058 return ret;
7059}
7060
7061static int out_get_mmap_position(const struct audio_stream_out *stream,
7062 struct audio_mmap_position *position)
7063{
7064 struct stream_out *out = (struct stream_out *)stream;
7065 ALOGVV("%s", __func__);
7066 if (position == NULL) {
7067 return -EINVAL;
7068 }
7069 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08007070 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07007071 return -ENOSYS;
7072 }
7073 if (out->pcm == NULL) {
7074 return -ENOSYS;
7075 }
7076
7077 struct timespec ts = { 0, 0 };
7078 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
7079 if (ret < 0) {
7080 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
7081 return ret;
7082 }
Phil Burkfe17efd2019-03-25 10:23:35 -07007083 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7084 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07007085 return 0;
7086}
7087
7088
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007089/** audio_stream_in implementation **/
7090static uint32_t in_get_sample_rate(const struct audio_stream *stream)
7091{
7092 struct stream_in *in = (struct stream_in *)stream;
7093
7094 return in->config.rate;
7095}
7096
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007097static int in_set_sample_rate(struct audio_stream *stream __unused,
7098 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007099{
7100 return -ENOSYS;
7101}
7102
7103static size_t in_get_buffer_size(const struct audio_stream *stream)
7104{
7105 struct stream_in *in = (struct stream_in *)stream;
7106
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007107 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
7108 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07007109 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
7110 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307111 else if(audio_extn_cin_attached_usecase(in))
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307112 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007113
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007114 return in->config.period_size * in->af_period_multiplier *
7115 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007116}
7117
7118static uint32_t in_get_channels(const struct audio_stream *stream)
7119{
7120 struct stream_in *in = (struct stream_in *)stream;
7121
7122 return in->channel_mask;
7123}
7124
7125static audio_format_t in_get_format(const struct audio_stream *stream)
7126{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007127 struct stream_in *in = (struct stream_in *)stream;
7128
7129 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007130}
7131
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007132static int in_set_format(struct audio_stream *stream __unused,
7133 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007134{
7135 return -ENOSYS;
7136}
7137
7138static int in_standby(struct audio_stream *stream)
7139{
7140 struct stream_in *in = (struct stream_in *)stream;
7141 struct audio_device *adev = in->dev;
7142 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307143 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
7144 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07007145 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307146
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007147 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007148 if (!in->standby && in->is_st_session) {
7149 ALOGD("%s: sound trigger pcm stop lab", __func__);
7150 audio_extn_sound_trigger_stop_lab(in);
George Gao3018ede2019-10-23 13:23:00 -07007151 if (adev->num_va_sessions > 0)
7152 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007153 in->standby = 1;
7154 }
7155
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007156 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007157 if (adev->adm_deregister_stream)
7158 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
7159
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08007160 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007161 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08007162 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08007163 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08007164 voice_extn_compress_voip_close_input_stream(stream);
7165 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07007166 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
7167 do_stop = in->capture_started;
7168 in->capture_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07007169 if (in->mmap_shared_memory_fd >= 0) {
7170 ALOGV("%s: closing mmap_shared_memory_fd = %d",
7171 __func__, in->mmap_shared_memory_fd);
7172 close(in->mmap_shared_memory_fd);
7173 in->mmap_shared_memory_fd = -1;
7174 }
Zhou Songa8895042016-07-05 17:54:22 +08007175 } else {
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307176 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05307177 audio_extn_cin_close_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08007178 }
7179
Arun Mirpuri5d170872019-03-26 13:21:31 -07007180 if (in->pcm) {
7181 ATRACE_BEGIN("pcm_in_close");
7182 pcm_close(in->pcm);
7183 ATRACE_END();
7184 in->pcm = NULL;
7185 }
7186
Carter Hsu2e429db2019-05-14 18:50:52 +08007187 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08007188 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08007189
George Gao3018ede2019-10-23 13:23:00 -07007190 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
7191 if (adev->num_va_sessions > 0)
7192 adev->num_va_sessions--;
7193 }
Quinn Malef6050362019-01-30 15:55:40 -08007194
Eric Laurent150dbfe2013-02-27 14:31:02 -08007195 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007196 }
7197 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07007198 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007199 return status;
7200}
7201
Aalique Grahame22e49102018-12-18 14:23:57 -08007202static int in_dump(const struct audio_stream *stream,
7203 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007204{
Aalique Grahame22e49102018-12-18 14:23:57 -08007205 struct stream_in *in = (struct stream_in *)stream;
7206
7207 // We try to get the lock for consistency,
7208 // but it isn't necessary for these variables.
7209 // If we're not in standby, we may be blocked on a read.
7210 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
7211 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
7212 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
7213 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
Dechen Chai22768452021-07-30 09:29:16 +05307214#ifndef LINUX_ENABLED
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007215 char buffer[256]; // for statistics formatting
7216 if (in->start_latency_ms.n > 0) {
7217 simple_stats_to_string(&in->start_latency_ms, buffer, sizeof(buffer));
7218 dprintf(fd, " Start latency ms: %s\n", buffer);
7219 }
Dechen Chai22768452021-07-30 09:29:16 +05307220#endif
Aalique Grahame22e49102018-12-18 14:23:57 -08007221 if (locked) {
7222 pthread_mutex_unlock(&in->lock);
7223 }
Dechen Chai22768452021-07-30 09:29:16 +05307224#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -08007225 // dump error info
7226 (void)error_log_dump(
7227 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Dechen Chai22768452021-07-30 09:29:16 +05307228#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007229 return 0;
7230}
7231
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307232static void in_snd_mon_cb(void * stream, struct str_parms * parms)
7233{
7234 if (!stream || !parms)
7235 return;
7236
7237 struct stream_in *in = (struct stream_in *)stream;
7238 struct audio_device *adev = in->dev;
7239
7240 card_status_t status;
7241 int card;
7242 if (parse_snd_card_status(parms, &card, &status) < 0)
7243 return;
7244
7245 pthread_mutex_lock(&adev->lock);
7246 bool valid_cb = (card == adev->snd_card);
7247 pthread_mutex_unlock(&adev->lock);
7248
7249 if (!valid_cb)
7250 return;
7251
7252 lock_input_stream(in);
7253 if (in->card_status != status)
7254 in->card_status = status;
7255 pthread_mutex_unlock(&in->lock);
7256
7257 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
7258 use_case_table[in->usecase],
7259 status == CARD_STATUS_OFFLINE ? "offline" : "online");
7260
7261 // a better solution would be to report error back to AF and let
7262 // it put the stream to standby
7263 if (status == CARD_STATUS_OFFLINE)
7264 in_standby(&in->stream.common);
7265
7266 return;
7267}
7268
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007269int route_input_stream(struct stream_in *in,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007270 struct listnode *devices,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007271 audio_source_t source)
7272{
7273 struct audio_device *adev = in->dev;
7274 int ret = 0;
7275
7276 lock_input_stream(in);
7277 pthread_mutex_lock(&adev->lock);
7278
7279 /* no audio source uses val == 0 */
7280 if ((in->source != source) && (source != AUDIO_SOURCE_DEFAULT)) {
7281 in->source = source;
7282 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
7283 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
7284 (voice_extn_compress_voip_is_format_supported(in->format)) &&
7285 (in->config.rate == 8000 || in->config.rate == 16000 ||
7286 in->config.rate == 32000 || in->config.rate == 48000 ) &&
7287 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
7288 ret = voice_extn_compress_voip_open_input_stream(in);
7289 if (ret != 0) {
7290 ALOGE("%s: Compress voip input cannot be opened, error:%d",
7291 __func__, ret);
7292 }
7293 }
7294 }
7295
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007296 if (!compare_devices(&in->device_list, devices) && !list_empty(devices) &&
7297 is_audio_in_device_type(devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007298 // Workaround: If routing to an non existing usb device, fail gracefully
7299 // The routing request will otherwise block during 10 second
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007300 struct str_parms *usb_addr =
7301 str_parms_create_str(get_usb_device_address(devices));
7302 if (is_usb_in_device_type(devices) && usb_addr &&
Weiyin Jiangabedea32020-12-09 12:49:19 +08007303 !audio_extn_usb_connected(NULL)) {
7304 ALOGW("%s: ignoring rerouting to non existing USB", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007305 ret = -ENOSYS;
7306 } else {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007307 /* If recording is in progress, change the tx device to new device */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007308 assign_devices(&in->device_list, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007309 if (!in->standby && !in->is_st_session) {
7310 ALOGV("update input routing change");
7311 // inform adm before actual routing to prevent glitches.
7312 if (adev->adm_on_routing_change) {
7313 adev->adm_on_routing_change(adev->adm_data,
7314 in->capture_handle);
7315 ret = select_devices(adev, in->usecase);
7316 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7317 adev->adm_routing_changed = true;
7318 }
7319 }
7320 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007321 if (usb_addr)
7322 str_parms_destroy(usb_addr);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007323 }
7324 pthread_mutex_unlock(&adev->lock);
7325 pthread_mutex_unlock(&in->lock);
7326
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07007327 ALOGV("%s: exit: status(%d)", __func__, ret);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007328 return ret;
7329}
7330
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007331static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
7332{
7333 struct stream_in *in = (struct stream_in *)stream;
7334 struct audio_device *adev = in->dev;
7335 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007336 char value[32];
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307337 int err = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007338
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307339 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007340 parms = str_parms_create_str(kvpairs);
7341
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307342 if (!parms)
7343 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007344 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08007345 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007346
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307347 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
7348 if (err >= 0) {
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307349 strlcpy(in->profile, value, sizeof(in->profile));
7350 ALOGV("updating stream profile with value '%s'", in->profile);
7351 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
7352 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007353 &in->device_list, in->flags, in->format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307354 in->sample_rate, in->bit_width,
7355 in->profile, &in->app_type_cfg);
7356 }
7357
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007358 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08007359 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007360
7361 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307362error:
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307363 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007364}
7365
7366static char* in_get_parameters(const struct audio_stream *stream,
7367 const char *keys)
7368{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007369 struct stream_in *in = (struct stream_in *)stream;
7370 struct str_parms *query = str_parms_create_str(keys);
7371 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007372 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007373
7374 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08007375 if (reply) {
7376 str_parms_destroy(reply);
7377 }
7378 if (query) {
7379 str_parms_destroy(query);
7380 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007381 ALOGE("in_get_parameters: failed to create query or reply");
7382 return NULL;
7383 }
7384
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007385 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007386
7387 voice_extn_in_get_parameters(in, query, reply);
7388
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007389 stream_get_parameter_channels(query, reply,
7390 &in->supported_channel_masks[0]);
7391 stream_get_parameter_formats(query, reply,
7392 &in->supported_formats[0]);
7393 stream_get_parameter_rates(query, reply,
7394 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007395 str = str_parms_to_str(reply);
7396 str_parms_destroy(query);
7397 str_parms_destroy(reply);
7398
7399 ALOGV("%s: exit: returns - %s", __func__, str);
7400 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007401}
7402
Aalique Grahame22e49102018-12-18 14:23:57 -08007403static int in_set_gain(struct audio_stream_in *stream,
7404 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007405{
Aalique Grahame22e49102018-12-18 14:23:57 -08007406 struct stream_in *in = (struct stream_in *)stream;
7407 char mixer_ctl_name[128];
7408 struct mixer_ctl *ctl;
7409 int ctl_value;
7410
7411 ALOGV("%s: gain %f", __func__, gain);
7412
7413 if (stream == NULL)
7414 return -EINVAL;
7415
7416 /* in_set_gain() only used to silence MMAP capture for now */
7417 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
7418 return -ENOSYS;
7419
7420 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
7421
7422 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
7423 if (!ctl) {
7424 ALOGW("%s: Could not get ctl for mixer cmd - %s",
7425 __func__, mixer_ctl_name);
7426 return -ENOSYS;
7427 }
7428
7429 if (gain < RECORD_GAIN_MIN)
7430 gain = RECORD_GAIN_MIN;
7431 else if (gain > RECORD_GAIN_MAX)
7432 gain = RECORD_GAIN_MAX;
7433 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
7434
7435 mixer_ctl_set_value(ctl, 0, ctl_value);
7436
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007437 return 0;
7438}
7439
7440static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
7441 size_t bytes)
7442{
7443 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05307444
7445 if (in == NULL) {
7446 ALOGE("%s: stream_in ptr is NULL", __func__);
7447 return -EINVAL;
7448 }
7449
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007450 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05307451 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307452 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007453
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007454 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05307455
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007456 if (in->is_st_session) {
7457 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
7458 /* Read from sound trigger HAL */
7459 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08007460 if (in->standby) {
George Gao3018ede2019-10-23 13:23:00 -07007461 if (adev->num_va_sessions < UINT_MAX)
7462 adev->num_va_sessions++;
Quinn Malef6050362019-01-30 15:55:40 -08007463 in->standby = 0;
7464 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007465 pthread_mutex_unlock(&in->lock);
7466 return bytes;
7467 }
7468
Haynes Mathew George16081042017-05-31 17:16:49 -07007469 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
7470 ret = -ENOSYS;
7471 goto exit;
7472 }
7473
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007474 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
7475 !in->standby && adev->adm_routing_changed) {
7476 ret = -ENOSYS;
7477 goto exit;
7478 }
7479
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007480 if (in->standby) {
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007481 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
7482
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007483 pthread_mutex_lock(&adev->lock);
7484 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
7485 ret = voice_extn_compress_voip_start_input_stream(in);
7486 else
7487 ret = start_input_stream(in);
George Gao3018ede2019-10-23 13:23:00 -07007488 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
7489 if (adev->num_va_sessions < UINT_MAX)
7490 adev->num_va_sessions++;
7491 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007492 pthread_mutex_unlock(&adev->lock);
7493 if (ret != 0) {
7494 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007495 }
7496 in->standby = 0;
Dechen Chai22768452021-07-30 09:29:16 +05307497#ifndef LINUX_ENABLED
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007498 // log startup time in ms.
7499 simple_stats_log(
7500 &in->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Dechen Chai22768452021-07-30 09:29:16 +05307501#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007502 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007503
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05307504 /* Avoid read if capture_stopped is set */
7505 if (android_atomic_acquire_load(&(in->capture_stopped)) > 0) {
7506 ALOGD("%s: force stopped catpure session, ignoring read request", __func__);
7507 ret = -EINVAL;
7508 goto exit;
7509 }
7510
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007511 // what's the duration requested by the client?
7512 long ns = 0;
7513
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307514 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007515 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
7516 in->config.rate;
7517
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007518 ret = request_in_focus(in, ns);
7519 if (ret != 0)
7520 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007521 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007522
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307523 if (audio_extn_cin_attached_usecase(in)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307524 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
7525 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307526 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007527 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307528 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07007529 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007530 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007531 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07007532 } else if (audio_extn_ffv_get_stream() == in) {
7533 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307534 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007535 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307536 /* data from DSP comes in 24_8 format, convert it to 8_24 */
7537 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
7538 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
7539 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307540 ret = -EINVAL;
7541 goto exit;
7542 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307543 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307544 ret = -errno;
7545 }
7546 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307547 /* bytes read is always set to bytes for non compress usecases */
7548 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007549 }
7550
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007551 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007552
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007553 /*
Quinn Malef6050362019-01-30 15:55:40 -08007554 * Instead of writing zeroes here, we could trust the hardware to always
7555 * provide zeroes when muted. This is also muted with voice recognition
7556 * usecases so that other clients do not have access to voice recognition
7557 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007558 */
Quinn Malef6050362019-01-30 15:55:40 -08007559 if ((ret == 0 && voice_get_mic_mute(adev) &&
7560 !voice_is_in_call_rec_stream(in) &&
Zhou Song62ea0282020-03-22 19:53:01 +08007561 (in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY &&
7562 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY2)) ||
Quinn Malef6050362019-01-30 15:55:40 -08007563 (adev->num_va_sessions &&
7564 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
7565 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
7566 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007567 memset(buffer, 0, bytes);
7568
7569exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307570 frame_size = audio_stream_in_frame_size(stream);
7571 if (frame_size > 0)
7572 in->frames_read += bytes_read/frame_size;
7573
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007574 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307575 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007576 pthread_mutex_unlock(&in->lock);
7577
7578 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307579 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307580 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307581 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307582 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307583 in->standby = true;
7584 }
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307585 if (!audio_extn_cin_attached_usecase(in)) {
Sharad Sangled17c9122017-03-20 15:58:52 +05307586 bytes_read = bytes;
7587 memset(buffer, 0, bytes);
7588 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007589 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007590 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7591 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007592 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05307593 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05307594 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007595 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307596 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007597}
7598
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007599static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007600{
7601 return 0;
7602}
7603
Aalique Grahame22e49102018-12-18 14:23:57 -08007604static int in_get_capture_position(const struct audio_stream_in *stream,
7605 int64_t *frames, int64_t *time)
7606{
7607 if (stream == NULL || frames == NULL || time == NULL) {
7608 return -EINVAL;
7609 }
7610 struct stream_in *in = (struct stream_in *)stream;
7611 int ret = -ENOSYS;
7612
7613 lock_input_stream(in);
7614 // note: ST sessions do not close the alsa pcm driver synchronously
7615 // on standby. Therefore, we may return an error even though the
7616 // pcm stream is still opened.
7617 if (in->standby) {
7618 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
7619 "%s stream in standby but pcm not NULL for non ST session", __func__);
7620 goto exit;
7621 }
7622 if (in->pcm) {
7623 struct timespec timestamp;
7624 unsigned int avail;
7625 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
7626 *frames = in->frames_read + avail;
Robert Lee58215542019-07-15 20:55:12 +08007627 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec
George Gao9ba8a142020-07-23 14:30:03 -07007628 - platform_capture_latency(in) * 1000LL;
Kakanaboina Ramanjaneyulu8cedb092021-03-15 15:55:29 +05307629 //Adjustment accounts for A2dp decoder latency for recording usecase
7630 // Note: decoder latency is returned in ms, while platform_capture_latency in ns.
7631 if (is_a2dp_in_device_type(&in->device_list))
7632 *time -= audio_extn_a2dp_get_decoder_latency() * 1000000LL;
Aalique Grahame22e49102018-12-18 14:23:57 -08007633 ret = 0;
7634 }
7635 }
7636exit:
7637 pthread_mutex_unlock(&in->lock);
7638 return ret;
7639}
7640
Carter Hsu2e429db2019-05-14 18:50:52 +08007641static int in_update_effect_list(bool add, effect_handle_t effect,
7642 struct listnode *head)
7643{
7644 struct listnode *node;
7645 struct in_effect_list *elist = NULL;
7646 struct in_effect_list *target = NULL;
7647 int ret = 0;
7648
7649 if (!head)
7650 return ret;
7651
7652 list_for_each(node, head) {
7653 elist = node_to_item(node, struct in_effect_list, list);
7654 if (elist->handle == effect) {
7655 target = elist;
7656 break;
7657 }
7658 }
7659
7660 if (add) {
7661 if (target) {
7662 ALOGD("effect %p already exist", effect);
7663 return ret;
7664 }
7665
7666 target = (struct in_effect_list *)
7667 calloc(1, sizeof(struct in_effect_list));
7668
7669 if (!target) {
7670 ALOGE("%s:fail to allocate memory", __func__);
7671 return -ENOMEM;
7672 }
7673
7674 target->handle = effect;
7675 list_add_tail(head, &target->list);
7676 } else {
7677 if (target) {
7678 list_remove(&target->list);
7679 free(target);
7680 }
7681 }
7682
7683 return ret;
7684}
7685
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007686static int add_remove_audio_effect(const struct audio_stream *stream,
7687 effect_handle_t effect,
7688 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007689{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007690 struct stream_in *in = (struct stream_in *)stream;
7691 int status = 0;
7692 effect_descriptor_t desc;
7693
7694 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007695 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
7696
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007697 if (status != 0)
7698 return status;
7699
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007700 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007701 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08007702 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08007703 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
7704 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007705 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08007706
7707 in_update_effect_list(enable, effect, &in->aec_list);
7708 enable = !list_empty(&in->aec_list);
7709 if (enable == in->enable_aec)
7710 goto exit;
7711
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007712 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007713 ALOGD("AEC enable %d", enable);
7714
Aalique Grahame22e49102018-12-18 14:23:57 -08007715 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7716 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
7717 in->dev->enable_voicerx = enable;
7718 struct audio_usecase *usecase;
7719 struct listnode *node;
7720 list_for_each(node, &in->dev->usecase_list) {
7721 usecase = node_to_item(node, struct audio_usecase, list);
7722 if (usecase->type == PCM_PLAYBACK)
7723 select_devices(in->dev, usecase->id);
7724 }
7725 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007726 if (!in->standby) {
7727 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
7728 select_devices(in->dev, in->usecase);
7729 }
7730
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007731 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007732 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
7733
7734 in_update_effect_list(enable, effect, &in->ns_list);
7735 enable = !list_empty(&in->ns_list);
7736 if (enable == in->enable_ns)
7737 goto exit;
7738
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007739 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007740 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007741 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08007742 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Ramu Gottipatifa5be522021-12-28 19:18:21 +05307743 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
kunleizd96526c2018-04-09 11:12:32 +08007744 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007745 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
7746 select_devices(in->dev, in->usecase);
7747 } else
7748 select_devices(in->dev, in->usecase);
7749 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007750 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007751exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007752 pthread_mutex_unlock(&in->dev->lock);
7753 pthread_mutex_unlock(&in->lock);
7754
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007755 return 0;
7756}
7757
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007758static int in_add_audio_effect(const struct audio_stream *stream,
7759 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007760{
Eric Laurent994a6932013-07-17 11:51:42 -07007761 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007762 return add_remove_audio_effect(stream, effect, true);
7763}
7764
7765static int in_remove_audio_effect(const struct audio_stream *stream,
7766 effect_handle_t effect)
7767{
Eric Laurent994a6932013-07-17 11:51:42 -07007768 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007769 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007770}
7771
Haynes Mathew George16081042017-05-31 17:16:49 -07007772static int in_stop(const struct audio_stream_in* stream)
7773{
7774 struct stream_in *in = (struct stream_in *)stream;
7775 struct audio_device *adev = in->dev;
7776
7777 int ret = -ENOSYS;
7778 ALOGV("%s", __func__);
7779 pthread_mutex_lock(&adev->lock);
7780 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7781 in->capture_started && in->pcm != NULL) {
7782 pcm_stop(in->pcm);
7783 ret = stop_input_stream(in);
7784 in->capture_started = false;
7785 }
7786 pthread_mutex_unlock(&adev->lock);
7787 return ret;
7788}
7789
7790static int in_start(const struct audio_stream_in* stream)
7791{
7792 struct stream_in *in = (struct stream_in *)stream;
7793 struct audio_device *adev = in->dev;
7794 int ret = -ENOSYS;
7795
7796 ALOGV("%s in %p", __func__, in);
7797 pthread_mutex_lock(&adev->lock);
7798 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7799 !in->capture_started && in->pcm != NULL) {
7800 if (!in->capture_started) {
7801 ret = start_input_stream(in);
7802 if (ret == 0) {
7803 in->capture_started = true;
7804 }
7805 }
7806 }
7807 pthread_mutex_unlock(&adev->lock);
7808 return ret;
7809}
7810
Phil Burke0a86d12019-02-16 22:28:11 -08007811// Read offset for the positional timestamp from a persistent vendor property.
7812// This is to workaround apparent inaccuracies in the timing information that
7813// is used by the AAudio timing model. The inaccuracies can cause glitches.
7814static int64_t in_get_mmap_time_offset() {
7815 const int32_t kDefaultOffsetMicros = 0;
7816 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08007817 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08007818 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
7819 return mmap_time_offset_micros * (int64_t)1000;
7820}
7821
Haynes Mathew George16081042017-05-31 17:16:49 -07007822static int in_create_mmap_buffer(const struct audio_stream_in *stream,
7823 int32_t min_size_frames,
7824 struct audio_mmap_buffer_info *info)
7825{
7826 struct stream_in *in = (struct stream_in *)stream;
7827 struct audio_device *adev = in->dev;
7828 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07007829 unsigned int offset1 = 0;
7830 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007831 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07007832 uint32_t mmap_size = 0;
7833 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007834
7835 pthread_mutex_lock(&adev->lock);
7836 ALOGV("%s in %p", __func__, in);
7837
Sharad Sanglec6f32552018-05-04 16:15:38 +05307838 if (CARD_STATUS_OFFLINE == in->card_status||
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05007839 CARD_STATUS_OFFLINE == adev->card_status ||
7840 POWER_POLICY_STATUS_OFFLINE == adev->in_power_policy) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307841 ALOGW("in->card_status or adev->card_status offline, try again");
7842 ret = -EIO;
7843 goto exit;
7844 }
7845
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307846 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07007847 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
7848 ret = -EINVAL;
7849 goto exit;
7850 }
7851 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
7852 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
7853 ALOGV("%s in %p", __func__, in);
7854 ret = -ENOSYS;
7855 goto exit;
7856 }
7857 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
7858 if (in->pcm_device_id < 0) {
7859 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
7860 __func__, in->pcm_device_id, in->usecase);
7861 ret = -EINVAL;
7862 goto exit;
7863 }
7864
7865 adjust_mmap_period_count(&in->config, min_size_frames);
7866
7867 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
7868 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
7869 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
7870 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307871 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307872 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7873 in->card_status = CARD_STATUS_OFFLINE;
7874 adev->card_status = CARD_STATUS_OFFLINE;
7875 ret = -EIO;
7876 goto exit;
7877 }
7878
Haynes Mathew George16081042017-05-31 17:16:49 -07007879 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
7880 step = "open";
7881 ret = -ENODEV;
7882 goto exit;
7883 }
7884
7885 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
7886 if (ret < 0) {
7887 step = "begin";
7888 goto exit;
7889 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007890
juyuchen626833d2019-06-04 16:48:02 +08007891 info->flags = 0;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007892 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
7893 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
7894 info->burst_size_frames = in->config.period_size;
7895 ret = platform_get_mmap_data_fd(adev->platform,
7896 in->pcm_device_id, 1 /*capture*/,
7897 &info->shared_memory_fd,
7898 &mmap_size);
7899 if (ret < 0) {
7900 // Fall back to non exclusive mode
7901 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
7902 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07007903 in->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
7904 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, in->mmap_shared_memory_fd);
7905
Arun Mirpuri5d170872019-03-26 13:21:31 -07007906 if (mmap_size < buffer_size) {
7907 step = "mmap";
7908 goto exit;
7909 }
juyuchen626833d2019-06-04 16:48:02 +08007910 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007911 }
7912
7913 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07007914
7915 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
7916 if (ret < 0) {
7917 step = "commit";
7918 goto exit;
7919 }
7920
Phil Burke0a86d12019-02-16 22:28:11 -08007921 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
7922
Haynes Mathew George16081042017-05-31 17:16:49 -07007923 in->standby = false;
7924 ret = 0;
7925
7926 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
7927 __func__, info->shared_memory_address, info->buffer_size_frames);
7928
7929exit:
7930 if (ret != 0) {
7931 if (in->pcm == NULL) {
7932 ALOGE("%s: %s - %d", __func__, step, ret);
7933 } else {
7934 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
7935 pcm_close(in->pcm);
7936 in->pcm = NULL;
7937 }
7938 }
7939 pthread_mutex_unlock(&adev->lock);
7940 return ret;
7941}
7942
7943static int in_get_mmap_position(const struct audio_stream_in *stream,
7944 struct audio_mmap_position *position)
7945{
7946 struct stream_in *in = (struct stream_in *)stream;
7947 ALOGVV("%s", __func__);
7948 if (position == NULL) {
7949 return -EINVAL;
7950 }
Gautam Manam34d1f542021-01-05 20:24:37 +05307951 lock_input_stream(in);
Haynes Mathew George16081042017-05-31 17:16:49 -07007952 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
Gautam Manam34d1f542021-01-05 20:24:37 +05307953 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07007954 return -ENOSYS;
7955 }
7956 if (in->pcm == NULL) {
Gautam Manam34d1f542021-01-05 20:24:37 +05307957 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07007958 return -ENOSYS;
7959 }
7960 struct timespec ts = { 0, 0 };
7961 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
7962 if (ret < 0) {
7963 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
Gautam Manam34d1f542021-01-05 20:24:37 +05307964 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07007965 return ret;
7966 }
Phil Burke0a86d12019-02-16 22:28:11 -08007967 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7968 + in->mmap_time_offset_nanos;
Gautam Manam34d1f542021-01-05 20:24:37 +05307969 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07007970 return 0;
7971}
7972
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307973static int in_get_active_microphones(const struct audio_stream_in *stream,
7974 struct audio_microphone_characteristic_t *mic_array,
7975 size_t *mic_count) {
7976 struct stream_in *in = (struct stream_in *)stream;
7977 struct audio_device *adev = in->dev;
7978 ALOGVV("%s", __func__);
7979
7980 lock_input_stream(in);
7981 pthread_mutex_lock(&adev->lock);
7982 int ret = platform_get_active_microphones(adev->platform,
7983 audio_channel_count_from_in_mask(in->channel_mask),
7984 in->usecase, mic_array, mic_count);
7985 pthread_mutex_unlock(&adev->lock);
7986 pthread_mutex_unlock(&in->lock);
7987
7988 return ret;
7989}
7990
7991static int adev_get_microphones(const struct audio_hw_device *dev,
7992 struct audio_microphone_characteristic_t *mic_array,
7993 size_t *mic_count) {
7994 struct audio_device *adev = (struct audio_device *)dev;
7995 ALOGVV("%s", __func__);
7996
7997 pthread_mutex_lock(&adev->lock);
7998 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
7999 pthread_mutex_unlock(&adev->lock);
8000
8001 return ret;
8002}
juyuchendb308c22019-01-21 11:57:17 -07008003
8004static void in_update_sink_metadata(struct audio_stream_in *stream,
8005 const struct sink_metadata *sink_metadata) {
8006
8007 if (stream == NULL
8008 || sink_metadata == NULL
8009 || sink_metadata->tracks == NULL) {
8010 return;
8011 }
8012
8013 int error = 0;
8014 struct stream_in *in = (struct stream_in *)stream;
8015 struct audio_device *adev = in->dev;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008016 struct listnode devices;
8017
8018 list_init(&devices);
juyuchendb308c22019-01-21 11:57:17 -07008019
8020 if (sink_metadata->track_count != 0)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008021 reassign_device_list(&devices, sink_metadata->tracks->dest_device, "");
juyuchendb308c22019-01-21 11:57:17 -07008022
8023 lock_input_stream(in);
8024 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008025 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, get_device_types(&devices));
juyuchendb308c22019-01-21 11:57:17 -07008026
Zhou Song503196b2021-07-23 17:31:05 +08008027 if ((in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY ||
8028 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2) &&
8029 !list_empty(&devices) &&
8030 adev->voice_tx_output != NULL) {
juyuchendb308c22019-01-21 11:57:17 -07008031 /* Use the rx device from afe-proxy record to route voice call because
8032 there is no routing if tx device is on primary hal and rx device
8033 is on other hal during voice call. */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008034 assign_devices(&adev->voice_tx_output->device_list, &devices);
juyuchendb308c22019-01-21 11:57:17 -07008035
8036 if (!voice_is_call_state_active(adev)) {
8037 if (adev->mode == AUDIO_MODE_IN_CALL) {
8038 adev->current_call_output = adev->voice_tx_output;
8039 error = voice_start_call(adev);
8040 if (error != 0)
8041 ALOGE("%s: start voice call failed %d", __func__, error);
8042 }
8043 } else {
8044 adev->current_call_output = adev->voice_tx_output;
8045 voice_update_devices_for_all_voice_usecases(adev);
8046 }
8047 }
8048
8049 pthread_mutex_unlock(&adev->lock);
8050 pthread_mutex_unlock(&in->lock);
8051}
8052
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308053int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07008054 audio_io_handle_t handle,
8055 audio_devices_t devices,
8056 audio_output_flags_t flags,
8057 struct audio_config *config,
8058 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04008059 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008060{
8061 struct audio_device *adev = (struct audio_device *)dev;
8062 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05308063 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008064 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008065 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05308066 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008067 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
8068 bool is_usb_dev = audio_is_usb_out_device(devices) &&
8069 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
8070 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008071 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07008072 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
8073 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008074 bool force_haptic_path =
8075 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07008076 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008077#ifdef AUDIO_GKI_ENABLED
8078 __s32 *generic_dec;
8079#endif
Weiyin Jiang906db3c2021-03-02 13:17:04 +08008080 pthread_mutexattr_t latch_attr;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008081
kunleizdff872d2018-08-20 14:40:33 +08008082 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08008083 is_usb_dev = false;
8084 devices = AUDIO_DEVICE_OUT_SPEAKER;
8085 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
8086 __func__, devices);
Mingshu Pangdbd20562019-11-25 18:04:39 +08008087 if (config->format == AUDIO_FORMAT_DEFAULT)
8088 config->format = AUDIO_FORMAT_PCM_16_BIT;
8089 if (config->sample_rate == 0)
8090 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8091 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8092 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
kunleizd6a9e0c2018-07-30 15:38:52 +08008093 }
8094
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008095 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05308096
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008097 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
8098
Mingming Yin3a941d42016-02-17 18:08:05 -08008099 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04008100 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
8101 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308102
8103
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008104 if (!out) {
8105 return -ENOMEM;
8106 }
8107
Haynes Mathew George204045b2015-02-25 20:32:03 -08008108 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07008109 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Weiyin Jiang906db3c2021-03-02 13:17:04 +08008110 pthread_mutexattr_init(&latch_attr);
8111 pthread_mutexattr_settype(&latch_attr, PTHREAD_MUTEX_RECURSIVE);
8112 pthread_mutex_init(&out->latch_lock, &latch_attr);
8113 pthread_mutexattr_destroy(&latch_attr);
Zhou Song48453a02018-01-10 17:50:59 +08008114 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08008115 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
8116
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008117 if (devices == AUDIO_DEVICE_NONE)
8118 devices = AUDIO_DEVICE_OUT_SPEAKER;
8119
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008120 out->flags = flags;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008121 list_init(&out->device_list);
8122 update_device_list(&out->device_list, devices, address, true /* add devices */);
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07008123 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07008124 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008125 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05308126 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05308127 if (out->channel_mask == AUDIO_CHANNEL_NONE)
8128 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
8129 else
8130 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07008131 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07008132 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08008133 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308134 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308135 out->started = 0;
Zhou Songbaddf9f2020-11-20 13:57:39 +08008136 out->a2dp_muted = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008137 out->hal_output_suspend_supported = 0;
8138 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05308139 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05308140 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05308141 out->pspd_coeff_sent = false;
Phil Burkd898ba62019-06-20 12:49:01 -07008142 out->mmap_shared_memory_fd = -1; // not open
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008143
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05308144 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05308145 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07008146 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
8147
Aalique Grahame22e49102018-12-18 14:23:57 -08008148 if (direct_dev &&
8149 (audio_is_linear_pcm(out->format) ||
8150 config->format == AUDIO_FORMAT_DEFAULT) &&
8151 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
8152 audio_format_t req_format = config->format;
8153 audio_channel_mask_t req_channel_mask = config->channel_mask;
8154 uint32_t req_sample_rate = config->sample_rate;
8155
8156 pthread_mutex_lock(&adev->lock);
8157 if (is_hdmi) {
8158 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
8159 ret = read_hdmi_sink_caps(out);
8160 if (config->sample_rate == 0)
8161 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8162 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8163 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
8164 if (config->format == AUDIO_FORMAT_DEFAULT)
8165 config->format = AUDIO_FORMAT_PCM_16_BIT;
8166 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008167 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
8168 &config->format,
8169 &out->supported_formats[0],
8170 MAX_SUPPORTED_FORMATS,
8171 &config->channel_mask,
8172 &out->supported_channel_masks[0],
8173 MAX_SUPPORTED_CHANNEL_MASKS,
8174 &config->sample_rate,
8175 &out->supported_sample_rates[0],
8176 MAX_SUPPORTED_SAMPLE_RATES);
8177 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008178 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008179
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008180 pthread_mutex_unlock(&adev->lock);
8181 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08008182 if (ret == -ENOSYS) {
8183 /* ignore and go with default */
8184 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08008185 }
8186 // For MMAP NO IRQ, allow conversions in ADSP
8187 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
8188 goto error_open;
8189 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008190 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08008191 goto error_open;
8192 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008193
8194 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
8195 config->sample_rate = req_sample_rate;
8196 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
8197 config->channel_mask = req_channel_mask;
8198 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
8199 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08008200 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008201
8202 out->sample_rate = config->sample_rate;
8203 out->channel_mask = config->channel_mask;
8204 out->format = config->format;
8205 if (is_hdmi) {
8206 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
8207 out->config = pcm_config_hdmi_multi;
8208 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8209 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8210 out->config = pcm_config_mmap_playback;
8211 out->stream.start = out_start;
8212 out->stream.stop = out_stop;
8213 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8214 out->stream.get_mmap_position = out_get_mmap_position;
8215 } else {
8216 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
8217 out->config = pcm_config_hifi;
8218 }
8219
8220 out->config.rate = out->sample_rate;
8221 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
8222 if (is_hdmi) {
8223 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
8224 audio_bytes_per_sample(out->format));
8225 }
8226 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08008227 }
8228
Derek Chenf6318be2017-06-12 17:16:24 -04008229 /* validate bus device address */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008230 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008231 /* extract car audio stream index */
8232 out->car_audio_stream =
8233 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
8234 if (out->car_audio_stream < 0) {
8235 ALOGE("%s: invalid car audio stream %x",
8236 __func__, out->car_audio_stream);
8237 ret = -EINVAL;
8238 goto error_open;
8239 }
Derek Chen5f67a942020-02-24 23:08:13 -08008240 ALOGV("%s: car_audio_stream %x", __func__, out->car_audio_stream);
Derek Chenf6318be2017-06-12 17:16:24 -04008241 }
8242
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008243 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07008244 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008245 if (!voice_extn_is_compress_voip_supported()) {
8246 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
8247 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07008248 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
Lakshman Chaluvarajue7fc9482020-05-30 14:29:29 +05308249 config->channel_mask : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008250 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
8251 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07008252 out->volume_l = INVALID_OUT_VOLUME;
8253 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07008254
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008255 out->config = default_pcm_config_voip_copp;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008256 out->config.rate = out->sample_rate;
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07008257 uint32_t channel_count =
8258 audio_channel_count_from_out_mask(out->channel_mask);
Ramjee Singh968858a2020-08-06 16:30:48 +05308259 out->config.channels = channel_count;
8260
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07008261 uint32_t buffer_size = get_stream_buffer_size(DEFAULT_VOIP_BUF_DURATION_MS,
8262 out->sample_rate, out->format,
8263 channel_count, false);
8264 uint32_t frame_size = audio_bytes_per_sample(out->format) * channel_count;
8265 if (frame_size != 0)
8266 out->config.period_size = buffer_size / frame_size;
8267 else
8268 ALOGW("%s: frame size is 0 for format %#x", __func__, out->format);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008269 }
8270 } else {
8271 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
8272 voice_extn_compress_voip_is_active(out->dev)) &&
8273 (voice_extn_compress_voip_is_config_supported(config))) {
8274 ret = voice_extn_compress_voip_open_output_stream(out);
8275 if (ret != 0) {
8276 ALOGE("%s: Compress voip output cannot be opened, error:%d",
8277 __func__, ret);
8278 goto error_open;
8279 }
Sujin Panicker19027262019-09-16 18:28:06 +05308280 } else {
8281 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8282 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008283 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008284 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008285 } else if (audio_is_linear_pcm(out->format) &&
8286 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
8287 out->channel_mask = config->channel_mask;
8288 out->sample_rate = config->sample_rate;
8289 out->format = config->format;
8290 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
8291 // does this change?
8292 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
8293 out->config.rate = config->sample_rate;
8294 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
8295 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
8296 audio_bytes_per_sample(config->format));
8297 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07008298 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308299 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308300 pthread_mutex_lock(&adev->lock);
8301 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
8302 pthread_mutex_unlock(&adev->lock);
8303
8304 // reject offload during card offline to allow
8305 // fallback to s/w paths
8306 if (offline) {
8307 ret = -ENODEV;
8308 goto error_open;
8309 }
vivek mehta0ea887a2015-08-26 14:01:20 -07008310
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008311 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
8312 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
8313 ALOGE("%s: Unsupported Offload information", __func__);
8314 ret = -EINVAL;
8315 goto error_open;
8316 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008317
Atul Khare3fa6e542017-08-09 00:56:17 +05308318 if (config->offload_info.format == 0)
8319 config->offload_info.format = config->format;
8320 if (config->offload_info.sample_rate == 0)
8321 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008322
Mingming Yin90310102013-11-13 16:57:00 -08008323 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308324 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07008325 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008326 ret = -EINVAL;
8327 goto error_open;
8328 }
8329
Ben Romberger0f8c87b2017-05-24 17:41:11 -07008330 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
8331 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
8332 (audio_extn_passthru_is_passthrough_stream(out)) &&
8333 !((config->sample_rate == 48000) ||
8334 (config->sample_rate == 96000) ||
8335 (config->sample_rate == 192000))) {
8336 ALOGE("%s: Unsupported sample rate %d for audio format %x",
8337 __func__, config->sample_rate, config->offload_info.format);
8338 ret = -EINVAL;
8339 goto error_open;
8340 }
8341
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008342 out->compr_config.codec = (struct snd_codec *)
8343 calloc(1, sizeof(struct snd_codec));
8344
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008345 if (!out->compr_config.codec) {
8346 ret = -ENOMEM;
8347 goto error_open;
8348 }
8349
Dhananjay Kumarac341582017-02-23 23:42:25 +05308350 out->stream.pause = out_pause;
8351 out->stream.resume = out_resume;
8352 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05308353 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05308354 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07008355 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05308356 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07008357 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05308358 } else {
8359 out->usecase = get_offload_usecase(adev, false /* is_compress */);
8360 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07008361 }
vivek mehta446c3962015-09-14 10:57:35 -07008362
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308363 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8364 ALOGD("%s: Setting latency mode to true", __func__);
Meng Wang4c32fb42020-01-16 17:57:11 +08008365#ifdef AUDIO_GKI_ENABLED
8366 /* out->compr_config.codec->reserved[1] is for flags */
8367 out->compr_config.codec->reserved[1] |= audio_extn_utils_get_perf_mode_flag();
8368#else
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308369 out->compr_config.codec->flags |= audio_extn_utils_get_perf_mode_flag();
Meng Wang4c32fb42020-01-16 17:57:11 +08008370#endif
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308371 }
8372
vivek mehta446c3962015-09-14 10:57:35 -07008373 if (out->usecase == USECASE_INVALID) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008374 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Mingming Yin3a941d42016-02-17 18:08:05 -08008375 config->format == 0 && config->sample_rate == 0 &&
8376 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07008377 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08008378 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
8379 } else {
8380 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
8381 ret = -EEXIST;
8382 goto error_open;
8383 }
vivek mehta446c3962015-09-14 10:57:35 -07008384 }
8385
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008386 if (config->offload_info.channel_mask)
8387 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008388 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008389 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008390 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008391 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05308392 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008393 ret = -EINVAL;
8394 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008395 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008396
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008397 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008398 out->sample_rate = config->offload_info.sample_rate;
8399
Mingming Yin3ee55c62014-08-04 14:23:35 -07008400 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008401
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308402 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05308403 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308404 audio_extn_dolby_send_ddp_endp_params(adev);
8405 audio_extn_dolby_set_dmid(adev);
8406 }
vivek mehta0ea887a2015-08-26 14:01:20 -07008407
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008408 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08008409 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008410 out->compr_config.codec->bit_rate =
8411 config->offload_info.bit_rate;
8412 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05308413 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008414 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05308415 /* Update bit width only for non passthrough usecases.
8416 * For passthrough usecases, the output will always be opened @16 bit
8417 */
8418 if (!audio_extn_passthru_is_passthrough_stream(out))
8419 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308420
8421 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
Meng Wang4c32fb42020-01-16 17:57:11 +08008422#ifdef AUDIO_GKI_ENABLED
8423 /* out->compr_config.codec->reserved[1] is for flags */
8424 out->compr_config.codec->reserved[1] |= COMPRESSED_TIMESTAMP_FLAG;
8425 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->reserved[1]);
8426#else
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308427 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
8428 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
Meng Wang4c32fb42020-01-16 17:57:11 +08008429#endif
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308430
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008431 /*TODO: Do we need to change it for passthrough */
8432 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008433
Manish Dewangana6fc5442015-08-24 20:30:31 +05308434 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
8435 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308436 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05308437 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308438 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
8439 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308440
8441 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
8442 AUDIO_FORMAT_PCM) {
8443
8444 /*Based on platform support, configure appropriate alsa format for corresponding
8445 *hal input format.
8446 */
8447 out->compr_config.codec->format = hal_format_to_alsa(
8448 config->offload_info.format);
8449
Ashish Jain83a6cc22016-06-28 14:34:17 +05308450 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05308451 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308452 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308453
Dhananjay Kumarac341582017-02-23 23:42:25 +05308454 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05308455 *hal input format and alsa format might differ based on platform support.
8456 */
8457 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05308458 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308459
8460 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
8461
Deeraj Soman93155a62019-09-30 19:00:37 +05308462 if (property_get_bool("vendor.audio.offload.buffer.duration.enabled", false)) {
8463 if ((config->offload_info.duration_us >= MIN_OFFLOAD_BUFFER_DURATION_MS * 1000) &&
8464 (config->offload_info.duration_us <= MAX_OFFLOAD_BUFFER_DURATION_MS * 1000))
8465 out->info.duration_us = (int64_t)config->offload_info.duration_us;
8466 }
Deeraj Soman65358ab2019-02-07 15:40:49 +05308467
Ashish Jainf1eaa582016-05-23 20:54:24 +05308468 /* Check if alsa session is configured with the same format as HAL input format,
8469 * if not then derive correct fragment size needed to accomodate the
8470 * conversion of HAL input format to alsa format.
8471 */
8472 audio_extn_utils_update_direct_pcm_fragment_size(out);
8473
8474 /*if hal input and output fragment size is different this indicates HAL input format is
8475 *not same as the alsa format
8476 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308477 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05308478 /*Allocate a buffer to convert input data to the alsa configured format.
8479 *size of convert buffer is equal to the size required to hold one fragment size
8480 *worth of pcm data, this is because flinger does not write more than fragment_size
8481 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308482 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
8483 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05308484 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
8485 ret = -ENOMEM;
8486 goto error_open;
8487 }
8488 }
8489 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
8490 out->compr_config.fragment_size =
8491 audio_extn_passthru_get_buffer_size(&config->offload_info);
8492 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8493 } else {
8494 out->compr_config.fragment_size =
8495 platform_get_compress_offload_buffer_size(&config->offload_info);
8496 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8497 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008498
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308499 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8500 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
8501 }
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008502 if (config->offload_info.format == AUDIO_FORMAT_FLAC) {
8503#ifdef AUDIO_GKI_ENABLED
8504 generic_dec =
8505 &(out->compr_config.codec->options.generic.reserved[1]);
8506 ((struct snd_generic_dec_flac *)generic_dec)->sample_size =
8507 AUDIO_OUTPUT_BIT_WIDTH;
8508#else
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05308509 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008510#endif
8511 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008512
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05308513 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
8514 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
8515 }
8516
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008517 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
8518 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008519
Manish Dewangan69426c82017-01-30 17:35:36 +05308520 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
8521 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
8522 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
8523 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8524 out->render_mode = RENDER_MODE_AUDIO_MASTER;
8525 } else {
8526 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
8527 }
Alexy Josephaa54c872014-12-03 02:46:47 -08008528
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05308529 memset(&out->channel_map_param, 0,
8530 sizeof(struct audio_out_channel_map_param));
8531
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008532 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05308533 out->send_next_track_params = false;
8534 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008535 out->offload_state = OFFLOAD_STATE_IDLE;
8536 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08008537 out->writeAt.tv_sec = 0;
8538 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008539
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008540 audio_extn_dts_create_state_notifier_node(out->usecase);
8541
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008542 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
8543 __func__, config->offload_info.version,
8544 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05308545
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308546 /* Check if DSD audio format is supported in codec
8547 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308548 */
8549
8550 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308551 (!platform_check_codec_dsd_support(adev->platform) ||
8552 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308553 ret = -EINVAL;
8554 goto error_open;
8555 }
8556
Ashish Jain5106d362016-05-11 19:23:33 +05308557 /* Disable gapless if any of the following is true
8558 * passthrough playback
8559 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05308560 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05308561 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308562 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308563 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07008564 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308565 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308566 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05308567 check_and_set_gapless_mode(adev, false);
8568 } else
8569 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07008570
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308571 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07008572 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
8573 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308574 if (config->format == AUDIO_FORMAT_DSD) {
8575 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
Meng Wang4c32fb42020-01-16 17:57:11 +08008576#ifdef AUDIO_GKI_ENABLED
8577 /* out->compr_config.codec->reserved[0] is for compr_passthr */
8578 out->compr_config.codec->reserved[0] = PASSTHROUGH_DSD;
8579#else
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308580 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
Meng Wang4c32fb42020-01-16 17:57:11 +08008581#endif
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308582 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07008583
8584 create_offload_callback_thread(out);
8585
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008586 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008587 switch (config->sample_rate) {
8588 case 0:
8589 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8590 break;
8591 case 8000:
8592 case 16000:
8593 case 48000:
8594 out->sample_rate = config->sample_rate;
8595 break;
8596 default:
8597 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
8598 config->sample_rate);
8599 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8600 ret = -EINVAL;
8601 goto error_open;
8602 }
8603 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8604 switch (config->channel_mask) {
8605 case AUDIO_CHANNEL_NONE:
8606 case AUDIO_CHANNEL_OUT_STEREO:
8607 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8608 break;
8609 default:
8610 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
8611 config->channel_mask);
8612 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8613 ret = -EINVAL;
8614 goto error_open;
8615 }
8616 switch (config->format) {
8617 case AUDIO_FORMAT_DEFAULT:
8618 case AUDIO_FORMAT_PCM_16_BIT:
8619 out->format = AUDIO_FORMAT_PCM_16_BIT;
8620 break;
8621 default:
8622 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
8623 config->format);
8624 config->format = AUDIO_FORMAT_PCM_16_BIT;
8625 ret = -EINVAL;
8626 goto error_open;
8627 }
8628
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05308629 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008630 if (ret != 0) {
8631 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008632 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008633 goto error_open;
8634 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008635 } else if (is_single_device_type_equal(&out->device_list,
8636 AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08008637 switch (config->sample_rate) {
8638 case 0:
8639 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
8640 break;
8641 case 8000:
8642 case 16000:
8643 case 48000:
8644 out->sample_rate = config->sample_rate;
8645 break;
8646 default:
8647 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
8648 config->sample_rate);
8649 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8650 ret = -EINVAL;
8651 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008652 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008653 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8654 switch (config->channel_mask) {
8655 case AUDIO_CHANNEL_NONE:
8656 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8657 break;
8658 case AUDIO_CHANNEL_OUT_STEREO:
8659 out->channel_mask = config->channel_mask;
8660 break;
8661 default:
8662 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
8663 config->channel_mask);
8664 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8665 ret = -EINVAL;
8666 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008667 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008668 switch (config->format) {
8669 case AUDIO_FORMAT_DEFAULT:
8670 out->format = AUDIO_FORMAT_PCM_16_BIT;
8671 break;
8672 case AUDIO_FORMAT_PCM_16_BIT:
8673 out->format = config->format;
8674 break;
8675 default:
8676 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
8677 config->format);
8678 config->format = AUDIO_FORMAT_PCM_16_BIT;
8679 ret = -EINVAL;
8680 break;
8681 }
8682 if (ret != 0)
8683 goto error_open;
8684
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008685 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
8686 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08008687 out->config.rate = out->sample_rate;
8688 out->config.channels =
8689 audio_channel_count_from_out_mask(out->channel_mask);
8690 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008691 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008692 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05308693 unsigned int channels = 0;
8694 /*Update config params to default if not set by the caller*/
8695 if (config->sample_rate == 0)
8696 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8697 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8698 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8699 if (config->format == AUDIO_FORMAT_DEFAULT)
8700 config->format = AUDIO_FORMAT_PCM_16_BIT;
8701
8702 channels = audio_channel_count_from_out_mask(out->channel_mask);
8703
Varun Balaraje49253e2017-07-06 19:48:56 +05308704 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
8705 out->usecase = get_interactive_usecase(adev);
8706 out->config = pcm_config_low_latency;
8707 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05308708 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008709 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
8710 out->flags);
8711 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07008712 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8713 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8714 out->config = pcm_config_mmap_playback;
8715 out->stream.start = out_start;
8716 out->stream.stop = out_stop;
8717 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8718 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308719 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8720 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008721 out->hal_output_suspend_supported =
8722 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
8723 out->dynamic_pm_qos_config_supported =
8724 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
8725 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08008726 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
8727 } else {
8728 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
8729 //the mixer path will be a string similar to "low-latency-playback resume"
8730 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
8731 strlcat(out->pm_qos_mixer_path,
8732 " resume", MAX_MIXER_PATH_LEN);
8733 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
8734 out->pm_qos_mixer_path);
8735 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308736 out->config = pcm_config_low_latency;
8737 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
8738 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
8739 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05308740 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
8741 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
8742 if (out->config.period_size <= 0) {
8743 ALOGE("Invalid configuration period size is not valid");
8744 ret = -EINVAL;
8745 goto error_open;
8746 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008747 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
8748 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
8749 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008750 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
8751 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
8752 out->config = pcm_config_haptics_audio;
8753 if (force_haptic_path)
8754 adev->haptics_config = pcm_config_haptics_audio;
8755 else
8756 adev->haptics_config = pcm_config_haptics;
8757
Meng Wangd08ce322020-04-02 08:59:20 +08008758 channels =
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008759 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
8760
8761 if (force_haptic_path) {
8762 out->config.channels = 1;
8763 adev->haptics_config.channels = 1;
8764 } else
8765 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 -08008766 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008767 ret = audio_extn_auto_hal_open_output_stream(out);
8768 if (ret) {
8769 ALOGE("%s: Failed to open output stream for bus device", __func__);
8770 ret = -EINVAL;
8771 goto error_open;
8772 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308773 } else {
8774 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008775 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8776 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308777 }
8778 out->hal_ip_format = format = out->format;
8779 out->config.format = hal_format_to_pcm(out->hal_ip_format);
8780 out->hal_op_format = pcm_format_to_hal(out->config.format);
8781 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
8782 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008783 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05308784 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308785 if (out->hal_ip_format != out->hal_op_format) {
8786 uint32_t buffer_size = out->config.period_size *
8787 format_to_bitwidth_table[out->hal_op_format] *
8788 out->config.channels;
8789 out->convert_buffer = calloc(1, buffer_size);
8790 if (out->convert_buffer == NULL){
8791 ALOGE("Allocation failed for convert buffer for size %d",
8792 out->compr_config.fragment_size);
8793 ret = -ENOMEM;
8794 goto error_open;
8795 }
8796 ALOGD("Convert buffer allocated of size %d", buffer_size);
8797 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008798 }
8799
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008800 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
8801 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308802
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008803 /* TODO remove this hardcoding and check why width is zero*/
8804 if (out->bit_width == 0)
8805 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308806 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008807 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008808 &out->device_list, out->flags,
8809 out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05308810 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05308811 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08008812 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08008813 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
8814 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008815 if(adev->primary_output == NULL)
8816 adev->primary_output = out;
8817 else {
8818 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008819 ret = -EEXIST;
8820 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008821 }
8822 }
8823
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008824 /* Check if this usecase is already existing */
8825 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07008826 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
8827 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008828 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008829 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008830 ret = -EEXIST;
8831 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008832 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008833
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008834 pthread_mutex_unlock(&adev->lock);
8835
8836 out->stream.common.get_sample_rate = out_get_sample_rate;
8837 out->stream.common.set_sample_rate = out_set_sample_rate;
8838 out->stream.common.get_buffer_size = out_get_buffer_size;
8839 out->stream.common.get_channels = out_get_channels;
8840 out->stream.common.get_format = out_get_format;
8841 out->stream.common.set_format = out_set_format;
8842 out->stream.common.standby = out_standby;
8843 out->stream.common.dump = out_dump;
8844 out->stream.common.set_parameters = out_set_parameters;
8845 out->stream.common.get_parameters = out_get_parameters;
8846 out->stream.common.add_audio_effect = out_add_audio_effect;
8847 out->stream.common.remove_audio_effect = out_remove_audio_effect;
8848 out->stream.get_latency = out_get_latency;
8849 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08008850#ifdef NO_AUDIO_OUT
8851 out->stream.write = out_write_for_no_output;
8852#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008853 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08008854#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008855 out->stream.get_render_position = out_get_render_position;
8856 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008857 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008858
Haynes Mathew George16081042017-05-31 17:16:49 -07008859 if (out->realtime)
8860 out->af_period_multiplier = af_period_multiplier;
8861 else
8862 out->af_period_multiplier = 1;
8863
Andy Hunga1f48fa2019-07-01 18:14:53 -07008864 out->kernel_buffer_size = out->config.period_size * out->config.period_count;
8865
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008866 out->standby = 1;
Zhou Songbaddf9f2020-11-20 13:57:39 +08008867 out->volume_l = PLAYBACK_GAIN_MAX;
8868 out->volume_r = PLAYBACK_GAIN_MAX;
Eric Laurenta9024de2013-04-04 09:19:12 -07008869 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008870 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008871
8872 config->format = out->stream.common.get_format(&out->stream.common);
8873 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
8874 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308875 register_format(out->format, out->supported_formats);
8876 register_channel_mask(out->channel_mask, out->supported_channel_masks);
8877 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008878
Dechen Chai22768452021-07-30 09:29:16 +05308879#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -08008880 out->error_log = error_log_create(
8881 ERROR_LOG_ENTRIES,
8882 1000000000 /* aggregate consecutive identical errors within one second in ns */);
Dechen Chai22768452021-07-30 09:29:16 +05308883#endif
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308884 /*
8885 By locking output stream before registering, we allow the callback
8886 to update stream's state only after stream's initial state is set to
8887 adev state.
8888 */
8889 lock_output_stream(out);
8890 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
8891 pthread_mutex_lock(&adev->lock);
8892 out->card_status = adev->card_status;
8893 pthread_mutex_unlock(&adev->lock);
8894 pthread_mutex_unlock(&out->lock);
8895
Aalique Grahame22e49102018-12-18 14:23:57 -08008896 stream_app_type_cfg_init(&out->app_type_cfg);
8897
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008898 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308899 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07008900 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008901
8902 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
8903 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
8904 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008905 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05308906 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008907 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07008908 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05308909 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
8910 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008911 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
8912 out->usecase, PCM_PLAYBACK);
8913 hdlr_stream_cfg.flags = out->flags;
8914 hdlr_stream_cfg.type = PCM_PLAYBACK;
8915 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
8916 &hdlr_stream_cfg);
8917 if (ret) {
8918 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
8919 out->adsp_hdlr_stream_handle = NULL;
8920 }
8921 }
Gangadhar Sb0210342019-02-22 17:39:41 +05308922 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
8923 is_direct_passthough, false);
8924 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
8925 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07008926 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07008927 if (ret < 0) {
8928 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
8929 out->ip_hdlr_handle = NULL;
8930 }
8931 }
Derek Chenf939fb72018-11-13 13:34:41 -08008932
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008933 ret = io_streams_map_insert(adev, &out->stream.common,
8934 out->handle, AUDIO_PATCH_HANDLE_NONE);
8935 if (ret != 0)
8936 goto error_open;
8937
Susan Wang6dd13092021-01-25 10:27:11 -05008938 out->out_ctxt.output = out;
Derek Chenf939fb72018-11-13 13:34:41 -08008939
8940 pthread_mutex_lock(&adev->lock);
Susan Wang6dd13092021-01-25 10:27:11 -05008941 list_add_tail(&adev->active_outputs_list, &out->out_ctxt.list);
Derek Chenf939fb72018-11-13 13:34:41 -08008942 pthread_mutex_unlock(&adev->lock);
8943
Eric Laurent994a6932013-07-17 11:51:42 -07008944 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008945 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008946
8947error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05308948 if (out->convert_buffer)
8949 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008950 free(out);
8951 *stream_out = NULL;
8952 ALOGD("%s: exit: ret %d", __func__, ret);
8953 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008954}
8955
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308956void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008957 struct audio_stream_out *stream)
8958{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008959 struct stream_out *out = (struct stream_out *)stream;
8960 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008961 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008962
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008963 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308964
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008965 io_streams_map_remove(adev, out->handle);
8966
Susan Wang6dd13092021-01-25 10:27:11 -05008967 // remove out_ctxt early to prevent the stream
8968 // being opened in a race condition
8969 pthread_mutex_lock(&adev->lock);
8970 list_remove(&out->out_ctxt.list);
8971 pthread_mutex_unlock(&adev->lock);
8972
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308973 // must deregister from sndmonitor first to prevent races
8974 // between the callback and close_stream
8975 audio_extn_snd_mon_unregister_listener(out);
8976
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008977 /* close adsp hdrl session before standby */
8978 if (out->adsp_hdlr_stream_handle) {
8979 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
8980 if (ret)
8981 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
8982 out->adsp_hdlr_stream_handle = NULL;
8983 }
8984
Manish Dewangan21a850a2017-08-14 12:03:55 +05308985 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07008986 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
8987 out->ip_hdlr_handle = NULL;
8988 }
8989
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008990 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308991 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008992 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308993 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308994 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008995 if(ret != 0)
8996 ALOGE("%s: Compress voip output cannot be closed, error:%d",
8997 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008998 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008999 out_standby(&stream->common);
9000
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07009001 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08009002 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07009003 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07009004 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07009005 if (out->compr_config.codec != NULL)
9006 free(out->compr_config.codec);
9007 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009008
Zhou Songbaddf9f2020-11-20 13:57:39 +08009009 out->a2dp_muted = false;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05309010
Varun Balaraje49253e2017-07-06 19:48:56 +05309011 if (is_interactive_usecase(out->usecase))
9012 free_interactive_usecase(adev, out->usecase);
9013
Ashish Jain83a6cc22016-06-28 14:34:17 +05309014 if (out->convert_buffer != NULL) {
9015 free(out->convert_buffer);
9016 out->convert_buffer = NULL;
9017 }
9018
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009019 if (adev->voice_tx_output == out)
9020 adev->voice_tx_output = NULL;
9021
Dechen Chai22768452021-07-30 09:29:16 +05309022#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -08009023 error_log_destroy(out->error_log);
9024 out->error_log = NULL;
Dechen Chai22768452021-07-30 09:29:16 +05309025#endif
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05309026 if (adev->primary_output == out)
9027 adev->primary_output = NULL;
9028
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07009029 pthread_cond_destroy(&out->cond);
9030 pthread_mutex_destroy(&out->lock);
Weiyin Jiang280ea742020-09-08 20:28:22 +08009031 pthread_mutex_destroy(&out->pre_lock);
9032 pthread_mutex_destroy(&out->latch_lock);
9033 pthread_mutex_destroy(&out->position_query_lock);
Derek Chenf939fb72018-11-13 13:34:41 -08009034
9035 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009036 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08009037 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07009038 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009039}
9040
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05009041void in_set_power_policy(uint8_t enable)
9042{
9043 struct listnode *node;
9044
9045 ALOGD("%s: Enter, state %d", __func__, enable);
9046
9047 pthread_mutex_lock(&adev->lock);
9048 adev->in_power_policy = enable ? POWER_POLICY_STATUS_ONLINE : POWER_POLICY_STATUS_OFFLINE;
9049 pthread_mutex_unlock(&adev->lock);
9050
9051 if (!enable) {
9052 list_for_each(node, &adev->active_inputs_list) {
9053 streams_input_ctxt_t *in_ctxt = node_to_item(node,
9054 streams_input_ctxt_t,
9055 list);
9056 struct stream_in *in = in_ctxt->input;
9057 in_standby(&in->stream.common);
9058 }
9059 }
9060
9061 ALOGD("%s: Exit", __func__);
9062}
9063
9064void out_set_power_policy(uint8_t enable)
9065{
9066 struct listnode *node;
9067
9068 ALOGD("%s: Enter, state %d", __func__, enable);
9069
9070 pthread_mutex_lock(&adev->lock);
E V Ravi317be872022-02-23 19:08:15 +05309071 adev->out_power_policy = enable ? POWER_POLICY_STATUS_ONLINE : POWER_POLICY_STATUS_OFFLINE;
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -05009072 pthread_mutex_unlock(&adev->lock);
9073
9074 if (!enable) {
9075 list_for_each(node, &adev->active_outputs_list) {
9076 streams_output_ctxt_t *out_ctxt = node_to_item(node,
9077 streams_output_ctxt_t,
9078 list);
9079 struct stream_out *out = out_ctxt->output;
9080 out_on_error(&out->stream.common);
9081 }
9082 }
9083
9084 ALOGD("%s: Exit", __func__);
9085}
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009086static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
9087{
9088 struct audio_device *adev = (struct audio_device *)dev;
9089 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009090 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07009091 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009092 int ret;
9093 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08009094 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08009095 struct listnode *node;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07009096 int controller = -1, stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009097
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009098 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009099 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009100
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05309101 if (!parms)
9102 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05309103
Derek Chen6f293672019-04-01 01:40:24 -07009104 /* notify adev and input/output streams on the snd card status */
9105 adev_snd_mon_cb((void *)adev, parms);
9106
Weiyin Jiang24f55292020-12-22 14:35:46 +08009107 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
9108 if (ret >= 0) {
9109 list_for_each(node, &adev->active_outputs_list) {
9110 streams_output_ctxt_t *out_ctxt = node_to_item(node,
9111 streams_output_ctxt_t,
9112 list);
9113 out_snd_mon_cb((void *)out_ctxt->output, parms);
9114 }
Derek Chen6f293672019-04-01 01:40:24 -07009115
Weiyin Jiang24f55292020-12-22 14:35:46 +08009116 list_for_each(node, &adev->active_inputs_list) {
9117 streams_input_ctxt_t *in_ctxt = node_to_item(node,
9118 streams_input_ctxt_t,
9119 list);
9120 in_snd_mon_cb((void *)in_ctxt->input, parms);
9121 }
Derek Chen6f293672019-04-01 01:40:24 -07009122 }
9123
Zhou Songd6d71752019-05-21 18:08:51 +08009124 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05309125 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
9126 if (ret >= 0) {
9127 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08009128 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05309129 adev->bt_sco_on = true;
Shalini Manjunatha3a2e06e2021-02-01 12:23:49 +05309130 /*
9131 * When ever BT_SCO=ON arrives, make sure to route
9132 * all use cases to SCO device, otherwise due to delay in
9133 * BT_SCO=ON and lack of synchronization with create audio patch
9134 * request for SCO device, some times use case not routed properly to
9135 * SCO device
9136 */
9137 struct audio_usecase *usecase;
9138 struct listnode *node;
9139 list_for_each(node, &adev->usecase_list) {
9140 usecase = node_to_item(node, struct audio_usecase, list);
Anver sadhiquef0efca32021-09-03 15:25:44 +05309141 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
Anver sadhique93f3c912021-08-11 11:19:45 +05309142 (!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 +05309143 ALOGD("BT_SCO ON, switch all in use case to it");
9144 select_devices(adev, usecase->id);
9145 }
Mingshu Pangef517202021-04-22 10:35:00 +08009146 if (usecase->stream.out && (usecase->type == PCM_PLAYBACK ||
9147 usecase->type == VOICE_CALL) &&
Anver sadhique93f3c912021-08-11 11:19:45 +05309148 (!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 +05309149 ALOGD("BT_SCO ON, switch all out use case to it");
9150 select_devices(adev, usecase->id);
9151 }
9152 }
9153 }
9154 else {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05309155 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08009156 audio_extn_sco_reset_configuration();
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08009157 }
9158 }
9159
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009160 status = voice_set_parameters(adev, parms);
9161 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08009162 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009163
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009164 status = platform_set_parameters(adev->platform, parms);
9165 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08009166 goto done;
9167
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009168 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
9169 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07009170 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009171 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
9172 adev->bluetooth_nrec = true;
9173 else
9174 adev->bluetooth_nrec = false;
9175 }
9176
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009177 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
9178 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009179 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
9180 adev->screen_off = false;
9181 else
9182 adev->screen_off = true;
Quinn Male70f20f32019-06-26 16:50:26 -07009183 audio_extn_sound_trigger_update_screen_status(adev->screen_off);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009184 }
9185
Eric Laurent4b084132018-10-19 17:33:43 -07009186 ret = str_parms_get_int(parms, "rotation", &val);
9187 if (ret >= 0) {
9188 bool reverse_speakers = false;
9189 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
9190 switch (val) {
9191 // FIXME: note that the code below assumes that the speakers are in the correct placement
9192 // relative to the user when the device is rotated 90deg from its default rotation. This
9193 // assumption is device-specific, not platform-specific like this code.
9194 case 270:
9195 reverse_speakers = true;
9196 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
9197 break;
9198 case 0:
9199 case 180:
9200 camera_rotation = CAMERA_ROTATION_PORTRAIT;
9201 break;
9202 case 90:
9203 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
9204 break;
9205 default:
9206 ALOGE("%s: unexpected rotation of %d", __func__, val);
9207 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07009208 }
Eric Laurent4b084132018-10-19 17:33:43 -07009209 if (status == 0) {
9210 // check and set swap
9211 // - check if orientation changed and speaker active
9212 // - set rotation and cache the rotation value
9213 adev->camera_orientation =
9214 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
9215 if (!audio_extn_is_maxx_audio_enabled())
9216 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
9217 }
9218 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07009219
Mingming Yin514a8bc2014-07-29 15:22:21 -07009220 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
9221 if (ret >= 0) {
9222 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
9223 adev->bt_wb_speech_enabled = true;
9224 else
9225 adev->bt_wb_speech_enabled = false;
9226 }
9227
Zhou Song12c29502019-03-16 10:37:18 +08009228 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
9229 if (ret >= 0) {
9230 val = atoi(value);
9231 adev->swb_speech_mode = val;
9232 }
9233
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07009234 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
9235 if (ret >= 0) {
9236 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309237 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08009238 if (audio_is_output_device(val) &&
9239 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07009240 ALOGV("cache new ext disp type and edid");
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07009241 platform_get_controller_stream_from_params(parms, &controller, &stream);
9242 platform_set_ext_display_device_v2(adev->platform, controller, stream);
9243 ret = platform_get_ext_disp_type_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07009244 if (ret < 0) {
9245 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05309246 } else {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07009247 platform_cache_edid_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07009248 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309249 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07009250 /*
9251 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
9252 * Per AudioPolicyManager, USB device is higher priority than WFD.
9253 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
9254 * If WFD use case occupies AFE proxy, it may result unintended behavior while
9255 * starting voice call on USB
9256 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08009257 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309258 if (ret >= 0)
9259 audio_extn_usb_add_device(device, atoi(value));
9260
Zhou Song6f862822017-11-06 17:27:57 +08009261 if (!audio_extn_usb_is_tunnel_supported()) {
9262 ALOGV("detected USB connect .. disable proxy");
9263 adev->allow_afe_proxy_usage = false;
9264 }
Zhou Song503196b2021-07-23 17:31:05 +08009265 } else if (audio_is_hearing_aid_out_device(device) &&
9266 property_get_bool("persist.vendor.audio.ha_proxy.enabled", false)) {
9267 adev->ha_proxy_enable = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07009268 }
9269 }
9270
9271 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
9272 if (ret >= 0) {
9273 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309274 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07009275 /*
9276 * The HDMI / Displayport disconnect handling has been moved to
9277 * audio extension to ensure that its parameters are not
9278 * invalidated prior to updating sysfs of the disconnect event
9279 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
9280 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309281 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08009282 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309283 if (ret >= 0)
9284 audio_extn_usb_remove_device(device, atoi(value));
9285
Zhou Song6f862822017-11-06 17:27:57 +08009286 if (!audio_extn_usb_is_tunnel_supported()) {
9287 ALOGV("detected USB disconnect .. enable proxy");
9288 adev->allow_afe_proxy_usage = true;
9289 }
Zhou Song503196b2021-07-23 17:31:05 +08009290 } else if (audio_is_hearing_aid_out_device(device)) {
9291 adev->ha_proxy_enable = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07009292 }
9293 }
9294
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009295 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08009296
9297 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08009298 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309299 struct audio_usecase *usecase;
9300 struct listnode *node;
9301 list_for_each(node, &adev->usecase_list) {
9302 usecase = node_to_item(node, struct audio_usecase, list);
Weiyin Jiangff56ff32020-05-08 14:32:21 +08009303 if ((usecase->stream.out == NULL) || (usecase->type != PCM_PLAYBACK))
9304 continue;
9305
9306 if (is_a2dp_out_device_type(&usecase->device_list)) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309307 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05309308 audio_extn_a2dp_set_handoff_mode(true);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05309309 ALOGD("Switching to speaker and muting the stream before select_devices");
9310 check_a2dp_restore_l(adev, usecase->stream.out, false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309311 //force device switch to re configure encoder
9312 select_devices(adev, usecase->id);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05309313 ALOGD("Unmuting the stream after select_devices");
Zhou Songbaddf9f2020-11-20 13:57:39 +08009314 check_a2dp_restore_l(adev, usecase->stream.out, true);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05309315 audio_extn_a2dp_set_handoff_mode(false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309316 break;
Zhou Songd01e7a22020-09-23 22:49:01 +08009317 } else if (is_offload_usecase(usecase->stream.out->usecase)) {
Weiyin Jiang280ea742020-09-08 20:28:22 +08009318 pthread_mutex_lock(&usecase->stream.out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +08009319 if (usecase->stream.out->a2dp_muted) {
Weiyin Jiang280ea742020-09-08 20:28:22 +08009320 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
9321 reassign_device_list(&usecase->stream.out->device_list,
9322 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, "");
9323 check_a2dp_restore_l(adev, usecase->stream.out, true);
9324 break;
9325 }
9326 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309327 }
9328 }
9329 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009330
9331 //handle vr audio setparam
9332 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9333 value, sizeof(value));
9334 if (ret >= 0) {
9335 ALOGI("Setting vr mode to be %s", value);
9336 if (!strncmp(value, "true", 4)) {
9337 adev->vr_audio_mode_enabled = true;
9338 ALOGI("Setting vr mode to true");
9339 } else if (!strncmp(value, "false", 5)) {
9340 adev->vr_audio_mode_enabled = false;
9341 ALOGI("Setting vr mode to false");
9342 } else {
9343 ALOGI("wrong vr mode set");
9344 }
9345 }
9346
Eric Laurent4b084132018-10-19 17:33:43 -07009347 //FIXME: to be replaced by proper video capture properties API
9348 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
9349 if (ret >= 0) {
9350 int camera_facing = CAMERA_FACING_BACK;
9351 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
9352 camera_facing = CAMERA_FACING_FRONT;
9353 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
9354 camera_facing = CAMERA_FACING_BACK;
9355 else {
9356 ALOGW("%s: invalid camera facing value: %s", __func__, value);
9357 goto done;
9358 }
9359 adev->camera_orientation =
9360 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
9361 struct audio_usecase *usecase;
9362 struct listnode *node;
9363 list_for_each(node, &adev->usecase_list) {
9364 usecase = node_to_item(node, struct audio_usecase, list);
9365 struct stream_in *in = usecase->stream.in;
9366 if (usecase->type == PCM_CAPTURE && in != NULL &&
9367 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
9368 select_devices(adev, in->usecase);
9369 }
9370 }
9371 }
9372
Naresh Tannirucd2353e2016-08-19 00:37:25 +05309373 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08009374done:
9375 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009376 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05309377error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009378 ALOGV("%s: exit with code(%d)", __func__, status);
9379 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009380}
9381
9382static char* adev_get_parameters(const struct audio_hw_device *dev,
9383 const char *keys)
9384{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05309385 ALOGD("%s:%s", __func__, keys);
9386
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009387 struct audio_device *adev = (struct audio_device *)dev;
9388 struct str_parms *reply = str_parms_create();
9389 struct str_parms *query = str_parms_create_str(keys);
9390 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05309391 char value[256] = {0};
9392 int ret = 0;
9393
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009394 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08009395 if (reply) {
9396 str_parms_destroy(reply);
9397 }
9398 if (query) {
9399 str_parms_destroy(query);
9400 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009401 ALOGE("adev_get_parameters: failed to create query or reply");
9402 return NULL;
9403 }
9404
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009405 //handle vr audio getparam
9406
9407 ret = str_parms_get_str(query,
9408 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9409 value, sizeof(value));
9410
9411 if (ret >= 0) {
9412 bool vr_audio_enabled = false;
9413 pthread_mutex_lock(&adev->lock);
9414 vr_audio_enabled = adev->vr_audio_mode_enabled;
9415 pthread_mutex_unlock(&adev->lock);
9416
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07009417 ALOGV("getting vr mode to %d", vr_audio_enabled);
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009418
9419 if (vr_audio_enabled) {
9420 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9421 "true");
9422 goto exit;
9423 } else {
9424 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9425 "false");
9426 goto exit;
9427 }
9428 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009429
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009430 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009431 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08009432 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08009433 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009434 platform_get_parameters(adev->platform, query, reply);
justinwengd5395152019-11-04 12:23:09 +08009435 audio_extn_ma_get_parameters(adev, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05309436 pthread_mutex_unlock(&adev->lock);
9437
Naresh Tannirud7205b62014-06-20 02:54:48 +05309438exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009439 str = str_parms_to_str(reply);
9440 str_parms_destroy(query);
9441 str_parms_destroy(reply);
9442
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07009443 ALOGV("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009444 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009445}
9446
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009447static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009448{
9449 return 0;
9450}
9451
9452static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
9453{
Haynes Mathew George5191a852013-09-11 14:19:36 -07009454 int ret;
9455 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08009456
9457 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
9458
Haynes Mathew George5191a852013-09-11 14:19:36 -07009459 pthread_mutex_lock(&adev->lock);
9460 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07009461 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07009462 pthread_mutex_unlock(&adev->lock);
9463 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009464}
9465
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009466static int adev_set_master_volume(struct audio_hw_device *dev __unused,
9467 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009468{
9469 return -ENOSYS;
9470}
9471
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009472static int adev_get_master_volume(struct audio_hw_device *dev __unused,
9473 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009474{
9475 return -ENOSYS;
9476}
9477
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009478static int adev_set_master_mute(struct audio_hw_device *dev __unused,
9479 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009480{
9481 return -ENOSYS;
9482}
9483
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009484static int adev_get_master_mute(struct audio_hw_device *dev __unused,
9485 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009486{
9487 return -ENOSYS;
9488}
9489
9490static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
9491{
9492 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07009493 struct listnode *node;
9494 struct audio_usecase *usecase = NULL;
9495 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08009496
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009497 pthread_mutex_lock(&adev->lock);
9498 if (adev->mode != mode) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309499 ALOGD("%s: mode %d , prev_mode %d \n", __func__, mode , adev->mode);
9500 adev->prev_mode = adev->mode; /* prev_mode is kept to handle voip concurrency*/
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009501 adev->mode = mode;
Weiyin Jiang96b96f72020-09-22 16:48:19 +08009502 if (mode == AUDIO_MODE_CALL_SCREEN) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309503 adev->current_call_output = adev->primary_output;
9504 voice_start_call(adev);
9505 } else if (voice_is_in_call_or_call_screen(adev) &&
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08009506 (mode == AUDIO_MODE_NORMAL ||
9507 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07009508 list_for_each(node, &adev->usecase_list) {
9509 usecase = node_to_item(node, struct audio_usecase, list);
9510 if (usecase->type == VOICE_CALL)
9511 break;
9512 }
9513 if (usecase &&
9514 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
9515 ret = audio_extn_usb_check_and_set_svc_int(usecase,
9516 true);
9517 if (ret != 0) {
9518 /* default service interval was successfully updated,
9519 reopen USB backend with new service interval */
9520 check_usecases_codec_backend(adev,
9521 usecase,
9522 usecase->out_snd_device);
9523 }
9524 }
9525
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009526 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07009527 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009528 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08009529 // restore device for other active usecases after stop call
9530 list_for_each(node, &adev->usecase_list) {
9531 usecase = node_to_item(node, struct audio_usecase, list);
9532 select_devices(adev, usecase->id);
9533 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009534 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009535 }
9536 pthread_mutex_unlock(&adev->lock);
9537 return 0;
9538}
9539
9540static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
9541{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009542 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08009543 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009544
9545 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08009546 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009547 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009548
Derek Chend2530072014-11-24 12:39:14 -08009549 if (adev->ext_hw_plugin)
9550 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009551
9552 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009553 pthread_mutex_unlock(&adev->lock);
9554
9555 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009556}
9557
9558static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
9559{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009560 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009561 return 0;
9562}
9563
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009564static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009565 const struct audio_config *config)
9566{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009567 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009568
Aalique Grahame22e49102018-12-18 14:23:57 -08009569 /* Don't know if USB HIFI in this context so use true to be conservative */
9570 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9571 true /*is_usb_hifi */) != 0)
9572 return 0;
9573
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009574 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
9575 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009576}
9577
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009578static bool adev_input_allow_hifi_record(struct audio_device *adev,
9579 audio_devices_t devices,
9580 audio_input_flags_t flags,
9581 audio_source_t source) {
9582 const bool allowed = true;
9583
9584 if (!audio_is_usb_in_device(devices))
9585 return !allowed;
9586
9587 switch (flags) {
9588 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009589 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07009590 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
9591 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009592 default:
9593 return !allowed;
9594 }
9595
9596 switch (source) {
9597 case AUDIO_SOURCE_DEFAULT:
9598 case AUDIO_SOURCE_MIC:
9599 case AUDIO_SOURCE_UNPROCESSED:
9600 break;
9601 default:
9602 return !allowed;
9603 }
9604
9605 switch (adev->mode) {
9606 case 0:
9607 break;
9608 default:
9609 return !allowed;
9610 }
9611
9612 return allowed;
9613}
9614
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009615static int adev_update_voice_comm_input_stream(struct stream_in *in,
9616 struct audio_config *config)
9617{
9618 bool valid_rate = (config->sample_rate == 8000 ||
9619 config->sample_rate == 16000 ||
9620 config->sample_rate == 32000 ||
9621 config->sample_rate == 48000);
9622 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
9623
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009624 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08009625 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009626 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9627 in->config = default_pcm_config_voip_copp;
9628 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
9629 DEFAULT_VOIP_BUF_DURATION_MS,
9630 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009631 } else {
9632 ALOGW("%s No valid input in voip, use defaults"
9633 "sample rate %u, channel mask 0x%X",
9634 __func__, config->sample_rate, in->channel_mask);
9635 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009636 in->config.rate = config->sample_rate;
9637 in->sample_rate = config->sample_rate;
9638 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009639 //XXX needed for voice_extn_compress_voip_open_input_stream
9640 in->config.rate = config->sample_rate;
9641 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
Shalini Manjunathaa763cc42019-08-23 15:13:46 +05309642 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009643 voice_extn_compress_voip_is_active(in->dev)) &&
9644 (voice_extn_compress_voip_is_format_supported(in->format)) &&
9645 valid_rate && valid_ch) {
9646 voice_extn_compress_voip_open_input_stream(in);
9647 // update rate entries to match config from AF
9648 in->config.rate = config->sample_rate;
9649 in->sample_rate = config->sample_rate;
9650 } else {
9651 ALOGW("%s compress voip not active, use defaults", __func__);
9652 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009653 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009654 return 0;
9655}
9656
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009657static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07009658 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009659 audio_devices_t devices,
9660 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009661 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309662 audio_input_flags_t flags,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009663 const char *address,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009664 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009665{
9666 struct audio_device *adev = (struct audio_device *)dev;
9667 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009668 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009669 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009670 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05309671 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009672 bool is_usb_dev = audio_is_usb_in_device(devices);
9673 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
9674 devices,
9675 flags,
9676 source);
Andy Hung94320602018-10-29 18:31:12 -07009677 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
9678 " sample_rate %u, channel_mask %#x, format %#x",
9679 __func__, flags, is_usb_dev, may_use_hifi_record,
9680 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309681
kunleizdff872d2018-08-20 14:40:33 +08009682 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08009683 is_usb_dev = false;
9684 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
9685 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
9686 __func__, devices);
9687 }
9688
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009689 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009690
9691 if (!(is_usb_dev && may_use_hifi_record)) {
9692 if (config->sample_rate == 0)
9693 config->sample_rate = 48000;
9694 if (config->channel_mask == AUDIO_CHANNEL_NONE)
9695 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9696 if (config->format == AUDIO_FORMAT_DEFAULT)
9697 config->format = AUDIO_FORMAT_PCM_16_BIT;
9698
9699 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
9700
Aalique Grahame22e49102018-12-18 14:23:57 -08009701 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9702 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009703 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05309704 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009705
9706 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009707
9708 if (!in) {
9709 ALOGE("failed to allocate input stream");
9710 return -ENOMEM;
9711 }
9712
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309713 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05309714 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
9715 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009716 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07009717 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009718
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009719 in->stream.common.get_sample_rate = in_get_sample_rate;
9720 in->stream.common.set_sample_rate = in_set_sample_rate;
9721 in->stream.common.get_buffer_size = in_get_buffer_size;
9722 in->stream.common.get_channels = in_get_channels;
9723 in->stream.common.get_format = in_get_format;
9724 in->stream.common.set_format = in_set_format;
9725 in->stream.common.standby = in_standby;
9726 in->stream.common.dump = in_dump;
9727 in->stream.common.set_parameters = in_set_parameters;
9728 in->stream.common.get_parameters = in_get_parameters;
9729 in->stream.common.add_audio_effect = in_add_audio_effect;
9730 in->stream.common.remove_audio_effect = in_remove_audio_effect;
9731 in->stream.set_gain = in_set_gain;
9732 in->stream.read = in_read;
9733 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08009734 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309735 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07009736 in->stream.set_microphone_direction = in_set_microphone_direction;
9737 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07009738 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009739
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009740 list_init(&in->device_list);
9741 update_device_list(&in->device_list, devices, address, true);
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009742 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009743 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009744 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009745 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009746 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07009747 in->bit_width = 16;
9748 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07009749 in->direction = MIC_DIRECTION_UNSPECIFIED;
9750 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08009751 list_init(&in->aec_list);
9752 list_init(&in->ns_list);
Phil Burkd898ba62019-06-20 12:49:01 -07009753 in->mmap_shared_memory_fd = -1; // not open
Haynes Mathew George46740472017-10-27 18:40:12 -07009754
Andy Hung94320602018-10-29 18:31:12 -07009755 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08009756 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
9757 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
9758 /* Force channel config requested to mono if incall
9759 record is being requested for only uplink/downlink */
9760 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
9761 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9762 ret = -EINVAL;
9763 goto err_open;
9764 }
9765 }
9766
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009767 if (is_usb_dev && may_use_hifi_record) {
9768 /* HiFi record selects an appropriate format, channel, rate combo
9769 depending on sink capabilities*/
9770 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
9771 &config->format,
9772 &in->supported_formats[0],
9773 MAX_SUPPORTED_FORMATS,
9774 &config->channel_mask,
9775 &in->supported_channel_masks[0],
9776 MAX_SUPPORTED_CHANNEL_MASKS,
9777 &config->sample_rate,
9778 &in->supported_sample_rates[0],
9779 MAX_SUPPORTED_SAMPLE_RATES);
9780 if (ret != 0) {
9781 ret = -EINVAL;
9782 goto err_open;
9783 }
9784 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009785 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309786 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05309787 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
9788 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
9789 in->config.format = PCM_FORMAT_S32_LE;
9790 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309791 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
9792 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
9793 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
9794 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
9795 bool ret_error = false;
9796 in->bit_width = 24;
9797 /* 24 bit is restricted to UNPROCESSED source only,also format supported
9798 from HAL is 24_packed and 8_24
9799 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
9800 24_packed return error indicating supported format is 24_packed
9801 *> In case of any other source requesting 24 bit or float return error
9802 indicating format supported is 16 bit only.
9803
9804 on error flinger will retry with supported format passed
9805 */
9806 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
9807 (source != AUDIO_SOURCE_CAMCORDER)) {
9808 config->format = AUDIO_FORMAT_PCM_16_BIT;
9809 if (config->sample_rate > 48000)
9810 config->sample_rate = 48000;
9811 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07009812 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
9813 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309814 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
9815 ret_error = true;
9816 }
9817
9818 if (ret_error) {
9819 ret = -EINVAL;
9820 goto err_open;
9821 }
9822 }
9823
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009824 in->channel_mask = config->channel_mask;
9825 in->format = config->format;
9826
9827 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309828
Huicheng Liu1404ba12020-09-11 01:03:25 -04009829 /* validate bus device address */
9830 if (compare_device_type(&in->device_list, AUDIO_DEVICE_IN_BUS)) {
9831 /* extract car audio stream index */
9832 in->car_audio_stream =
9833 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
9834 if (in->car_audio_stream < 0) {
9835 ALOGE("%s: invalid car audio stream %x",
9836 __func__, in->car_audio_stream);
9837 ret = -EINVAL;
9838 goto err_open;
9839 }
9840 ALOGV("%s: car_audio_stream 0x%x", __func__, in->car_audio_stream);
Huicheng Liuea4fd422021-01-12 18:34:50 -05009841 ret = audio_extn_auto_hal_open_input_stream(in);
9842 if (ret) {
9843 ALOGE("%s: Failed to open input stream for bus device", __func__);
9844 ret = -EINVAL;
9845 goto err_open;
9846 }
Huicheng Liu1404ba12020-09-11 01:03:25 -04009847 }
9848
Susan Wange3959562021-03-11 11:50:26 -05009849 /* reassign use case for echo reference stream on automotive platforms */
9850 if (in->source == AUDIO_SOURCE_ECHO_REFERENCE) {
9851 ret = audio_extn_auto_hal_open_echo_reference_stream(in);
9852 }
9853
Kogara Naveen Kumar379ff692022-01-31 11:56:51 +05309854 if ((in->source == AUDIO_SOURCE_FM_TUNER) || (devices == AUDIO_DEVICE_IN_FM_TUNER)) {
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309855 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
9856 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
9857 else {
9858 ret = -EINVAL;
9859 goto err_open;
9860 }
9861 }
9862
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +05309863 if ((config->sample_rate == 48000 ||
9864 config->sample_rate == 32000 ||
9865 config->sample_rate == 24000 ||
9866 config->sample_rate == 16000 ||
9867 config->sample_rate == 8000)&&
Deeraj Somanfa377bf2019-02-06 12:57:59 +05309868 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
9869 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009870 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
9871 is_low_latency = true;
9872#if LOW_LATENCY_CAPTURE_USE_CASE
Revathi Uddarajud9f23d92020-07-27 10:55:06 +05309873 if ((flags & AUDIO_INPUT_FLAG_VOIP_TX) != 0)
9874 in->usecase = USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY;
9875 else
9876 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009877#endif
9878 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08009879 if (!in->realtime) {
9880 in->config = pcm_config_audio_capture;
9881 frame_size = audio_stream_in_frame_size(&in->stream);
9882 buffer_size = get_input_buffer_size(config->sample_rate,
9883 config->format,
9884 channel_count,
9885 is_low_latency);
9886 in->config.period_size = buffer_size / frame_size;
9887 in->config.rate = config->sample_rate;
9888 in->af_period_multiplier = 1;
9889 } else {
9890 // period size is left untouched for rt mode playback
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +05309891 switch(config->sample_rate)
9892 {
9893 case 48000:
9894 in->config = pcm_config_audio_capture_rt_48KHz;
9895 break;
9896 case 32000:
9897 in->config = pcm_config_audio_capture_rt_32KHz;
9898 break;
9899 case 24000:
9900 in->config = pcm_config_audio_capture_rt_24KHz;
9901 break;
9902 case 16000:
9903 in->config = pcm_config_audio_capture_rt_16KHz;
9904 break;
9905 case 8000:
9906 in->config = pcm_config_audio_capture_rt_8KHz;
9907 break;
9908 default:
9909 in->config = pcm_config_audio_capture_rt_48KHz;
9910 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009911 in->af_period_multiplier = af_period_multiplier;
9912 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009913 }
9914
Susan Wangb803cb52021-10-14 12:03:36 -04009915 /* Additional sample rates added below must also be present
9916 in audio_policy_configuration.xml for mmap_no_irq_in */
9917 bool valid_mmap_record_rate = (config->sample_rate == 8000 ||
9918 config->sample_rate == 16000 ||
Susan Wang89da9042021-10-14 12:03:36 -04009919 config->sample_rate == 24000 ||
Susan Wangb803cb52021-10-14 12:03:36 -04009920 config->sample_rate == 32000 ||
9921 config->sample_rate == 48000);
9922 if (valid_mmap_record_rate &&
9923 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009924 in->realtime = 0;
9925 in->usecase = USECASE_AUDIO_RECORD_MMAP;
9926 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07009927 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009928 in->stream.start = in_start;
9929 in->stream.stop = in_stop;
9930 in->stream.create_mmap_buffer = in_create_mmap_buffer;
9931 in->stream.get_mmap_position = in_get_mmap_position;
Ramjee Singhbcb3b6c2021-11-17 13:19:16 +05309932 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009933 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
Haynes Mathew George46740472017-10-27 18:40:12 -07009934 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009935 in->usecase = USECASE_AUDIO_RECORD_HIFI;
9936 in->config = pcm_config_audio_capture;
9937 frame_size = audio_stream_in_frame_size(&in->stream);
9938 buffer_size = get_input_buffer_size(config->sample_rate,
9939 config->format,
9940 channel_count,
9941 false /*is_low_latency*/);
9942 in->config.period_size = buffer_size / frame_size;
9943 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009944 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07009945 switch (config->format) {
9946 case AUDIO_FORMAT_PCM_32_BIT:
9947 in->bit_width = 32;
9948 break;
9949 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
9950 case AUDIO_FORMAT_PCM_8_24_BIT:
9951 in->bit_width = 24;
9952 break;
9953 default:
9954 in->bit_width = 16;
9955 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009956 } else if (is_single_device_type_equal(&in->device_list,
9957 AUDIO_DEVICE_IN_TELEPHONY_RX) ||
9958 is_single_device_type_equal(&in->device_list,
9959 AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009960 if (config->sample_rate == 0)
9961 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9962 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
9963 config->sample_rate != 8000) {
9964 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9965 ret = -EINVAL;
9966 goto err_open;
9967 }
9968 if (config->format == AUDIO_FORMAT_DEFAULT)
9969 config->format = AUDIO_FORMAT_PCM_16_BIT;
9970 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
9971 config->format = AUDIO_FORMAT_PCM_16_BIT;
9972 ret = -EINVAL;
9973 goto err_open;
9974 }
9975
9976 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
Zhou Song62ea0282020-03-22 19:53:01 +08009977 if (adev->ha_proxy_enable &&
9978 is_single_device_type_equal(&in->device_list,
9979 AUDIO_DEVICE_IN_TELEPHONY_RX))
9980 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY2;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009981 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009982 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08009983 in->af_period_multiplier = 1;
9984 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
Shalini Manjunathaac412b32020-01-03 15:00:14 +05309985 (!voice_extn_is_compress_voip_supported()) &&
Aalique Grahame22e49102018-12-18 14:23:57 -08009986 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
9987 (config->sample_rate == 8000 ||
9988 config->sample_rate == 16000 ||
9989 config->sample_rate == 32000 ||
9990 config->sample_rate == 48000) &&
9991 channel_count == 1) {
9992 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9993 in->config = pcm_config_audio_capture;
9994 frame_size = audio_stream_in_frame_size(&in->stream);
9995 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
9996 config->sample_rate,
9997 config->format,
9998 channel_count, false /*is_low_latency*/);
9999 in->config.period_size = buffer_size / frame_size;
10000 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
10001 in->config.rate = config->sample_rate;
10002 in->af_period_multiplier = 1;
Mingshu Pangc2d65042021-01-14 16:19:10 +080010003 } else if (in->realtime) {
10004 in->config = pcm_config_audio_capture_rt;
10005 in->config.format = pcm_format_from_audio_format(config->format);
10006 in->af_period_multiplier = af_period_multiplier;
Haynes Mathew George46740472017-10-27 18:40:12 -070010007 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +053010008 int ret_val;
10009 pthread_mutex_lock(&adev->lock);
10010 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
10011 in, config, &channel_mask_updated);
10012 pthread_mutex_unlock(&adev->lock);
10013
10014 if (!ret_val) {
10015 if (channel_mask_updated == true) {
10016 ALOGD("%s: return error to retry with updated channel mask (%#x)",
10017 __func__, config->channel_mask);
10018 ret = -EINVAL;
10019 goto err_open;
10020 }
10021 ALOGD("%s: created multi-channel session succesfully",__func__);
10022 } else if (audio_extn_compr_cap_enabled() &&
10023 audio_extn_compr_cap_format_supported(config->format) &&
10024 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
10025 audio_extn_compr_cap_init(in);
10026 } else if (audio_extn_cin_applicable_stream(in)) {
Deeraj Soman14230922019-01-30 16:39:30 +053010027 ret = audio_extn_cin_configure_input_stream(in, config);
Revathi Uddarajud2634032017-12-07 14:42:34 +053010028 if (ret)
10029 goto err_open;
10030 } else {
10031 in->config = pcm_config_audio_capture;
10032 in->config.rate = config->sample_rate;
10033 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +053010034 in->format = config->format;
10035 frame_size = audio_stream_in_frame_size(&in->stream);
10036 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -070010037 config->format,
10038 channel_count,
10039 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +020010040 /* prevent division-by-zero */
10041 if (frame_size == 0) {
10042 ALOGE("%s: Error frame_size==0", __func__);
10043 ret = -EINVAL;
10044 goto err_open;
10045 }
10046
Revathi Uddarajud2634032017-12-07 14:42:34 +053010047 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -080010048 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -080010049
Revathi Uddarajud2634032017-12-07 14:42:34 +053010050 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
10051 /* optionally use VOIP usecase depending on config(s) */
10052 ret = adev_update_voice_comm_input_stream(in, config);
10053 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -080010054
Revathi Uddarajud2634032017-12-07 14:42:34 +053010055 if (ret) {
10056 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
10057 goto err_open;
10058 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -080010059 }
Jaideep Sharmad305a4a2020-02-27 14:29:04 +053010060
10061 /* assign concurrent capture usecase if record has to caried out from
10062 * actual hardware input source */
10063 if (audio_extn_is_concurrent_capture_enabled() &&
10064 !audio_is_virtual_input_source(in->source)) {
Samyak Jainc37062f2019-04-25 18:41:06 +053010065 /* Acquire lock to avoid two concurrent use cases initialized to
10066 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +080010067
Samyak Jainc37062f2019-04-25 18:41:06 +053010068 if (in->usecase == USECASE_AUDIO_RECORD) {
10069 pthread_mutex_lock(&adev->lock);
10070 if (!(adev->pcm_record_uc_state)) {
10071 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
10072 adev->pcm_record_uc_state = 1;
10073 pthread_mutex_unlock(&adev->lock);
Krishna Kishor Jha0f4d8482022-02-18 10:56:05 +053010074 } else if (audio_extn_is_concurrent_pcm_record_enabled()) {
10075 in->usecase = get_record_usecase(adev);
10076 pthread_mutex_unlock(&adev->lock);
Samyak Jainc37062f2019-04-25 18:41:06 +053010077 } else {
10078 pthread_mutex_unlock(&adev->lock);
10079 /* Assign compress record use case for second record */
10080 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
10081 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
10082 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
10083 if (audio_extn_cin_applicable_stream(in)) {
10084 in->sample_rate = config->sample_rate;
Deeraj Soman14230922019-01-30 16:39:30 +053010085 ret = audio_extn_cin_configure_input_stream(in, config);
Samyak Jainc37062f2019-04-25 18:41:06 +053010086 if (ret)
10087 goto err_open;
10088 }
10089 }
10090 }
kunleiz28c73e72019-03-27 17:24:04 +080010091 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -070010092 }
Kogara Naveen Kumar51bb57d2022-02-17 16:40:06 +053010093 if (in->realtime) {
10094 switch(config->sample_rate)
10095 {
10096 case 48000:
10097 in->config = pcm_config_audio_capture_rt_48KHz;
10098 break;
10099 case 32000:
10100 in->config = pcm_config_audio_capture_rt_32KHz;
10101 break;
10102 case 24000:
10103 in->config = pcm_config_audio_capture_rt_24KHz;
10104 break;
10105 case 16000:
10106 in->config = pcm_config_audio_capture_rt_16KHz;
10107 break;
10108 case 8000:
10109 in->config = pcm_config_audio_capture_rt_8KHz;
10110 break;
10111 default:
10112 in->config = pcm_config_audio_capture_rt_48KHz;
10113 }
10114 in->config.format = pcm_format_from_audio_format(config->format);
10115 in->af_period_multiplier = af_period_multiplier;
10116 }
10117
Ramjee Singh82fd0c12019-08-21 16:31:33 +053010118 if (audio_extn_ssr_get_stream() != in)
10119 in->config.channels = channel_count;
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -070010120
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -070010121 in->sample_rate = in->config.rate;
10122
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010123 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
10124 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010125 &in->device_list, flags, in->format,
Haynes Mathew George4ffef292017-11-21 15:08:02 -080010126 in->sample_rate, in->bit_width,
10127 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +053010128 register_format(in->format, in->supported_formats);
10129 register_channel_mask(in->channel_mask, in->supported_channel_masks);
10130 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010131
Dechen Chai22768452021-07-30 09:29:16 +053010132#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -080010133 in->error_log = error_log_create(
10134 ERROR_LOG_ENTRIES,
10135 1000000000 /* aggregate consecutive identical errors within one second */);
Dechen Chai22768452021-07-30 09:29:16 +053010136#endif
Aalique Grahame22e49102018-12-18 14:23:57 -080010137
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010138 /* This stream could be for sound trigger lab,
10139 get sound trigger pcm if present */
10140 audio_extn_sound_trigger_check_and_get_session(in);
10141
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010142 lock_input_stream(in);
10143 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
10144 pthread_mutex_lock(&adev->lock);
10145 in->card_status = adev->card_status;
10146 pthread_mutex_unlock(&adev->lock);
10147 pthread_mutex_unlock(&in->lock);
10148
Aalique Grahame22e49102018-12-18 14:23:57 -080010149 stream_app_type_cfg_init(&in->app_type_cfg);
10150
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010151 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -080010152
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010153 ret = io_streams_map_insert(adev, &in->stream.common,
10154 handle, AUDIO_PATCH_HANDLE_NONE);
10155 if (ret != 0)
10156 goto err_open;
10157
Susan Wang6dd13092021-01-25 10:27:11 -050010158 in->in_ctxt.input = in;
Derek Chenf939fb72018-11-13 13:34:41 -080010159
10160 pthread_mutex_lock(&adev->lock);
Susan Wang6dd13092021-01-25 10:27:11 -050010161 list_add_tail(&adev->active_inputs_list, &in->in_ctxt.list);
Derek Chenf939fb72018-11-13 13:34:41 -080010162 pthread_mutex_unlock(&adev->lock);
10163
Eric Laurent994a6932013-07-17 11:51:42 -070010164 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -080010165 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010166
10167err_open:
Krishna Kishor Jha0f4d8482022-02-18 10:56:05 +053010168 if (audio_extn_is_concurrent_pcm_record_enabled() && is_pcm_record_usecase(in->usecase)) {
10169 free_record_usecase(adev, in->usecase);
10170 } else if (in->usecase == USECASE_AUDIO_RECORD) {
Samyak Jainc37062f2019-04-25 18:41:06 +053010171 pthread_mutex_lock(&adev->lock);
10172 adev->pcm_record_uc_state = 0;
10173 pthread_mutex_unlock(&adev->lock);
10174 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010175 free(in);
10176 *stream_in = NULL;
10177 return ret;
10178}
10179
10180static void adev_close_input_stream(struct audio_hw_device *dev,
10181 struct audio_stream_in *stream)
10182{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080010183 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -070010184 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -070010185 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +053010186
Sidipotu Ashokf43018c2014-05-02 16:21:50 +053010187 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080010188
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010189 if (in == NULL) {
10190 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
10191 return;
10192 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010193 io_streams_map_remove(adev, in->capture_handle);
10194
Susan Wang6dd13092021-01-25 10:27:11 -050010195 // remove out_ctxt early to prevent the stream
10196 // being opened in a race condition
10197 pthread_mutex_lock(&adev->lock);
10198 list_remove(&in->in_ctxt.list);
10199 pthread_mutex_unlock(&adev->lock);
10200
kunleiz70e57612018-12-28 17:50:23 +080010201 /* must deregister from sndmonitor first to prevent races
10202 * between the callback and close_stream
10203 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010204 audio_extn_snd_mon_unregister_listener(stream);
10205
kunleiz70e57612018-12-28 17:50:23 +080010206 /* Disable echo reference if there are no active input, hfp call
10207 * and sound trigger while closing input stream
10208 */
Eric Laurent637e2d42018-11-15 12:24:31 -080010209 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +080010210 !audio_extn_hfp_is_active(adev) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010211 !audio_extn_sound_trigger_check_ec_ref_enable()) {
10212 struct listnode out_devices;
10213 list_init(&out_devices);
10214 platform_set_echo_reference(adev, false, &out_devices);
10215 } else
kunleiz70e57612018-12-28 17:50:23 +080010216 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +053010217
Dechen Chai22768452021-07-30 09:29:16 +053010218#ifndef LINUX_ENABLED
Weiyin Jiang2995f662019-04-17 14:25:12 +080010219 error_log_destroy(in->error_log);
10220 in->error_log = NULL;
Dechen Chai22768452021-07-30 09:29:16 +053010221#endif
Pallavid7c7a272018-01-16 11:22:55 +053010222
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080010223 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +053010224 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080010225 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +053010226 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080010227 if (ret != 0)
10228 ALOGE("%s: Compress voip input cannot be closed, error:%d",
10229 __func__, ret);
10230 } else
10231 in_standby(&stream->common);
10232
Weiyin Jiang280ea742020-09-08 20:28:22 +080010233 pthread_mutex_destroy(&in->lock);
10234 pthread_mutex_destroy(&in->pre_lock);
10235
Revathi Uddarajud2634032017-12-07 14:42:34 +053010236 pthread_mutex_lock(&adev->lock);
Krishna Kishor Jha0f4d8482022-02-18 10:56:05 +053010237 if (audio_extn_is_concurrent_pcm_record_enabled() && is_pcm_record_usecase(in->usecase)) {
10238 free_record_usecase(adev, in->usecase);
10239 } else if (in->usecase == USECASE_AUDIO_RECORD) {
Samyak Jain15fda662018-12-18 16:40:52 +053010240 adev->pcm_record_uc_state = 0;
10241 }
10242
Kunlei Zhang5d5d8d92020-02-26 15:00:59 +080010243 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
10244 adev->enable_voicerx = false;
10245 }
10246
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -070010247 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -070010248 audio_extn_ssr_deinit();
10249 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010250
Garmond Leunge2433c32017-09-28 21:51:22 -070010251 if (audio_extn_ffv_get_stream() == in) {
10252 audio_extn_ffv_stream_deinit();
10253 }
10254
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010255 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -070010256 audio_extn_compr_cap_format_supported(in->config.format))
10257 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +053010258
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +053010259 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +053010260 audio_extn_cin_free_input_stream_resources(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010261
Mingming Yinfd7607b2016-01-22 12:48:44 -080010262 if (in->is_st_session) {
10263 ALOGV("%s: sound trigger pcm stop lab", __func__);
10264 audio_extn_sound_trigger_stop_lab(in);
10265 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010266 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +053010267 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010268 return;
10269}
10270
Aalique Grahame22e49102018-12-18 14:23:57 -080010271/* verifies input and output devices and their capabilities.
10272 *
10273 * This verification is required when enabling extended bit-depth or
10274 * sampling rates, as not all qcom products support it.
10275 *
10276 * Suitable for calling only on initialization such as adev_open().
10277 * It fills the audio_device use_case_table[] array.
10278 *
10279 * Has a side-effect that it needs to configure audio routing / devices
10280 * in order to power up the devices and read the device parameters.
10281 * It does not acquire any hw device lock. Should restore the devices
10282 * back to "normal state" upon completion.
10283 */
10284static int adev_verify_devices(struct audio_device *adev)
10285{
10286 /* enumeration is a bit difficult because one really wants to pull
10287 * the use_case, device id, etc from the hidden pcm_device_table[].
10288 * In this case there are the following use cases and device ids.
10289 *
10290 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
10291 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
10292 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
10293 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
10294 * [USECASE_AUDIO_RECORD] = {0, 0},
10295 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
10296 * [USECASE_VOICE_CALL] = {2, 2},
10297 *
10298 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
10299 * USECASE_VOICE_CALL omitted, but possible for either input or output.
10300 */
10301
10302 /* should be the usecases enabled in adev_open_input_stream() */
10303 static const int test_in_usecases[] = {
10304 USECASE_AUDIO_RECORD,
10305 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
10306 };
10307 /* should be the usecases enabled in adev_open_output_stream()*/
10308 static const int test_out_usecases[] = {
10309 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
10310 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
10311 };
10312 static const usecase_type_t usecase_type_by_dir[] = {
10313 PCM_PLAYBACK,
10314 PCM_CAPTURE,
10315 };
10316 static const unsigned flags_by_dir[] = {
10317 PCM_OUT,
10318 PCM_IN,
10319 };
10320
10321 size_t i;
10322 unsigned dir;
10323 const unsigned card_id = adev->snd_card;
10324
10325 for (dir = 0; dir < 2; ++dir) {
10326 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
10327 const unsigned flags_dir = flags_by_dir[dir];
10328 const size_t testsize =
10329 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
10330 const int *testcases =
10331 dir ? test_in_usecases : test_out_usecases;
10332 const audio_devices_t audio_device =
10333 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
10334
10335 for (i = 0; i < testsize; ++i) {
10336 const audio_usecase_t audio_usecase = testcases[i];
10337 int device_id;
10338 struct pcm_params **pparams;
10339 struct stream_out out;
10340 struct stream_in in;
10341 struct audio_usecase uc_info;
10342 int retval;
10343
10344 pparams = &adev->use_case_table[audio_usecase];
10345 pcm_params_free(*pparams); /* can accept null input */
10346 *pparams = NULL;
10347
10348 /* find the device ID for the use case (signed, for error) */
10349 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
10350 if (device_id < 0)
10351 continue;
10352
10353 /* prepare structures for device probing */
10354 memset(&uc_info, 0, sizeof(uc_info));
10355 uc_info.id = audio_usecase;
10356 uc_info.type = usecase_type;
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010357 list_init(&uc_info.device_list);
Aalique Grahame22e49102018-12-18 14:23:57 -080010358 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -080010359 memset(&in, 0, sizeof(in));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010360 list_init(&in.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010361 update_device_list(&in.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -080010362 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
10363 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -080010364 }
10365 memset(&out, 0, sizeof(out));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010366 list_init(&out.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010367 update_device_list(&out.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -080010368 uc_info.stream.out = &out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010369 update_device_list(&uc_info.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -080010370 uc_info.in_snd_device = SND_DEVICE_NONE;
10371 uc_info.out_snd_device = SND_DEVICE_NONE;
10372 list_add_tail(&adev->usecase_list, &uc_info.list);
10373
10374 /* select device - similar to start_(in/out)put_stream() */
10375 retval = select_devices(adev, audio_usecase);
10376 if (retval >= 0) {
10377 *pparams = pcm_params_get(card_id, device_id, flags_dir);
10378#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -070010379 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -080010380 if (*pparams) {
10381 ALOGV("%s: (%s) card %d device %d", __func__,
10382 dir ? "input" : "output", card_id, device_id);
10383 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
10384 } else {
10385 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
10386 }
10387#endif
10388 }
10389
10390 /* deselect device - similar to stop_(in/out)put_stream() */
10391 /* 1. Get and set stream specific mixer controls */
10392 retval = disable_audio_route(adev, &uc_info);
10393 /* 2. Disable the rx device */
10394 retval = disable_snd_device(adev,
10395 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
10396 list_remove(&uc_info.list);
10397 }
10398 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010399 return 0;
10400}
10401
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010402int update_patch(unsigned int num_sources,
10403 const struct audio_port_config *sources,
10404 unsigned int num_sinks,
10405 const struct audio_port_config *sinks,
10406 audio_patch_handle_t handle,
10407 struct audio_patch_info *p_info,
10408 patch_type_t patch_type, bool new_patch)
10409{
Aniket Kumar Latad13758f2020-08-06 15:11:36 -070010410 ALOGV("%s: enter", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010411
10412 if (p_info == NULL) {
10413 ALOGE("%s: Invalid patch pointer", __func__);
10414 return -EINVAL;
10415 }
10416
10417 if (new_patch) {
10418 p_info->patch = (struct audio_patch *) calloc(1, sizeof(struct audio_patch));
10419 if (p_info->patch == NULL) {
10420 ALOGE("%s: Could not allocate patch", __func__);
10421 return -ENOMEM;
10422 }
10423 }
10424
10425 p_info->patch->id = handle;
10426 p_info->patch->num_sources = num_sources;
10427 p_info->patch->num_sinks = num_sinks;
10428
10429 for (int i = 0; i < num_sources; i++)
10430 p_info->patch->sources[i] = sources[i];
10431 for (int i = 0; i < num_sinks; i++)
10432 p_info->patch->sinks[i] = sinks[i];
10433
10434 p_info->patch_type = patch_type;
10435 return 0;
10436}
10437
10438audio_patch_handle_t generate_patch_handle()
10439{
10440 static audio_patch_handle_t patch_handle = AUDIO_PATCH_HANDLE_NONE;
10441 if (++patch_handle < 0)
10442 patch_handle = AUDIO_PATCH_HANDLE_NONE + 1;
10443 return patch_handle;
10444}
10445
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010446int adev_create_audio_patch(struct audio_hw_device *dev,
10447 unsigned int num_sources,
10448 const struct audio_port_config *sources,
10449 unsigned int num_sinks,
10450 const struct audio_port_config *sinks,
10451 audio_patch_handle_t *handle)
10452{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010453 int ret = 0;
10454 struct audio_device *adev = (struct audio_device *)dev;
10455 struct audio_patch_info *p_info = NULL;
10456 patch_type_t patch_type = PATCH_NONE;
10457 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10458 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
10459 struct audio_stream_info *s_info = NULL;
10460 struct audio_stream *stream = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010461 struct listnode devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010462 audio_devices_t device_type = AUDIO_DEVICE_NONE;
10463 bool new_patch = false;
10464 char addr[AUDIO_DEVICE_MAX_ADDRESS_LEN];
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010465
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010466 ALOGD("%s: enter: num sources %d, num_sinks %d, handle %d", __func__,
10467 num_sources, num_sinks, *handle);
10468
10469 if (num_sources == 0 || num_sources > AUDIO_PATCH_PORTS_MAX ||
10470 num_sinks == 0 || num_sinks > AUDIO_PATCH_PORTS_MAX) {
10471 ALOGE("%s: Invalid patch arguments", __func__);
10472 ret = -EINVAL;
10473 goto done;
10474 }
10475
10476 if (num_sources > 1) {
10477 ALOGE("%s: Multiple sources are not supported", __func__);
10478 ret = -EINVAL;
10479 goto done;
10480 }
10481
10482 if (sources == NULL || sinks == NULL) {
10483 ALOGE("%s: Invalid sources or sinks port config", __func__);
10484 ret = -EINVAL;
10485 goto done;
10486 }
10487
10488 ALOGV("%s: source role %d, source type %d", __func__,
10489 sources[0].type, sources[0].role);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010490 list_init(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010491
10492 // Populate source/sink information and fetch stream info
10493 switch (sources[0].type) {
10494 case AUDIO_PORT_TYPE_DEVICE: // Patch for audio capture or loopback
10495 device_type = sources[0].ext.device.type;
10496 strlcpy(&addr[0], &sources[0].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010497 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010498 if (sinks[0].type == AUDIO_PORT_TYPE_MIX) {
10499 patch_type = PATCH_CAPTURE;
10500 io_handle = sinks[0].ext.mix.handle;
10501 input_source = sinks[0].ext.mix.usecase.source;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010502 ALOGD("%s: Capture patch from device %x to mix %d",
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010503 __func__, device_type, io_handle);
10504 } else {
10505 // Device to device patch is not implemented.
10506 // This space will need changes if audio HAL
10507 // handles device to device patches in the future.
10508 patch_type = PATCH_DEVICE_LOOPBACK;
10509 }
10510 break;
10511 case AUDIO_PORT_TYPE_MIX: // Patch for audio playback
10512 io_handle = sources[0].ext.mix.handle;
10513 for (int i = 0; i < num_sinks; i++) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010514 device_type = sinks[i].ext.device.type;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010515 strlcpy(&addr[0], &sinks[i].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010516 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010517 }
10518 patch_type = PATCH_PLAYBACK;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010519 ALOGD("%s: Playback patch from mix handle %d to device %x",
10520 __func__, io_handle, get_device_types(&devices));
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010521 break;
10522 case AUDIO_PORT_TYPE_SESSION:
10523 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010524 ALOGE("%s: Unsupported source type %d", __func__, sources[0].type);
10525 ret = -EINVAL;
10526 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010527 }
10528
10529 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010530
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010531 // Generate patch info and update patch
10532 if (*handle == AUDIO_PATCH_HANDLE_NONE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010533 *handle = generate_patch_handle();
10534 p_info = (struct audio_patch_info *)
10535 calloc(1, sizeof(struct audio_patch_info));
10536 if (p_info == NULL) {
10537 ALOGE("%s: Failed to allocate memory", __func__);
10538 pthread_mutex_unlock(&adev->lock);
10539 ret = -ENOMEM;
10540 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010541 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010542 new_patch = true;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010543 } else {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010544 p_info = fetch_patch_info_l(adev, *handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010545 if (p_info == NULL) {
10546 ALOGE("%s: Unable to fetch patch for received patch handle %d",
10547 __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010548 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010549 ret = -EINVAL;
10550 goto done;
10551 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010552 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010553 update_patch(num_sources, sources, num_sinks, sinks,
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010554 *handle, p_info, patch_type, new_patch);
10555
10556 // Fetch stream info of associated mix for playback or capture patches
10557 if (p_info->patch_type == PATCH_PLAYBACK ||
10558 p_info->patch_type == PATCH_CAPTURE) {
10559 s_info = hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10560 if (s_info == NULL) {
10561 ALOGE("%s: Failed to obtain stream info", __func__);
10562 if (new_patch)
10563 free(p_info);
10564 pthread_mutex_unlock(&adev->lock);
10565 ret = -EINVAL;
10566 goto done;
10567 }
10568 ALOGV("%s: Fetched stream info with io_handle %d", __func__, io_handle);
10569 s_info->patch_handle = *handle;
10570 stream = s_info->stream;
10571 }
10572 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010573
10574 // Update routing for stream
10575 if (stream != NULL) {
Revathi Uddaraju4255a632021-12-02 05:11:13 -080010576 if (p_info->patch_type == PATCH_PLAYBACK) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010577 ret = route_output_stream((struct stream_out *) stream, &devices);
Revathi Uddaraju4255a632021-12-02 05:11:13 -080010578 clear_devices(&devices);
10579 } else if (p_info->patch_type == PATCH_CAPTURE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010580 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Revathi Uddaraju4255a632021-12-02 05:11:13 -080010581 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010582 if (ret < 0) {
10583 pthread_mutex_lock(&adev->lock);
10584 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10585 if (new_patch)
10586 free(p_info);
10587 pthread_mutex_unlock(&adev->lock);
10588 ALOGE("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10589 goto done;
10590 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010591 }
10592
10593 // Add new patch to patch map
10594 if (!ret && new_patch) {
10595 pthread_mutex_lock(&adev->lock);
10596 hashmapPut(adev->patch_map, (void *) (intptr_t) *handle, (void *) p_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010597 ALOGD("%s: Added a new patch with handle %d", __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010598 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010599 }
10600
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010601done:
10602 audio_extn_hw_loopback_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010603 num_sources,
10604 sources,
10605 num_sinks,
10606 sinks,
10607 handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010608 audio_extn_auto_hal_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010609 num_sources,
10610 sources,
10611 num_sinks,
10612 sinks,
10613 handle);
10614 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010615}
10616
10617int adev_release_audio_patch(struct audio_hw_device *dev,
10618 audio_patch_handle_t handle)
10619{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010620 struct audio_device *adev = (struct audio_device *) dev;
10621 int ret = 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010622 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010623 struct audio_stream *stream = NULL;
Derek Chenf939fb72018-11-13 13:34:41 -080010624
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010625 if (handle == AUDIO_PATCH_HANDLE_NONE) {
10626 ALOGE("%s: Invalid patch handle %d", __func__, handle);
10627 ret = -EINVAL;
10628 goto done;
10629 }
10630
10631 ALOGD("%s: Remove patch with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010632 pthread_mutex_lock(&adev->lock);
10633 struct audio_patch_info *p_info = fetch_patch_info_l(adev, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010634 if (p_info == NULL) {
10635 ALOGE("%s: Patch info not found with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010636 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010637 ret = -EINVAL;
10638 goto done;
10639 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010640 struct audio_patch *patch = p_info->patch;
10641 if (patch == NULL) {
10642 ALOGE("%s: Patch not found for handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010643 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010644 ret = -EINVAL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010645 goto done;
10646 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010647 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10648 switch (patch->sources[0].type) {
10649 case AUDIO_PORT_TYPE_MIX:
10650 io_handle = patch->sources[0].ext.mix.handle;
10651 break;
10652 case AUDIO_PORT_TYPE_DEVICE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010653 if (p_info->patch_type == PATCH_CAPTURE)
10654 io_handle = patch->sinks[0].ext.mix.handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010655 break;
10656 case AUDIO_PORT_TYPE_SESSION:
10657 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010658 pthread_mutex_unlock(&adev->lock);
10659 ret = -EINVAL;
10660 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010661 }
10662
10663 // Remove patch and reset patch handle in stream info
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010664 patch_type_t patch_type = p_info->patch_type;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010665 patch_map_remove_l(adev, handle);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010666 if (patch_type == PATCH_PLAYBACK ||
10667 patch_type == PATCH_CAPTURE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010668 struct audio_stream_info *s_info =
10669 hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10670 if (s_info == NULL) {
10671 ALOGE("%s: stream for io_handle %d is not available", __func__, io_handle);
10672 pthread_mutex_unlock(&adev->lock);
10673 goto done;
10674 }
10675 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10676 stream = s_info->stream;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010677 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010678 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010679
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010680 if (stream != NULL) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010681 struct listnode devices;
10682 list_init(&devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010683 if (patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010684 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010685 else if (patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010686 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010687 }
10688
10689 if (ret < 0)
10690 ALOGW("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10691
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010692done:
10693 audio_extn_hw_loopback_release_audio_patch(dev, handle);
10694 audio_extn_auto_hal_release_audio_patch(dev, handle);
10695
10696 ALOGV("%s: Successfully released patch %d", __func__, handle);
Derek Chenf939fb72018-11-13 13:34:41 -080010697 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010698}
10699
10700int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
10701{
Derek Chenf13dd492018-11-13 14:53:51 -080010702 int ret = 0;
10703
10704 ret = audio_extn_hw_loopback_get_audio_port(dev, config);
10705 ret |= audio_extn_auto_hal_get_audio_port(dev, config);
10706 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010707}
10708
10709int adev_set_audio_port_config(struct audio_hw_device *dev,
10710 const struct audio_port_config *config)
10711{
Derek Chenf13dd492018-11-13 14:53:51 -080010712 int ret = 0;
10713
10714 ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
10715 ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
10716 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010717}
10718
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -070010719static int adev_dump(const audio_hw_device_t *device __unused,
10720 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010721{
10722 return 0;
10723}
10724
10725static int adev_close(hw_device_t *device)
10726{
Aalique Grahame22e49102018-12-18 14:23:57 -080010727 size_t i;
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010728 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -070010729
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010730 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -070010731 return 0;
10732
10733 pthread_mutex_lock(&adev_init_lock);
10734
10735 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +053010736 if (audio_extn_spkr_prot_is_enabled())
10737 audio_extn_spkr_prot_deinit();
Jaideep Sharmaa2b49672019-09-10 20:37:03 +053010738 audio_extn_battery_properties_listener_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010739 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010740 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -080010741 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010742 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -080010743 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010744 audio_extn_utils_release_streams_cfg_lists(
10745 &adev->streams_output_cfg_list,
10746 &adev->streams_input_cfg_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010747 if (audio_extn_qap_is_enabled())
10748 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010749 if (audio_extn_qaf_is_enabled())
10750 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -070010751 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +080010752 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -070010753 free(adev->snd_dev_ref_cnt);
10754 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010755 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
10756 pcm_params_free(adev->use_case_table[i]);
10757 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010758 if (adev->adm_deinit)
10759 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010760 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010761 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010762 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010763 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010764 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010765 if (adev->device_cfg_params) {
10766 free(adev->device_cfg_params);
10767 adev->device_cfg_params = NULL;
10768 }
Derek Chend2530072014-11-24 12:39:14 -080010769 if(adev->ext_hw_plugin)
10770 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -080010771 audio_extn_auto_hal_deinit();
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010772 free_map(adev->patch_map);
10773 free_map(adev->io_streams_map);
Kiran Kandi910e1862013-10-29 13:29:42 -070010774 free(device);
10775 adev = NULL;
10776 }
10777 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +053010778 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010779 return 0;
10780}
10781
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010782/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
10783 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
10784 * just that it _might_ work.
10785 */
10786static int period_size_is_plausible_for_low_latency(int period_size)
10787{
10788 switch (period_size) {
10789 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -070010790 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010791 case 240:
10792 case 320:
10793 case 480:
10794 return 1;
10795 default:
10796 return 0;
10797 }
10798}
10799
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010800static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
10801{
10802 bool is_snd_card_status = false;
10803 bool is_ext_device_status = false;
10804 char value[32];
10805 int card = -1;
10806 card_status_t status;
10807
10808 if (cookie != adev || !parms)
10809 return;
10810
10811 if (!parse_snd_card_status(parms, &card, &status)) {
10812 is_snd_card_status = true;
10813 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
10814 is_ext_device_status = true;
10815 } else {
10816 // not a valid event
10817 return;
10818 }
10819
10820 pthread_mutex_lock(&adev->lock);
10821 if (card == adev->snd_card || is_ext_device_status) {
10822 if (is_snd_card_status && adev->card_status != status) {
Jaideep Sharmacb402512020-09-24 17:51:07 +053010823 ALOGD("%s card_status %d", __func__, status);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010824 adev->card_status = status;
10825 platform_snd_card_update(adev->platform, status);
10826 audio_extn_fm_set_parameters(adev, parms);
Derek Chend6f371d2019-03-01 13:45:58 -080010827 audio_extn_auto_hal_set_parameters(adev, parms);
Zhou Song4f43e352019-07-02 00:32:23 +080010828 if (status == CARD_STATUS_OFFLINE)
10829 audio_extn_sco_reset_configuration();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010830 } else if (is_ext_device_status) {
10831 platform_set_parameters(adev->platform, parms);
10832 }
10833 }
10834 pthread_mutex_unlock(&adev->lock);
10835 return;
10836}
10837
Weiyin Jiang280ea742020-09-08 20:28:22 +080010838/* adev lock held */
10839int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010840{
10841 struct audio_usecase *uc_info;
Zhou Song407e5aa2020-12-27 19:13:04 +080010842 struct audio_usecase *usecase;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010843 struct listnode devices;
Zhou Song407e5aa2020-12-27 19:13:04 +080010844 struct listnode *node;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010845
10846 uc_info = get_usecase_from_list(adev, out->usecase);
10847 if (uc_info == NULL) {
10848 ALOGE("%s: Could not find the usecase (%d) in the list",
10849 __func__, out->usecase);
10850 return -EINVAL;
10851 }
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010852 list_init(&devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010853
Zhou Songbaddf9f2020-11-20 13:57:39 +080010854 ALOGD("%s: enter: usecase(%d: %s), a2dp muted %d", __func__,
10855 out->usecase, use_case_table[out->usecase], out->a2dp_muted);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010856
10857 if (restore) {
Weiyin Jiang280ea742020-09-08 20:28:22 +080010858 pthread_mutex_lock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010859 // restore A2DP device for active usecases and unmute if required
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010860 if (is_a2dp_out_device_type(&out->device_list)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010861 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
Zhou Songe5225132019-09-26 15:33:36 +080010862 if (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)
10863 select_devices(adev, uc_info->id);
Zhou Songbaddf9f2020-11-20 13:57:39 +080010864
10865 if (is_offload_usecase(out->usecase)) {
10866 if (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)
Weiyin Jiang280ea742020-09-08 20:28:22 +080010867 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
Zhou Songbaddf9f2020-11-20 13:57:39 +080010868 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
10869 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
10870 } else {
10871 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010872 }
Zhou Songbaddf9f2020-11-20 13:57:39 +080010873 out->a2dp_muted = false;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010874 }
Weiyin Jiang280ea742020-09-08 20:28:22 +080010875 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010876 } else {
Weiyin Jiang280ea742020-09-08 20:28:22 +080010877 pthread_mutex_lock(&out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +080010878 // mute stream and switch to speaker if suspended
10879 if (!out->a2dp_muted && !out->standby) {
Zhou Songbaddf9f2020-11-20 13:57:39 +080010880 assign_devices(&devices, &out->device_list);
10881 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Zhou Song407e5aa2020-12-27 19:13:04 +080010882 list_for_each(node, &adev->usecase_list) {
10883 usecase = node_to_item(node, struct audio_usecase, list);
Zhou Songe63b6fe2021-04-15 13:54:46 +080010884 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
10885 !is_a2dp_out_device_type(&usecase->stream.out->device_list) &&
Zhou Songcf77af02021-05-14 18:21:14 +080010886 !is_sco_out_device_type(&usecase->stream.out->device_list) &&
Zhou Songe63b6fe2021-04-15 13:54:46 +080010887 platform_check_backends_match(SND_DEVICE_OUT_SPEAKER,
10888 usecase->out_snd_device)) {
Zhou Song407e5aa2020-12-27 19:13:04 +080010889 assign_devices(&out->device_list, &usecase->stream.out->device_list);
10890 break;
10891 }
10892 }
Zhou Songcf77af02021-05-14 18:21:14 +080010893 if ((is_a2dp_out_device_type(&devices) && list_length(&devices) == 1) ||
10894 (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)) {
Zhou Song8edbbdb2021-01-14 16:48:03 +080010895 out->a2dp_muted = true;
10896 if (is_offload_usecase(out->usecase)) {
10897 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10898 compress_pause(out->compr);
10899 out_set_compr_volume(&out->stream, (float)0, (float)0);
Zhou Song8edbbdb2021-01-14 16:48:03 +080010900 } else {
Weiyin Jiang906db3c2021-03-02 13:17:04 +080010901 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
10902 out_set_voip_volume(&out->stream, (float)0, (float)0);
10903 else
10904 out_set_pcm_volume(&out->stream, (float)0, (float)0);
10905
Zhou Song8edbbdb2021-01-14 16:48:03 +080010906 /* wait for stale pcm drained before switching to speaker */
10907 uint32_t latency =
10908 (out->config.period_count * out->config.period_size * 1000) /
10909 (out->config.rate);
10910 usleep(latency * 1000);
10911 }
Zhou Songbaddf9f2020-11-20 13:57:39 +080010912 }
10913 select_devices(adev, out->usecase);
Zhou Song8edbbdb2021-01-14 16:48:03 +080010914 ALOGD("%s: switched to device:%s and stream muted:%d", __func__,
10915 platform_get_snd_device_name(uc_info->out_snd_device), out->a2dp_muted);
Zhou Songbaddf9f2020-11-20 13:57:39 +080010916 if (is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010917 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10918 compress_resume(out->compr);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010919 }
Zhou Songbaddf9f2020-11-20 13:57:39 +080010920 assign_devices(&out->device_list, &devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010921 }
Weiyin Jiang280ea742020-09-08 20:28:22 +080010922 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010923 }
10924 ALOGV("%s: exit", __func__);
10925 return 0;
10926}
10927
Haynes Mathew George01156f92018-04-13 15:29:54 -070010928void adev_on_battery_status_changed(bool charging)
10929{
10930 pthread_mutex_lock(&adev->lock);
10931 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
10932 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +080010933 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -070010934 pthread_mutex_unlock(&adev->lock);
10935}
10936
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010937static int adev_open(const hw_module_t *module, const char *name,
10938 hw_device_t **device)
10939{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010940 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -080010941 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010942 char mixer_ctl_name[128] = {0};
10943 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010944
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080010945 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010946 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
10947
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010948 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -070010949 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010950 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -070010951 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010952 ALOGD("%s: returning existing instance of adev", __func__);
10953 ALOGD("%s: exit", __func__);
10954 pthread_mutex_unlock(&adev_init_lock);
10955 return 0;
10956 }
10957
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010958 adev = calloc(1, sizeof(struct audio_device));
10959
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -070010960 if (!adev) {
10961 pthread_mutex_unlock(&adev_init_lock);
10962 return -ENOMEM;
10963 }
10964
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -070010965 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
10966
Weiyin Jiange6ce6312019-01-28 18:28:22 +080010967 // register audio ext hidl at the earliest
10968 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053010969#ifdef DYNAMIC_LOG_ENABLED
10970 register_for_dynamic_logging("hal");
10971#endif
10972
Derek Chenf939fb72018-11-13 13:34:41 -080010973 /* default audio HAL major version */
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010974 uint32_t maj_version = 3;
Derek Chenf939fb72018-11-13 13:34:41 -080010975 if(property_get("vendor.audio.hal.maj.version", value, NULL))
10976 maj_version = atoi(value);
10977
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010978 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -080010979 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010980 adev->device.common.module = (struct hw_module_t *)module;
10981 adev->device.common.close = adev_close;
10982
10983 adev->device.init_check = adev_init_check;
10984 adev->device.set_voice_volume = adev_set_voice_volume;
10985 adev->device.set_master_volume = adev_set_master_volume;
10986 adev->device.get_master_volume = adev_get_master_volume;
10987 adev->device.set_master_mute = adev_set_master_mute;
10988 adev->device.get_master_mute = adev_get_master_mute;
10989 adev->device.set_mode = adev_set_mode;
10990 adev->device.set_mic_mute = adev_set_mic_mute;
10991 adev->device.get_mic_mute = adev_get_mic_mute;
10992 adev->device.set_parameters = adev_set_parameters;
10993 adev->device.get_parameters = adev_get_parameters;
10994 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
10995 adev->device.open_output_stream = adev_open_output_stream;
10996 adev->device.close_output_stream = adev_close_output_stream;
10997 adev->device.open_input_stream = adev_open_input_stream;
10998 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010999 adev->device.create_audio_patch = adev_create_audio_patch;
11000 adev->device.release_audio_patch = adev_release_audio_patch;
11001 adev->device.get_audio_port = adev_get_audio_port;
11002 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011003 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +053011004 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011005
11006 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011007 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -080011008 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011009 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011010 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -080011011 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -070011012 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +053011013 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -070011014 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -070011015 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -070011016 /* Init audio and voice feature */
11017 audio_extn_feature_init();
11018 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070011019 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -080011020 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -080011021 list_init(&adev->active_inputs_list);
11022 list_init(&adev->active_outputs_list);
Rahul Sharma99770982019-03-06 17:05:26 +053011023 list_init(&adev->audio_patch_record_list);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011024 adev->io_streams_map = hashmapCreate(AUDIO_IO_PORTS_MAX, audio_extn_utils_hash_fn,
11025 audio_extn_utils_hash_eq);
11026 if (!adev->io_streams_map) {
11027 ALOGE("%s: Could not create io streams map", __func__);
11028 ret = -ENOMEM;
11029 goto adev_open_err;
11030 }
11031 adev->patch_map = hashmapCreate(AUDIO_PATCH_PORTS_MAX, audio_extn_utils_hash_fn,
11032 audio_extn_utils_hash_eq);
11033 if (!adev->patch_map) {
11034 ALOGE("%s: Could not create audio patch map", __func__);
11035 ret = -ENOMEM;
11036 goto adev_open_err;
11037 }
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -080011038 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -070011039 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +053011040 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +053011041 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +053011042 adev->perf_lock_opts[0] = 0x101;
11043 adev->perf_lock_opts[1] = 0x20E;
11044 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +080011045 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -070011046 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053011047 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070011048 adev->adm_routing_changed = false;
Revathi Uddarajub26e3932020-06-10 14:51:02 +053011049 adev->a2dp_started = false;
Zhou Song503196b2021-07-23 17:31:05 +080011050 adev->ha_proxy_enable = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +053011051
Zhou Song68ebc352019-12-05 17:11:15 +080011052 audio_extn_perf_lock_init();
11053
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011054 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -070011055 adev->platform = platform_init(adev);
11056 if (!adev->platform) {
Eric Laurentb23d5282013-05-14 15:27:20 -070011057 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011058 ret = -EINVAL;
11059 goto adev_open_err;
Eric Laurentb23d5282013-05-14 15:27:20 -070011060 }
Eric Laurentc4aef752013-09-12 17:45:53 -070011061
Aalique Grahame22e49102018-12-18 14:23:57 -080011062 adev->extspk = audio_extn_extspk_init(adev);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053011063 if (audio_extn_qap_is_enabled()) {
11064 ret = audio_extn_qap_init(adev);
11065 if (ret < 0) {
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053011066 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011067 goto adev_open_err;
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053011068 }
11069 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
11070 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
11071 }
Aalique Grahame22e49102018-12-18 14:23:57 -080011072
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053011073 if (audio_extn_qaf_is_enabled()) {
11074 ret = audio_extn_qaf_init(adev);
11075 if (ret < 0) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053011076 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011077 goto adev_open_err;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053011078 }
11079
11080 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
11081 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
11082 }
11083
Derek Chenae7b0342019-02-08 15:17:04 -080011084 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -080011085 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
11086
Eric Laurentc4aef752013-09-12 17:45:53 -070011087 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
11088 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
11089 if (adev->visualizer_lib == NULL) {
11090 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
11091 } else {
11092 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
11093 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080011094 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070011095 "visualizer_hal_start_output");
11096 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080011097 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070011098 "visualizer_hal_stop_output");
11099 }
11100 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +053011101 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080011102 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -080011103 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +080011104 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +053011105 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070011106 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -070011107
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080011108 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
11109 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
11110 if (adev->offload_effects_lib == NULL) {
11111 ALOGE("%s: DLOPEN failed for %s", __func__,
11112 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
11113 } else {
11114 ALOGV("%s: DLOPEN successful for %s", __func__,
11115 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
11116 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +053011117 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080011118 "offload_effects_bundle_hal_start_output");
11119 adev->offload_effects_stop_output =
11120 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
11121 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080011122 adev->offload_effects_set_hpx_state =
11123 (int (*)(bool))dlsym(adev->offload_effects_lib,
11124 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +053011125 adev->offload_effects_get_parameters =
11126 (void (*)(struct str_parms *, struct str_parms *))
11127 dlsym(adev->offload_effects_lib,
11128 "offload_effects_bundle_get_parameters");
11129 adev->offload_effects_set_parameters =
11130 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
11131 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080011132 }
11133 }
11134
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070011135 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
11136 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
11137 if (adev->adm_lib == NULL) {
11138 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
11139 } else {
11140 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
11141 adev->adm_init = (adm_init_t)
11142 dlsym(adev->adm_lib, "adm_init");
11143 adev->adm_deinit = (adm_deinit_t)
11144 dlsym(adev->adm_lib, "adm_deinit");
11145 adev->adm_register_input_stream = (adm_register_input_stream_t)
11146 dlsym(adev->adm_lib, "adm_register_input_stream");
11147 adev->adm_register_output_stream = (adm_register_output_stream_t)
11148 dlsym(adev->adm_lib, "adm_register_output_stream");
11149 adev->adm_deregister_stream = (adm_deregister_stream_t)
11150 dlsym(adev->adm_lib, "adm_deregister_stream");
11151 adev->adm_request_focus = (adm_request_focus_t)
11152 dlsym(adev->adm_lib, "adm_request_focus");
11153 adev->adm_abandon_focus = (adm_abandon_focus_t)
11154 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -070011155 adev->adm_set_config = (adm_set_config_t)
11156 dlsym(adev->adm_lib, "adm_set_config");
11157 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
11158 dlsym(adev->adm_lib, "adm_request_focus_v2");
11159 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
11160 dlsym(adev->adm_lib, "adm_is_noirq_avail");
11161 adev->adm_on_routing_change = (adm_on_routing_change_t)
11162 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070011163 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
11164 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070011165 }
11166 }
11167
Aalique Grahame22e49102018-12-18 14:23:57 -080011168 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070011169 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +080011170 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Kunlei Zhanga3c4cb02021-03-05 16:03:54 +080011171 adev->fluence_nn_usecase_id = USECASE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -080011172 //initialize this to false for now,
11173 //this will be set to true through set param
11174 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070011175
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -070011176 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011177 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -080011178
11179 if (k_enable_extended_precision)
11180 adev_verify_devices(adev);
11181
Xiaojun Sang785b5da2017-08-03 15:52:29 +080011182 adev->dsp_bit_width_enforce_mode =
11183 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011184
Dhananjay Kumard6d32152016-10-13 16:11:03 +053011185 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
11186 &adev->streams_output_cfg_list,
11187 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070011188
Kiran Kandi910e1862013-10-29 13:29:42 -070011189 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070011190
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070011191 int trial;
Manisha Agarwalc75a0202019-12-06 18:48:25 +053011192 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070011193 trial = atoi(value);
11194 if (period_size_is_plausible_for_low_latency(trial)) {
11195 pcm_config_low_latency.period_size = trial;
11196 pcm_config_low_latency.start_threshold = trial / 4;
11197 pcm_config_low_latency.avail_min = trial / 4;
11198 configured_low_latency_capture_period_size = trial;
11199 }
11200 }
ronghuiz93177262021-04-21 19:58:13 +080011201 if (property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070011202 trial = atoi(value);
11203 if (period_size_is_plausible_for_low_latency(trial)) {
11204 configured_low_latency_capture_period_size = trial;
11205 }
11206 }
11207
Vignesh Kulothungan7d374312018-02-21 17:12:00 -080011208 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
11209
Eric Laurent4b084132018-10-19 17:33:43 -070011210 adev->camera_orientation = CAMERA_DEFAULT;
11211
Manisha Agarwalc75a0202019-12-06 18:48:25 +053011212 if (property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -070011213 af_period_multiplier = atoi(value);
11214 if (af_period_multiplier < 0)
11215 af_period_multiplier = 2;
11216 else if (af_period_multiplier > 4)
11217 af_period_multiplier = 4;
11218
11219 ALOGV("new period_multiplier = %d", af_period_multiplier);
11220 }
11221
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080011222 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080011223
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -070011224 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070011225 pthread_mutex_unlock(&adev_init_lock);
11226
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070011227 if (adev->adm_init)
11228 adev->adm_data = adev->adm_init();
11229
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053011230 qahwi_init(*device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080011231 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053011232
11233 audio_extn_snd_mon_init();
11234 pthread_mutex_lock(&adev->lock);
11235 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
11236 adev->card_status = CARD_STATUS_ONLINE;
Shubhasini Sugumaran3fde6582022-01-19 15:54:50 -050011237 adev->out_power_policy = POWER_POLICY_STATUS_ONLINE;
11238 adev->in_power_policy = POWER_POLICY_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -070011239 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
11240 /*
11241 * if the battery state callback happens before charging can be queried,
11242 * it will be guarded with the adev->lock held in the cb function and so
11243 * the callback value will reflect the latest state
11244 */
11245 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053011246 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +080011247 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -070011248 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +080011249 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053011250 /* Allocate memory for Device config params */
11251 adev->device_cfg_params = (struct audio_device_config_param*)
11252 calloc(platform_get_max_codec_backend(),
11253 sizeof(struct audio_device_config_param));
11254 if (adev->device_cfg_params == NULL)
11255 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053011256
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053011257 /*
11258 * Check if new PSPD matrix mixer control is supported. If not
11259 * supported, then set flag so that old mixer ctrl is sent while
11260 * sending pspd coefficients on older kernel version. Query mixer
11261 * control for default pcm id and channel value one.
11262 */
11263 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
11264 "AudStr %d ChMixer Weight Ch %d", 0, 1);
11265
11266 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
11267 if (!ctl) {
11268 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
11269 __func__, mixer_ctl_name);
11270 adev->use_old_pspd_mix_ctrl = true;
11271 }
11272
Jaideep Sharma0fa53812020-09-17 09:00:11 +053011273 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011274 return 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011275
11276adev_open_err:
11277 free_map(adev->patch_map);
11278 free_map(adev->io_streams_map);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080011279 free(adev->snd_dev_ref_cnt);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011280 pthread_mutex_destroy(&adev->lock);
11281 free(adev);
11282 adev = NULL;
11283 *device = NULL;
11284 pthread_mutex_unlock(&adev_init_lock);
11285 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011286}
11287
11288static struct hw_module_methods_t hal_module_methods = {
11289 .open = adev_open,
11290};
11291
11292struct audio_module HAL_MODULE_INFO_SYM = {
11293 .common = {
11294 .tag = HARDWARE_MODULE_TAG,
11295 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
11296 .hal_api_version = HARDWARE_HAL_API_VERSION,
11297 .id = AUDIO_HARDWARE_MODULE_ID,
11298 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -080011299 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011300 .methods = &hal_module_methods,
11301 },
11302};