blob: a32c4d44b01d03c965717a14a3c4619fea6835be [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Zhou Song642ec432020-12-23 16:11:10 +08002 * Copyright (c) 2013-2021, 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
Daniel Hillenbrand17873952013-05-23 10:10:00 +053088#include "audio_amplifier.h"
89
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053090#ifdef DYNAMIC_LOG_ENABLED
91#include <log_xml_parser.h>
92#define LOG_MASK HAL_MOD_FILE_AUDIO_HW
93#include <log_utils.h>
94#endif
95
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070096#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053097/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
98#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070099#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700100#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Arun Mirpuri5d170872019-03-26 13:21:31 -0700101#define MMAP_PLAYBACK_VOLUME_MAX 0x2000
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530102#define PCM_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530103#define DSD_VOLUME_MIN_DB (-110)
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700104#define INVALID_OUT_VOLUME -1
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700105#define AUDIO_IO_PORTS_MAX 32
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700106
Zhou Songbaddf9f2020-11-20 13:57:39 +0800107#define PLAYBACK_GAIN_MAX 1.0f
Aalique Grahame22e49102018-12-18 14:23:57 -0800108#define RECORD_GAIN_MIN 0.0f
109#define RECORD_GAIN_MAX 1.0f
110#define RECORD_VOLUME_CTL_MAX 0x2000
111
112/* treat as unsigned Q1.13 */
113#define APP_TYPE_GAIN_DEFAULT 0x2000
114
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700115#define PROXY_OPEN_RETRY_COUNT 100
116#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800117
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800118#define GET_USECASE_AUDIO_PLAYBACK_PRIMARY(db) \
119 (db)? USECASE_AUDIO_PLAYBACK_DEEP_BUFFER : \
120 USECASE_AUDIO_PLAYBACK_LOW_LATENCY
121#define GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(db) \
122 (db)? pcm_config_deep_buffer : pcm_config_low_latency
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800123
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700124#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700125#define DEFAULT_VOIP_BUF_DURATION_MS 20
126#define DEFAULT_VOIP_BIT_DEPTH_BYTE sizeof(int16_t)
127#define DEFAULT_VOIP_SAMP_RATE 48000
128
129#define VOIP_IO_BUF_SIZE(SR, DURATION_MS, BIT_DEPTH) (SR)/1000 * DURATION_MS * BIT_DEPTH
130
131struct pcm_config default_pcm_config_voip_copp = {
132 .channels = 1,
133 .rate = DEFAULT_VOIP_SAMP_RATE, /* changed when the stream is opened */
134 .period_size = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
135 .period_count = 2,
136 .format = PCM_FORMAT_S16_LE,
kunleiz95b597a2017-10-23 17:07:33 +0800137 .avail_min = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
138 .stop_threshold = INT_MAX,
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700139};
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700140
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700141#define MIN_CHANNEL_COUNT 1
142#define DEFAULT_CHANNEL_COUNT 2
143#define MAX_HIFI_CHANNEL_COUNT 8
144
Aalique Grahame22e49102018-12-18 14:23:57 -0800145#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
146#define MAX_CHANNEL_COUNT 1
147#else
148#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
149#define XSTR(x) STR(x)
150#define STR(x) #x
151#endif
152
Dechen Chai22768452021-07-30 09:29:16 +0530153#ifdef LINUX_ENABLED
154static inline int64_t audio_utils_ns_from_timespec(const struct timespec *ts)
155{
156 return ts->tv_sec * 1000000000LL + ts->tv_nsec;
157}
158#endif
159
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700160static unsigned int configured_low_latency_capture_period_size =
161 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
162
Haynes Mathew George16081042017-05-31 17:16:49 -0700163#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
164#define MMAP_PERIOD_COUNT_MIN 32
165#define MMAP_PERIOD_COUNT_MAX 512
166#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
167
Aalique Grahame22e49102018-12-18 14:23:57 -0800168/* This constant enables extended precision handling.
169 * TODO The flag is off until more testing is done.
170 */
171static const bool k_enable_extended_precision = false;
Arun Mirpurie008ed22019-03-21 11:21:04 -0700172extern int AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Aalique Grahame22e49102018-12-18 14:23:57 -0800173
Eric Laurentb23d5282013-05-14 15:27:20 -0700174struct pcm_config pcm_config_deep_buffer = {
175 .channels = 2,
176 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
177 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
178 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
179 .format = PCM_FORMAT_S16_LE,
180 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
181 .stop_threshold = INT_MAX,
182 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
183};
184
185struct pcm_config pcm_config_low_latency = {
186 .channels = 2,
187 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
188 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
189 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
190 .format = PCM_FORMAT_S16_LE,
191 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
192 .stop_threshold = INT_MAX,
193 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
194};
195
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800196struct pcm_config pcm_config_haptics_audio = {
197 .channels = 1,
198 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
199 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
200 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
201 .format = PCM_FORMAT_S16_LE,
202 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
203 .stop_threshold = INT_MAX,
204 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
205};
206
207struct pcm_config pcm_config_haptics = {
208 .channels = 1,
209 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
210 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
211 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
212 .format = PCM_FORMAT_S16_LE,
213 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
214 .stop_threshold = INT_MAX,
215 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
216};
217
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700218static int af_period_multiplier = 4;
219struct pcm_config pcm_config_rt = {
220 .channels = 2,
221 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
222 .period_size = ULL_PERIOD_SIZE, //1 ms
223 .period_count = 512, //=> buffer size is 512ms
224 .format = PCM_FORMAT_S16_LE,
225 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
226 .stop_threshold = INT_MAX,
227 .silence_threshold = 0,
228 .silence_size = 0,
229 .avail_min = ULL_PERIOD_SIZE, //1 ms
230};
231
Eric Laurentb23d5282013-05-14 15:27:20 -0700232struct pcm_config pcm_config_hdmi_multi = {
233 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
234 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
235 .period_size = HDMI_MULTI_PERIOD_SIZE,
236 .period_count = HDMI_MULTI_PERIOD_COUNT,
237 .format = PCM_FORMAT_S16_LE,
238 .start_threshold = 0,
239 .stop_threshold = INT_MAX,
240 .avail_min = 0,
241};
242
Haynes Mathew George16081042017-05-31 17:16:49 -0700243struct pcm_config pcm_config_mmap_playback = {
244 .channels = 2,
245 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
246 .period_size = MMAP_PERIOD_SIZE,
247 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
248 .format = PCM_FORMAT_S16_LE,
249 .start_threshold = MMAP_PERIOD_SIZE*8,
250 .stop_threshold = INT32_MAX,
251 .silence_threshold = 0,
252 .silence_size = 0,
253 .avail_min = MMAP_PERIOD_SIZE, //1 ms
254};
255
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700256struct pcm_config pcm_config_hifi = {
257 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
258 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
259 .period_size = HIFI_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
260 .period_count = HIFI_BUFFER_OUTPUT_PERIOD_COUNT,
261 .format = PCM_FORMAT_S24_3LE,
262 .start_threshold = 0,
263 .stop_threshold = INT_MAX,
264 .avail_min = 0,
265};
266
Eric Laurentb23d5282013-05-14 15:27:20 -0700267struct pcm_config pcm_config_audio_capture = {
268 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700269 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
270 .format = PCM_FORMAT_S16_LE,
271};
272
Haynes Mathew George16081042017-05-31 17:16:49 -0700273struct pcm_config pcm_config_mmap_capture = {
274 .channels = 2,
275 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
276 .period_size = MMAP_PERIOD_SIZE,
277 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
278 .format = PCM_FORMAT_S16_LE,
279 .start_threshold = 0,
280 .stop_threshold = INT_MAX,
281 .silence_threshold = 0,
282 .silence_size = 0,
283 .avail_min = MMAP_PERIOD_SIZE, //1 ms
284};
285
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700286#define AFE_PROXY_CHANNEL_COUNT 2
287#define AFE_PROXY_SAMPLING_RATE 48000
288
289#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
290#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
291
292struct pcm_config pcm_config_afe_proxy_playback = {
293 .channels = AFE_PROXY_CHANNEL_COUNT,
294 .rate = AFE_PROXY_SAMPLING_RATE,
295 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
296 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
297 .format = PCM_FORMAT_S16_LE,
298 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
299 .stop_threshold = INT_MAX,
300 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
301};
302
303#define AFE_PROXY_RECORD_PERIOD_SIZE 768
304#define AFE_PROXY_RECORD_PERIOD_COUNT 4
305
Aalique Grahame22e49102018-12-18 14:23:57 -0800306struct pcm_config pcm_config_audio_capture_rt = {
307 .channels = 2,
308 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
309 .period_size = ULL_PERIOD_SIZE,
310 .period_count = 512,
311 .format = PCM_FORMAT_S16_LE,
312 .start_threshold = 0,
313 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
314 .silence_threshold = 0,
315 .silence_size = 0,
316 .avail_min = ULL_PERIOD_SIZE, //1 ms
317};
318
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700319struct pcm_config pcm_config_afe_proxy_record = {
320 .channels = AFE_PROXY_CHANNEL_COUNT,
321 .rate = AFE_PROXY_SAMPLING_RATE,
322 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
323 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
324 .format = PCM_FORMAT_S16_LE,
325 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
326 .stop_threshold = INT_MAX,
327 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
328};
329
Ashish Jainf1eaa582016-05-23 20:54:24 +0530330#define AUDIO_MAX_PCM_FORMATS 7
331
332const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
333 [AUDIO_FORMAT_DEFAULT] = 0,
334 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
335 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
336 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
337 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
338 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
339 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
340};
341
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800342const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700343 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
344 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800345 [USECASE_AUDIO_PLAYBACK_WITH_HAPTICS] = "audio-with-haptics-playback",
Meng Wang51d8c2a2020-04-27 15:23:21 +0800346 [USECASE_AUDIO_PLAYBACK_HAPTICS] = "haptics-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700347 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
348 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700349 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700350 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700351 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
352 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
353 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
354 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
355 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
356 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
357 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
358 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
Haynes Mathew George16081042017-05-31 17:16:49 -0700359 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
360 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700361 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Aalique Grahame22e49102018-12-18 14:23:57 -0800362 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
vivek mehta0ea887a2015-08-26 14:01:20 -0700363
Eric Laurentb23d5282013-05-14 15:27:20 -0700364 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700365 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530366 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
367 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
368 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Dhananjay Kumar376e38b2017-09-28 22:26:23 +0530369 [USECASE_AUDIO_RECORD_COMPRESS5] = "audio-record-compress5",
370 [USECASE_AUDIO_RECORD_COMPRESS6] = "audio-record-compress6",
Eric Laurentb23d5282013-05-14 15:27:20 -0700371 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700372 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700373 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700374 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700375
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800376 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800377 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Derek Chenf7092792017-05-23 12:23:53 -0400378 [USECASE_AUDIO_HFP_SCO_DOWNLINK] = "hfp-sco-downlink",
379 [USECASE_AUDIO_HFP_SCO_WB_DOWNLINK] = "hfp-sco-wb-downlink",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700380
Derek Chenf7092792017-05-23 12:23:53 -0400381 [USECASE_VOICE_CALL] = "voice-call",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700382 [USECASE_VOICE2_CALL] = "voice2-call",
383 [USECASE_VOLTE_CALL] = "volte-call",
384 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800385 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800386 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
387 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800388 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700389 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
390 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
391 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800392 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
393 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
394 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
395
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700396 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
397 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700398 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
399 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700400
401 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
402 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Zhou Song62ea0282020-03-22 19:53:01 +0800403 [USECASE_AUDIO_RECORD_AFE_PROXY2] = "afe-proxy-record2",
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +0530404 [USECASE_AUDIO_PLAYBACK_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700405
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530406 /* Transcode loopback cases */
Surendar Karka93cd25a2018-08-28 14:21:37 +0530407 [USECASE_AUDIO_TRANSCODE_LOOPBACK_RX] = "audio-transcode-loopback-rx",
408 [USECASE_AUDIO_TRANSCODE_LOOPBACK_TX] = "audio-transcode-loopback-tx",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700409
410 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
411 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Revathi Uddarajud9f23d92020-07-27 10:55:06 +0530412 [USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY] = "audio-record-voip-low-latency",
Varun Balaraje49253e2017-07-06 19:48:56 +0530413 /* For Interactive Audio Streams */
414 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
415 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
416 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
417 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
418 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
419 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
420 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
421 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700422
Aniket Kumar Lata7fd86e12018-02-20 19:26:10 -0800423 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture",
424
Derek Chenf6318be2017-06-12 17:16:24 -0400425 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
426
427 [USECASE_AUDIO_PLAYBACK_MEDIA] = "media-playback",
428 [USECASE_AUDIO_PLAYBACK_SYS_NOTIFICATION] = "sys-notification-playback",
429 [USECASE_AUDIO_PLAYBACK_NAV_GUIDANCE] = "nav-guidance-playback",
430 [USECASE_AUDIO_PLAYBACK_PHONE] = "phone-playback",
Derek Chen1bcdc6b2020-02-06 22:44:53 -0800431 [USECASE_AUDIO_PLAYBACK_FRONT_PASSENGER] = "front-passenger-playback",
Derek Chendf05eea2019-08-01 13:57:49 -0700432 [USECASE_AUDIO_PLAYBACK_REAR_SEAT] = "rear-seat-playback",
Rahul Sharma99770982019-03-06 17:05:26 +0530433 [USECASE_AUDIO_FM_TUNER_EXT] = "fm-tuner-ext",
Derek Chena30a5f42019-12-03 11:17:09 -0500434 [USECASE_ICC_CALL] = "icc-call",
Huicheng Liu1404ba12020-09-11 01:03:25 -0400435
436 [USECASE_AUDIO_RECORD_BUS] = "audio-record",
437 [USECASE_AUDIO_RECORD_BUS_FRONT_PASSENGER] = "front-passenger-record",
438 [USECASE_AUDIO_RECORD_BUS_REAR_SEAT] = "rear-seat-record",
Fei Tongaffdf732020-02-20 20:39:05 +0800439 [USECASE_AUDIO_PLAYBACK_SYNTHESIZER] = "synth-loopback",
Susan Wange3959562021-03-11 11:50:26 -0500440 [USECASE_AUDIO_RECORD_ECHO_REF_EXT] = "echo-reference-external",
Eric Laurentb23d5282013-05-14 15:27:20 -0700441};
442
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700443static const audio_usecase_t offload_usecases[] = {
444 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700445 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
446 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
447 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
448 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
449 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
450 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
451 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
452 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700453};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800454
Varun Balaraje49253e2017-07-06 19:48:56 +0530455static const audio_usecase_t interactive_usecases[] = {
456 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
457 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
458 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
459 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
460 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
461 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
462 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
463 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
464};
465
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800466#define STRING_TO_ENUM(string) { #string, string }
467
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800468struct string_to_enum {
469 const char *name;
470 uint32_t value;
471};
472
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700473static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800474 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800475 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
476 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
477 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700478 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800479 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
480 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800481 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700482 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
483 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
484 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
485 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
486 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
487 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
488 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
489 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
490 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
491 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
492 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800493};
494
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700495static const struct string_to_enum formats_name_to_enum_table[] = {
496 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
497 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
498 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700499 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
500 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
501 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700502 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800503 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
504 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700505 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800506};
507
508//list of all supported sample rates by HDMI specification.
509static const int out_hdmi_sample_rates[] = {
510 32000, 44100, 48000, 88200, 96000, 176400, 192000,
511};
512
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700513static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800514 STRING_TO_ENUM(32000),
515 STRING_TO_ENUM(44100),
516 STRING_TO_ENUM(48000),
517 STRING_TO_ENUM(88200),
518 STRING_TO_ENUM(96000),
519 STRING_TO_ENUM(176400),
520 STRING_TO_ENUM(192000),
Mingshu pange8aedf12019-10-25 15:38:27 +0800521 STRING_TO_ENUM(352800),
522 STRING_TO_ENUM(384000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700523};
524
Carter Hsu2e429db2019-05-14 18:50:52 +0800525struct in_effect_list {
526 struct listnode list;
527 effect_handle_t handle;
528};
529
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700530static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700531static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700532static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700533//cache last MBDRC cal step level
534static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700535
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530536static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Arun Mirpuri5d170872019-03-26 13:21:31 -0700537static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800538static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530539static int out_set_pcm_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530540
Derek Chen6f293672019-04-01 01:40:24 -0700541static void adev_snd_mon_cb(void *cookie, struct str_parms *parms);
542static void in_snd_mon_cb(void * stream, struct str_parms * parms);
543static void out_snd_mon_cb(void * stream, struct str_parms * parms);
544
Zhou Song331c8e52019-08-26 14:16:12 +0800545static int configure_btsco_sample_rate(snd_device_t snd_device);
546
Vatsal Buchac09ae062018-11-14 13:25:08 +0530547#ifdef AUDIO_FEATURE_ENABLED_GCOV
548extern void __gcov_flush();
549static void enable_gcov()
550{
551 __gcov_flush();
552}
553#else
554static void enable_gcov()
555{
556}
557#endif
558
justinweng20fb6d82019-02-21 18:49:00 -0700559static int in_set_microphone_direction(const struct audio_stream_in *stream,
560 audio_microphone_direction_t dir);
561static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom);
562
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700563static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
564 int flags __unused)
565{
566 int dir = 0;
567 switch (uc_id) {
568 case USECASE_AUDIO_RECORD_LOW_LATENCY:
Revathi Uddarajud9f23d92020-07-27 10:55:06 +0530569 case USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY:
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700570 dir = 1;
571 case USECASE_AUDIO_PLAYBACK_ULL:
572 break;
573 default:
574 return false;
575 }
576
577 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
578 PCM_PLAYBACK : PCM_CAPTURE);
579 if (adev->adm_is_noirq_avail)
580 return adev->adm_is_noirq_avail(adev->adm_data,
581 adev->snd_card, dev_id, dir);
582 return false;
583}
584
585static void register_out_stream(struct stream_out *out)
586{
587 struct audio_device *adev = out->dev;
588 if (is_offload_usecase(out->usecase) ||
589 !adev->adm_register_output_stream)
590 return;
591
592 // register stream first for backward compatibility
593 adev->adm_register_output_stream(adev->adm_data,
594 out->handle,
595 out->flags);
596
597 if (!adev->adm_set_config)
598 return;
599
600 if (out->realtime)
601 adev->adm_set_config(adev->adm_data,
602 out->handle,
603 out->pcm, &out->config);
604}
605
606static void register_in_stream(struct stream_in *in)
607{
608 struct audio_device *adev = in->dev;
609 if (!adev->adm_register_input_stream)
610 return;
611
612 adev->adm_register_input_stream(adev->adm_data,
613 in->capture_handle,
614 in->flags);
615
616 if (!adev->adm_set_config)
617 return;
618
619 if (in->realtime)
620 adev->adm_set_config(adev->adm_data,
621 in->capture_handle,
622 in->pcm,
623 &in->config);
624}
625
626static void request_out_focus(struct stream_out *out, long ns)
627{
628 struct audio_device *adev = out->dev;
629
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700630 if (adev->adm_request_focus_v2)
631 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
632 else if (adev->adm_request_focus)
633 adev->adm_request_focus(adev->adm_data, out->handle);
634}
635
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700636static int request_in_focus(struct stream_in *in, long ns)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700637{
638 struct audio_device *adev = in->dev;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700639 int ret = 0;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700640
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700641 if (adev->adm_request_focus_v2_1)
642 ret = adev->adm_request_focus_v2_1(adev->adm_data, in->capture_handle, ns);
643 else if (adev->adm_request_focus_v2)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700644 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
645 else if (adev->adm_request_focus)
646 adev->adm_request_focus(adev->adm_data, in->capture_handle);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700647
648 return ret;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700649}
650
651static void release_out_focus(struct stream_out *out)
652{
653 struct audio_device *adev = out->dev;
654
655 if (adev->adm_abandon_focus)
656 adev->adm_abandon_focus(adev->adm_data, out->handle);
657}
658
659static void release_in_focus(struct stream_in *in)
660{
661 struct audio_device *adev = in->dev;
662 if (adev->adm_abandon_focus)
663 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
664}
665
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530666static int parse_snd_card_status(struct str_parms *parms, int *card,
667 card_status_t *status)
668{
669 char value[32]={0};
670 char state[32]={0};
671
672 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
673 if (ret < 0)
674 return -1;
675
676 // sscanf should be okay as value is of max length 32.
677 // same as sizeof state.
678 if (sscanf(value, "%d,%s", card, state) < 2)
679 return -1;
680
681 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
682 CARD_STATUS_OFFLINE;
683 return 0;
684}
685
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700686static inline void adjust_frames_for_device_delay(struct stream_out *out,
687 uint32_t *dsp_frames) {
688 // Adjustment accounts for A2dp encoder latency with offload usecases
689 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -0800690 if (is_a2dp_out_device_type(&out->device_list)) {
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700691 unsigned long offset =
692 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
693 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
694 }
695}
696
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700697static inline bool free_entry(void *key __unused,
698 void *value, void *context __unused)
699{
700 free(value);
701 return true;
702}
703
704static inline void free_map(Hashmap *map)
705{
706 if (map) {
707 hashmapForEach(map, free_entry, (void *) NULL);
708 hashmapFree(map);
709 }
710}
711
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800712static inline void patch_map_remove_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700713 audio_patch_handle_t patch_handle)
714{
715 if (patch_handle == AUDIO_PATCH_HANDLE_NONE)
716 return;
717
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700718 struct audio_patch_info *p_info =
719 hashmapGet(adev->patch_map, (void *) (intptr_t) patch_handle);
720 if (p_info) {
721 ALOGV("%s: Remove patch %d", __func__, patch_handle);
722 hashmapRemove(adev->patch_map, (void *) (intptr_t) patch_handle);
723 free(p_info->patch);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700724 free(p_info);
725 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700726}
727
728static inline int io_streams_map_insert(struct audio_device *adev,
729 struct audio_stream *stream,
730 audio_io_handle_t handle,
731 audio_patch_handle_t patch_handle)
732{
733 struct audio_stream_info *s_info =
734 (struct audio_stream_info *) calloc(1, sizeof(struct audio_stream_info));
735
736 if (s_info == NULL) {
737 ALOGE("%s: Could not allocate stream info", __func__);
738 return -ENOMEM;
739 }
740 s_info->stream = stream;
741 s_info->patch_handle = patch_handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700742
743 pthread_mutex_lock(&adev->lock);
744 struct audio_stream_info *stream_info =
745 hashmapPut(adev->io_streams_map, (void *) (intptr_t) handle, (void *) s_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700746 if (stream_info != NULL)
747 free(stream_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800748 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Latad13758f2020-08-06 15:11:36 -0700749 ALOGV("%s: Added stream in io_streams_map with handle %d", __func__, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700750 return 0;
751}
752
753static inline void io_streams_map_remove(struct audio_device *adev,
754 audio_io_handle_t handle)
755{
756 pthread_mutex_lock(&adev->lock);
757 struct audio_stream_info *s_info =
758 hashmapRemove(adev->io_streams_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700759 if (s_info == NULL)
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800760 goto done;
Aniket Kumar Latad13758f2020-08-06 15:11:36 -0700761 ALOGV("%s: Removed stream with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800762 patch_map_remove_l(adev, s_info->patch_handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700763 free(s_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800764done:
765 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700766 return;
767}
768
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800769static struct audio_patch_info* fetch_patch_info_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700770 audio_patch_handle_t handle)
771{
772 struct audio_patch_info *p_info = NULL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700773 p_info = (struct audio_patch_info *)
774 hashmapGet(adev->patch_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700775 return p_info;
776}
777
vivek mehtaa76401a2015-04-24 14:12:15 -0700778__attribute__ ((visibility ("default")))
779bool audio_hw_send_gain_dep_calibration(int level) {
780 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700781 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700782
783 pthread_mutex_lock(&adev_init_lock);
784
785 if (adev != NULL && adev->platform != NULL) {
786 pthread_mutex_lock(&adev->lock);
787 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700788
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530789 // cache level info for any of the use case which
790 // was not started.
791 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700792
vivek mehtaa76401a2015-04-24 14:12:15 -0700793 pthread_mutex_unlock(&adev->lock);
794 } else {
795 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
796 }
797
798 pthread_mutex_unlock(&adev_init_lock);
799
800 return ret_val;
801}
802
Ashish Jain5106d362016-05-11 19:23:33 +0530803static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
804{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800805 bool gapless_enabled = false;
806 const char *mixer_ctl_name = "Compress Gapless Playback";
807 struct mixer_ctl *ctl;
808
809 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700810 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530811
812 /*Disable gapless if its AV playback*/
813 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800814
815 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
816 if (!ctl) {
817 ALOGE("%s: Could not get ctl for mixer cmd - %s",
818 __func__, mixer_ctl_name);
819 return -EINVAL;
820 }
821
822 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
823 ALOGE("%s: Could not set gapless mode %d",
824 __func__, gapless_enabled);
825 return -EINVAL;
826 }
827 return 0;
828}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700829
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700830__attribute__ ((visibility ("default")))
831int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
832 int table_size) {
833 int ret_val = 0;
834 ALOGV("%s: enter ... ", __func__);
835
836 pthread_mutex_lock(&adev_init_lock);
837 if (adev == NULL) {
838 ALOGW("%s: adev is NULL .... ", __func__);
839 goto done;
840 }
841
842 pthread_mutex_lock(&adev->lock);
843 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
844 pthread_mutex_unlock(&adev->lock);
845done:
846 pthread_mutex_unlock(&adev_init_lock);
847 ALOGV("%s: exit ... ", __func__);
848 return ret_val;
849}
850
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800851bool audio_hw_send_qdsp_parameter(int stream_type, float vol, bool active)
Aalique Grahame22e49102018-12-18 14:23:57 -0800852{
853 bool ret = false;
854 ALOGV("%s: enter ...", __func__);
855
856 pthread_mutex_lock(&adev_init_lock);
857
858 if (adev != NULL && adev->platform != NULL) {
859 pthread_mutex_lock(&adev->lock);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800860 ret = audio_extn_qdsp_set_state(adev, stream_type, vol, active);
Aalique Grahame22e49102018-12-18 14:23:57 -0800861 pthread_mutex_unlock(&adev->lock);
862 }
863
864 pthread_mutex_unlock(&adev_init_lock);
865
866 ALOGV("%s: exit with ret %d", __func__, ret);
867 return ret;
868}
Aalique Grahame22e49102018-12-18 14:23:57 -0800869
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700870static bool is_supported_format(audio_format_t format)
871{
Eric Laurent86e17132013-09-12 17:49:30 -0700872 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530873 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530874 format == AUDIO_FORMAT_AAC_LC ||
875 format == AUDIO_FORMAT_AAC_HE_V1 ||
876 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530877 format == AUDIO_FORMAT_AAC_ADTS_LC ||
878 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
879 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530880 format == AUDIO_FORMAT_AAC_LATM_LC ||
881 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
882 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530883 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
884 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530885 format == AUDIO_FORMAT_PCM_FLOAT ||
886 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700887 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530888 format == AUDIO_FORMAT_AC3 ||
889 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700890 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530891 format == AUDIO_FORMAT_DTS ||
892 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800893 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530894 format == AUDIO_FORMAT_ALAC ||
895 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530896 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530897 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800898 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530899 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700900 format == AUDIO_FORMAT_APTX ||
901 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800902 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700903
904 return false;
905}
906
Kunlei Zhang67cc7072020-12-18 17:16:49 +0800907static bool is_supported_conc_usecase_for_power_mode_call(struct audio_device *adev)
908{
909 struct listnode *node;
910 struct audio_usecase *usecase;
911
912 list_for_each(node, &adev->usecase_list) {
913 usecase = node_to_item(node, struct audio_usecase, list);
914 if (usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
915 ALOGD("%s: FM usecase is active, not setting power mode", __func__);
916 return false;
917 }
918 }
919
920 return true;
921}
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700922static inline bool is_mmap_usecase(audio_usecase_t uc_id)
923{
924 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
Zhou Song62ea0282020-03-22 19:53:01 +0800925 (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY2) ||
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700926 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
927}
928
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700929static inline bool is_valid_volume(float left, float right)
930{
931 return ((left >= 0.0f && right >= 0.0f) ? true : false);
932}
933
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530934static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530935{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530936 ALOGV("%s", __func__);
937 audio_route_apply_and_update_path(adev->audio_route,
938 "asrc-mode");
939 adev->asrc_mode_enabled = true;
940}
941
942static void disable_asrc_mode(struct audio_device *adev)
943{
944 ALOGV("%s", __func__);
945 audio_route_reset_and_update_path(adev->audio_route,
946 "asrc-mode");
947 adev->asrc_mode_enabled = false;
948}
949
Saurav Kumarc1411662020-10-14 10:50:45 +0530950static void check_and_configure_headphone(struct audio_device *adev,
951 struct audio_usecase *uc_info,
952 snd_device_t snd_device)
953{
954 struct listnode *node;
955 struct audio_usecase *usecase;
956 int new_backend_idx, usecase_backend_idx;
957 bool spkr_hph_single_be_native_concurrency;
958
959 new_backend_idx = platform_get_backend_index(snd_device);
960 spkr_hph_single_be_native_concurrency = platform_get_spkr_hph_single_be_native_concurrency_flag();
Zhou Songd4b18c42021-01-14 15:15:29 +0800961 if ((spkr_hph_single_be_native_concurrency && (new_backend_idx == DEFAULT_CODEC_BACKEND)) ||
962 uc_info->id == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
Saurav Kumarc1411662020-10-14 10:50:45 +0530963 list_for_each(node, &adev->usecase_list) {
964 usecase = node_to_item(node, struct audio_usecase, list);
965 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
966 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
967 if (((usecase_backend_idx == HEADPHONE_BACKEND) ||
968 (usecase_backend_idx == HEADPHONE_44_1_BACKEND)) &&
969 ((usecase->stream.out->sample_rate % OUTPUT_SAMPLING_RATE_44100) == 0)) {
970 disable_audio_route(adev, usecase);
971 disable_snd_device(adev, usecase->out_snd_device);
972 usecase->stream.out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Saurav Kumar70902382020-10-28 11:16:04 +0530973 platform_check_and_set_codec_backend_cfg(adev, usecase,
974 usecase->out_snd_device);
Saurav Kumarc1411662020-10-14 10:50:45 +0530975 enable_snd_device(adev, usecase->out_snd_device);
Zhou Songd4b18c42021-01-14 15:15:29 +0800976 enable_audio_route(adev, usecase);
Saurav Kumarc1411662020-10-14 10:50:45 +0530977 }
978 }
Revathi Uddaraju2c0eac02021-07-27 02:06:42 -0700979 else if ((usecase->type != PCM_CAPTURE) && (usecase == uc_info)) {
980 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
981 if (((usecase_backend_idx == HEADPHONE_BACKEND) ||
982 (usecase_backend_idx == HEADPHONE_44_1_BACKEND)) &&
983 ((usecase->stream.out->sample_rate % OUTPUT_SAMPLING_RATE_44100) == 0)) {
984 usecase->stream.out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
985 platform_check_and_set_codec_backend_cfg(adev, usecase,
986 usecase->out_snd_device);
987 }
988 }
Saurav Kumarc1411662020-10-14 10:50:45 +0530989 }
990 }
991}
992
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530993/*
994 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
995 * 44.1 or Native DSD backends are enabled for any of current use case.
996 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
997 * - Disable current mix path use case(Headphone backend) and re-enable it with
998 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
999 * e.g. Naitve DSD or Headphone 44.1 -> + 48
1000 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301001static void check_and_set_asrc_mode(struct audio_device *adev,
1002 struct audio_usecase *uc_info,
1003 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301004{
1005 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301006 int i, num_new_devices = 0;
1007 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
1008 /*
1009 *Split snd device for new combo use case
1010 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
1011 */
1012 if (platform_split_snd_device(adev->platform,
1013 snd_device,
1014 &num_new_devices,
1015 split_new_snd_devices) == 0) {
1016 for (i = 0; i < num_new_devices; i++)
1017 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
1018 } else {
1019 int new_backend_idx = platform_get_backend_index(snd_device);
1020 if (((new_backend_idx == HEADPHONE_BACKEND) ||
1021 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
1022 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
1023 !adev->asrc_mode_enabled) {
1024 struct listnode *node = NULL;
1025 struct audio_usecase *uc = NULL;
1026 struct stream_out *curr_out = NULL;
1027 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
1028 int i, num_devices, ret = 0;
1029 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301030
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301031 list_for_each(node, &adev->usecase_list) {
1032 uc = node_to_item(node, struct audio_usecase, list);
1033 curr_out = (struct stream_out*) uc->stream.out;
1034 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
1035 /*
1036 *Split snd device for existing combo use case
1037 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
1038 */
1039 ret = platform_split_snd_device(adev->platform,
1040 uc->out_snd_device,
1041 &num_devices,
1042 split_snd_devices);
1043 if (ret < 0 || num_devices == 0) {
1044 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
1045 split_snd_devices[0] = uc->out_snd_device;
1046 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -08001047 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301048 for (i = 0; i < num_devices; i++) {
1049 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
1050 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
1051 if((new_backend_idx == HEADPHONE_BACKEND) &&
1052 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
1053 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07001054 ALOGV("%s:DSD or native stream detected enabling asrcmode in hardware",
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301055 __func__);
1056 enable_asrc_mode(adev);
1057 break;
1058 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
1059 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
1060 (usecase_backend_idx == HEADPHONE_BACKEND)) {
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07001061 ALOGV("%s: 48K stream detected, disabling and enabling it \
1062 with asrcmode in hardware", __func__);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301063 disable_audio_route(adev, uc);
1064 disable_snd_device(adev, uc->out_snd_device);
1065 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
1066 if (new_backend_idx == DSD_NATIVE_BACKEND)
1067 audio_route_apply_and_update_path(adev->audio_route,
1068 "hph-true-highquality-mode");
1069 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
1070 (curr_out->bit_width >= 24))
1071 audio_route_apply_and_update_path(adev->audio_route,
1072 "hph-highquality-mode");
1073 enable_asrc_mode(adev);
1074 enable_snd_device(adev, uc->out_snd_device);
1075 enable_audio_route(adev, uc);
1076 break;
1077 }
1078 }
1079 // reset split devices count
1080 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -08001081 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301082 if (adev->asrc_mode_enabled)
1083 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301084 }
1085 }
1086 }
1087}
1088
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001089static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
1090 struct audio_effect_config effect_config,
1091 unsigned int param_value)
1092{
1093 char mixer_ctl_name[] = "Audio Effect";
1094 struct mixer_ctl *ctl;
1095 long set_values[6];
Eric Laurent637e2d42018-11-15 12:24:31 -08001096 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001097
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001098 if (in == NULL) {
1099 ALOGE("%s: active input stream is NULL", __func__);
1100 return -EINVAL;
1101 }
1102
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001103 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1104 if (!ctl) {
1105 ALOGE("%s: Could not get mixer ctl - %s",
1106 __func__, mixer_ctl_name);
1107 return -EINVAL;
1108 }
1109
1110 set_values[0] = 1; //0:Rx 1:Tx
1111 set_values[1] = in->app_type_cfg.app_type;
1112 set_values[2] = (long)effect_config.module_id;
1113 set_values[3] = (long)effect_config.instance_id;
1114 set_values[4] = (long)effect_config.param_id;
1115 set_values[5] = param_value;
1116
1117 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
1118
1119 return 0;
1120
1121}
1122
1123static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
1124 int effect_type, unsigned int *param_value)
1125{
1126 int ret = 0;
1127 struct audio_effect_config other_effect_config;
1128 struct audio_usecase *usecase = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08001129 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001130
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001131 if (in == NULL) {
1132 ALOGE("%s: active input stream is NULL", __func__);
1133 return -EINVAL;
1134 }
1135
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001136 usecase = get_usecase_from_list(adev, in->usecase);
1137 if (!usecase)
1138 return -EINVAL;
1139
1140 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
1141 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
1142 if (ret < 0) {
1143 ALOGE("%s Failed to get effect params %d", __func__, ret);
1144 return ret;
1145 }
1146
1147 if (module_id == other_effect_config.module_id) {
1148 //Same module id for AEC/NS. Values need to be combined
1149 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
1150 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
1151 *param_value |= other_effect_config.param_value;
1152 }
1153 }
1154
1155 return ret;
1156}
1157
1158static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
Gangadhar Sb0210342019-02-22 17:39:41 +05301159{
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001160 struct audio_effect_config effect_config;
1161 struct audio_usecase *usecase = NULL;
1162 int ret = 0;
1163 unsigned int param_value = 0;
Eric Laurent637e2d42018-11-15 12:24:31 -08001164 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001165
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001166 if(!voice_extn_is_dynamic_ecns_enabled())
1167 return ENOSYS;
1168
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001169 if (!in) {
1170 ALOGE("%s: Invalid input stream", __func__);
1171 return -EINVAL;
1172 }
1173
1174 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
1175
1176 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +08001177 if (usecase == NULL) {
1178 ALOGE("%s: Could not find the usecase (%d) in the list",
1179 __func__, in->usecase);
1180 return -EINVAL;
1181 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001182
1183 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
1184 if (ret < 0) {
1185 ALOGE("%s Failed to get module id %d", __func__, ret);
1186 return ret;
1187 }
1188 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
1189 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
1190
1191 if(enable)
1192 param_value = effect_config.param_value;
1193
1194 /*Special handling for AEC & NS effects Param values need to be
1195 updated if module ids are same*/
1196
1197 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
1198 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
1199 if (ret < 0)
1200 return ret;
1201 }
1202
1203 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
1204
1205 return ret;
1206}
1207
1208static void check_and_enable_effect(struct audio_device *adev)
1209{
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001210 if(!voice_extn_is_dynamic_ecns_enabled())
1211 return;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001212
Eric Laurent637e2d42018-11-15 12:24:31 -08001213 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001214
Eric Laurent637e2d42018-11-15 12:24:31 -08001215 if (in != NULL && !in->standby) {
1216 if (in->enable_aec)
1217 enable_disable_effect(adev, EFFECT_AEC, true);
1218
1219 if (in->enable_ns &&
1220 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1221 enable_disable_effect(adev, EFFECT_NS, true);
1222 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001223 }
1224}
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001225
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001226int pcm_ioctl(struct pcm *pcm, int request, ...)
1227{
1228 va_list ap;
1229 void * arg;
1230 int pcm_fd = *(int*)pcm;
1231
1232 va_start(ap, request);
1233 arg = va_arg(ap, void *);
1234 va_end(ap);
1235
1236 return ioctl(pcm_fd, request, arg);
1237}
1238
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001239int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001240 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001241{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001242 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001243 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +05301244 struct stream_out *out = NULL;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301245 struct stream_in *in = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001246 struct listnode out_devices;
Soumya Managoli6993b762018-06-28 16:04:57 +05301247 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001248
1249 if (usecase == NULL)
1250 return -EINVAL;
1251
1252 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
1253
Carter Hsu2e429db2019-05-14 18:50:52 +08001254 if (usecase->type == PCM_CAPTURE) {
1255 struct stream_in *in = usecase->stream.in;
1256 struct audio_usecase *uinfo;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001257 snd_device = usecase->in_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001258
1259 if (in) {
1260 if (in->enable_aec || in->enable_ec_port) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001261 list_init(&out_devices);
1262 update_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "", true);
Carter Hsu2e429db2019-05-14 18:50:52 +08001263 struct listnode *node;
1264 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1265 USECASE_AUDIO_PLAYBACK_VOIP);
1266 if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001267 assign_devices(&out_devices,
1268 &voip_usecase->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001269 } else if (adev->primary_output &&
1270 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001271 assign_devices(&out_devices,
1272 &adev->primary_output->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001273 } else {
1274 list_for_each(node, &adev->usecase_list) {
1275 uinfo = node_to_item(node, struct audio_usecase, list);
1276 if (uinfo->type != PCM_CAPTURE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001277 assign_devices(&out_devices,
1278 &uinfo->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001279 break;
1280 }
1281 }
1282 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001283
1284 platform_set_echo_reference(adev, true, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001285 in->ec_opened = true;
1286 }
1287 }
Guodong Huf5e614d2019-06-24 18:42:03 +08001288 } else if ((usecase->type == TRANSCODE_LOOPBACK_TX) || ((usecase->type == PCM_HFP_CALL) &&
1289 ((usecase->id == USECASE_AUDIO_HFP_SCO) || (usecase->id == USECASE_AUDIO_HFP_SCO_WB)) &&
1290 (usecase->in_snd_device == SND_DEVICE_IN_VOICE_SPEAKER_MIC_HFP_MMSECNS))) {
Carter Hsu2e429db2019-05-14 18:50:52 +08001291 snd_device = usecase->in_snd_device;
1292 } else {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001293 snd_device = usecase->out_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001294 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001295
Kunlei Zhanga3c4cb02021-03-05 16:03:54 +08001296 if (usecase->type == PCM_CAPTURE) {
1297 if (platform_get_fluence_nn_state(adev->platform) == 0) {
1298 platform_set_fluence_nn_state(adev->platform, true);
1299 ALOGD("%s: set fluence nn capture state", __func__);
1300 }
1301 }
1302
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001303#ifdef DS1_DOLBY_DAP_ENABLED
1304 audio_extn_dolby_set_dmid(adev);
1305 audio_extn_dolby_set_endpoint(adev);
1306#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001307 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001308 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301309 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001310 audio_extn_utils_send_app_type_cfg(adev, usecase);
Jasmine Cha4dcc1092019-03-04 18:12:47 +08001311 if (audio_extn_is_maxx_audio_enabled())
1312 audio_extn_ma_set_device(usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301313 audio_extn_utils_send_audio_calibration(adev, usecase);
Zhou Songbaddf9f2020-11-20 13:57:39 +08001314 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1315 out = usecase->stream.out;
1316 if (out && out->compr)
Manish Dewangan58229382017-02-02 15:48:41 +05301317 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1318 }
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301319
1320 if (usecase->type == PCM_CAPTURE) {
Kunlei Zhanga3c4cb02021-03-05 16:03:54 +08001321 if (platform_get_fluence_nn_state(adev->platform) == 1 &&
1322 adev->fluence_nn_usecase_id == USECASE_INVALID ) {
1323 adev->fluence_nn_usecase_id = usecase->id;
1324 ALOGD("%s: assign fluence nn usecase %d", __func__, usecase->id);
1325 }
1326 }
1327
1328 if (usecase->type == PCM_CAPTURE) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301329 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001330 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301331 ALOGD("%s: set custom mtmx params v1", __func__);
1332 audio_extn_set_custom_mtmx_params_v1(adev, usecase, true);
1333 }
1334 } else {
1335 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
1336 }
Manish Dewangan58229382017-02-02 15:48:41 +05301337
Andy Hung756ecc12018-10-19 17:47:12 -07001338 // we shouldn't truncate mixer_path
1339 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1340 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1341 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001342 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001343 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301344 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1345 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1346 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1347 if (parms) {
1348 audio_extn_fm_set_parameters(adev, parms);
1349 str_parms_destroy(parms);
1350 }
1351 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001352 ALOGV("%s: exit", __func__);
1353 return 0;
1354}
1355
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001356int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001357 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001358{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001359 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001360 char mixer_path[MIXER_PATH_MAX_LENGTH];
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301361 struct stream_in *in = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001362
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301363 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001364 return -EINVAL;
1365
1366 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301367 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001368 snd_device = usecase->in_snd_device;
1369 else
1370 snd_device = usecase->out_snd_device;
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001371
1372 /* disable island and power mode on supported device for voice call */
1373 if (usecase->type == VOICE_CALL) {
1374 if (usecase->in_snd_device != SND_DEVICE_NONE) {
1375 if (platform_get_island_cfg_on_device(adev->platform, usecase->in_snd_device) &&
1376 platform_get_power_mode_on_device(adev->platform, usecase->in_snd_device)) {
1377 platform_set_island_cfg_on_device(adev, usecase->in_snd_device, false);
1378 platform_set_power_mode_on_device(adev, usecase->in_snd_device, false);
1379 platform_reset_island_power_status(adev->platform, usecase->in_snd_device);
Kunlei Zhang91c4b332020-07-20 17:53:14 +08001380 if (voice_is_lte_call_active(adev))
1381 platform_set_tx_lpi_mode(adev->platform, false);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001382 ALOGD("%s: disable island cfg and power mode in voice tx path",
1383 __func__);
1384 }
1385 }
1386 if (usecase->out_snd_device != SND_DEVICE_NONE) {
1387 if (platform_get_island_cfg_on_device(adev->platform, usecase->out_snd_device) &&
1388 platform_get_power_mode_on_device(adev->platform, usecase->out_snd_device)) {
1389 platform_set_island_cfg_on_device(adev, usecase->out_snd_device, false);
1390 platform_set_power_mode_on_device(adev, usecase->out_snd_device, false);
1391 platform_reset_island_power_status(adev->platform, usecase->out_snd_device);
1392 ALOGD("%s: disable island cfg and power mode in voice rx path",
1393 __func__);
1394 }
1395 }
1396 }
1397
Andy Hung756ecc12018-10-19 17:47:12 -07001398 // we shouldn't truncate mixer_path
1399 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1400 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1401 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001402 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001403 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001404 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Carter Hsu2e429db2019-05-14 18:50:52 +08001405 if (usecase->type == PCM_CAPTURE) {
1406 struct stream_in *in = usecase->stream.in;
1407 if (in && in->ec_opened) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001408 struct listnode out_devices;
1409 list_init(&out_devices);
1410 platform_set_echo_reference(in->dev, false, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001411 in->ec_opened = false;
1412 }
1413 }
Kunlei Zhanga3c4cb02021-03-05 16:03:54 +08001414 if (usecase->id == adev->fluence_nn_usecase_id) {
1415 platform_set_fluence_nn_state(adev->platform, false);
1416 adev->fluence_nn_usecase_id = USECASE_INVALID;
1417 ALOGD("%s: reset fluence nn capture state", __func__);
1418 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001419 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301420 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301421
1422 if (usecase->type == PCM_CAPTURE) {
1423 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001424 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301425 ALOGD("%s: reset custom mtmx params v1", __func__);
1426 audio_extn_set_custom_mtmx_params_v1(adev, usecase, false);
1427 }
1428 } else {
1429 audio_extn_set_custom_mtmx_params_v2(adev, usecase, false);
1430 }
1431
Weiyin Jiang298ffd92019-06-03 14:29:30 +08001432 if ((usecase->type == PCM_PLAYBACK) &&
1433 (usecase->stream.out != NULL))
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05301434 usecase->stream.out->pspd_coeff_sent = false;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301435
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001436 ALOGV("%s: exit", __func__);
1437 return 0;
1438}
1439
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001440int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001441 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001442{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301443 int i, num_devices = 0;
1444 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001445 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1446
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001447 if (snd_device < SND_DEVICE_MIN ||
1448 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001449 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001450 return -EINVAL;
1451 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001452
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001453 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001454 ALOGE("%s: Invalid sound device returned", __func__);
1455 return -EINVAL;
1456 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001457
1458 adev->snd_dev_ref_cnt[snd_device]++;
1459
1460 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1461 (platform_split_snd_device(adev->platform,
1462 snd_device,
1463 &num_devices,
1464 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001465 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001466 __func__, snd_device, device_name);
Aniket Kumar Lata990de552019-07-11 14:20:23 -07001467 /* Set backend config for A2DP to ensure slimbus configuration
1468 is correct if A2DP is already active and backend is closed
1469 and re-opened */
1470 if (snd_device == SND_DEVICE_OUT_BT_A2DP)
1471 audio_extn_a2dp_set_source_backend_cfg();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001472 return 0;
1473 }
1474
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001475 if (audio_extn_spkr_prot_is_enabled())
1476 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001477
Aalique Grahame22e49102018-12-18 14:23:57 -08001478 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1479
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001480 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1481 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001482 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1483 goto err;
1484 }
1485 audio_extn_dev_arbi_acquire(snd_device);
Daniel Hillenbrand17873952013-05-23 10:10:00 +05301486 amplifier_enable_devices(snd_device, true);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001487 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001488 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001489 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001490 goto err;
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001491 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001492 } else if (platform_split_snd_device(adev->platform,
1493 snd_device,
1494 &num_devices,
1495 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301496 for (i = 0; i < num_devices; i++) {
1497 enable_snd_device(adev, new_snd_devices[i]);
1498 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001499 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001500 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001501 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301502
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001503 /* enable island and power mode on supported device */
1504 if (platform_get_island_cfg_on_device(adev->platform, snd_device) &&
1505 platform_get_power_mode_on_device(adev->platform, snd_device)) {
1506 platform_set_island_cfg_on_device(adev, snd_device, true);
1507 platform_set_power_mode_on_device(adev, snd_device, true);
Kunlei Zhang91c4b332020-07-20 17:53:14 +08001508 if (voice_is_lte_call_active(adev) &&
1509 (snd_device >= SND_DEVICE_IN_BEGIN &&
1510 snd_device < SND_DEVICE_IN_END))
1511 platform_set_tx_lpi_mode(adev->platform, true);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001512 ALOGD("%s: enable island cfg and power mode on: %s",
1513 __func__, device_name);
1514 }
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301515
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301516 if (SND_DEVICE_OUT_BT_A2DP == snd_device) {
Ramjee Singh2d2944a2021-12-14 14:13:41 +05301517
1518 struct audio_usecase *usecase;
1519 struct listnode *node;
1520 /* Disable SCO Devices and enable handset mic for active input stream */
1521 list_for_each(node, &adev->usecase_list) {
1522 usecase = node_to_item(node, struct audio_usecase, list);
1523 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
1524 is_sco_in_device_type(&usecase->stream.in->device_list)) {
1525 ALOGD("a2dp resumed, switch bt sco mic to handset mic");
1526 reassign_device_list(&usecase->stream.in->device_list,
1527 AUDIO_DEVICE_IN_BUILTIN_MIC, "");
1528 select_devices(adev, usecase->id);
1529 }
1530 }
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301531 if (audio_extn_a2dp_start_playback() < 0) {
1532 ALOGE(" fail to configure A2dp Source control path ");
1533 goto err;
1534 } else {
1535 adev->a2dp_started = true;
1536 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001537 }
Florian Pfister1a84f312018-07-19 14:38:18 +02001538
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001539 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1540 (audio_extn_a2dp_start_capture() < 0)) {
1541 ALOGE(" fail to configure A2dp Sink control path ");
1542 goto err;
1543 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301544
Mingshu Pang7be5b1d2020-03-04 15:24:38 +08001545 if ((SND_DEVICE_OUT_BT_SCO_SWB == snd_device) ||
1546 (SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC == snd_device) ||
1547 (SND_DEVICE_IN_BT_SCO_MIC_SWB == snd_device)) {
1548 if (!adev->bt_sco_on || (audio_extn_sco_start_configuration() < 0)) {
1549 ALOGE(" fail to configure sco control path ");
1550 goto err;
1551 }
Zhou Song12c29502019-03-16 10:37:18 +08001552 }
1553
Zhou Song331c8e52019-08-26 14:16:12 +08001554 configure_btsco_sample_rate(snd_device);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001555 /* due to the possibility of calibration overwrite between listen
1556 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001557 audio_extn_sound_trigger_update_device_status(snd_device,
1558 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301559 audio_extn_listen_update_device_status(snd_device,
1560 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001561 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001562 audio_extn_sound_trigger_update_device_status(snd_device,
1563 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301564 audio_extn_listen_update_device_status(snd_device,
1565 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001566 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001567 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001568 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001569 audio_route_apply_and_update_path(adev->audio_route, device_name);
Daniel Hillenbrand17873952013-05-23 10:10:00 +05301570 amplifier_set_feedback(adev, snd_device, true);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301571
1572 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1573 !adev->native_playback_enabled &&
1574 audio_is_true_native_stream_active(adev)) {
1575 ALOGD("%s: %d: napb: enabling native mode in hardware",
1576 __func__, __LINE__);
1577 audio_route_apply_and_update_path(adev->audio_route,
1578 "true-native-mode");
1579 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301580 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301581 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1582 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001583 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001584 ALOGD("%s: init ec ref loopback", __func__);
1585 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1586 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001587 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001588 return 0;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001589err:
1590 adev->snd_dev_ref_cnt[snd_device]--;
1591 return -EINVAL;;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001592}
1593
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001594int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001595 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001596{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301597 int i, num_devices = 0;
1598 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001599 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1600
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001601 if (snd_device < SND_DEVICE_MIN ||
1602 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001603 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001604 return -EINVAL;
1605 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001606
1607 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1608 ALOGE("%s: Invalid sound device returned", __func__);
1609 return -EINVAL;
1610 }
1611
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001612 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1613 ALOGE("%s: device ref cnt is already 0", __func__);
1614 return -EINVAL;
1615 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001616
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001617 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001618
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001619
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001620 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001621 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301622
Aalique Grahame22e49102018-12-18 14:23:57 -08001623 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1624
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001625 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1626 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001627 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001628
1629 // when speaker device is disabled, reset swap.
1630 // will be renabled on usecase start
1631 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001632 } else if (platform_split_snd_device(adev->platform,
1633 snd_device,
1634 &num_devices,
1635 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301636 for (i = 0; i < num_devices; i++) {
1637 disable_snd_device(adev, new_snd_devices[i]);
1638 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001639 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001640 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001641 audio_route_reset_and_update_path(adev->audio_route, device_name);
Daniel Hillenbrand17873952013-05-23 10:10:00 +05301642 amplifier_enable_devices(snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001643 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001644
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301645 if (snd_device == SND_DEVICE_OUT_BT_A2DP) {
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301646 audio_extn_a2dp_stop_playback();
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301647 adev->a2dp_started = false;
1648 } else if (snd_device == SND_DEVICE_IN_BT_A2DP)
Florian Pfister1a84f312018-07-19 14:38:18 +02001649 audio_extn_a2dp_stop_capture();
Zhou Songd6d71752019-05-21 18:08:51 +08001650 else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001651 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
Ashish Jain81eb2a82015-05-13 10:52:34 +05301652 adev->is_channel_status_set = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001653 else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301654 adev->native_playback_enabled) {
1655 ALOGD("%s: %d: napb: disabling native mode in hardware",
1656 __func__, __LINE__);
1657 audio_route_reset_and_update_path(adev->audio_route,
1658 "true-native-mode");
1659 adev->native_playback_enabled = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001660 } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301661 adev->asrc_mode_enabled) {
1662 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301663 disable_asrc_mode(adev);
1664 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001665 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301666 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001667 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001668 ALOGD("%s: deinit ec ref loopback", __func__);
1669 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1670 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001671
1672 audio_extn_utils_release_snd_device(snd_device);
Daniel Hillenbrand17873952013-05-23 10:10:00 +05301673 amplifier_set_feedback(adev, snd_device, false);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001674 } else {
1675 if (platform_split_snd_device(adev->platform,
1676 snd_device,
1677 &num_devices,
1678 new_snd_devices) == 0) {
1679 for (i = 0; i < num_devices; i++) {
1680 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1681 }
1682 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001683 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001684
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001685 return 0;
1686}
1687
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001688/*
1689 legend:
1690 uc - existing usecase
1691 new_uc - new usecase
1692 d1, d11, d2 - SND_DEVICE enums
1693 a1, a2 - corresponding ANDROID device enums
1694 B1, B2 - backend strings
1695
1696case 1
1697 uc->dev d1 (a1) B1
1698 new_uc->dev d1 (a1), d2 (a2) B1, B2
1699
1700 resolution: disable and enable uc->dev on d1
1701
1702case 2
1703 uc->dev d1 (a1) B1
1704 new_uc->dev d11 (a1) B1
1705
1706 resolution: need to switch uc since d1 and d11 are related
1707 (e.g. speaker and voice-speaker)
1708 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1709
1710case 3
1711 uc->dev d1 (a1) B1
1712 new_uc->dev d2 (a2) B2
1713
1714 resolution: no need to switch uc
1715
1716case 4
1717 uc->dev d1 (a1) B1
1718 new_uc->dev d2 (a2) B1
1719
1720 resolution: disable enable uc-dev on d2 since backends match
1721 we cannot enable two streams on two different devices if they
1722 share the same backend. e.g. if offload is on speaker device using
1723 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1724 using the same backend, offload must also be switched to voice-handset.
1725
1726case 5
1727 uc->dev d1 (a1) B1
1728 new_uc->dev d1 (a1), d2 (a2) B1
1729
1730 resolution: disable enable uc-dev on d2 since backends match
1731 we cannot enable two streams on two different devices if they
1732 share the same backend.
1733
1734case 6
1735 uc->dev d1 (a1) B1
1736 new_uc->dev d2 (a1) B2
1737
1738 resolution: no need to switch
1739
1740case 7
1741 uc->dev d1 (a1), d2 (a2) B1, B2
1742 new_uc->dev d1 (a1) B1
1743
1744 resolution: no need to switch
1745
Zhou Song4ba65882018-07-09 14:48:07 +08001746case 8
1747 uc->dev d1 (a1) B1
1748 new_uc->dev d11 (a1), d2 (a2) B1, B2
1749 resolution: compared to case 1, for this case, d1 and d11 are related
1750 then need to do the same as case 2 to siwtch to new uc
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301751
1752case 9
1753 uc->dev d1 (a1), d2(a2) B1 B2
1754 new_uc->dev d1 (a1), d22 (a2) B1, B2
1755 resolution: disable enable uc-dev on d2 since backends match
1756 we cannot enable two streams on two different devices if they
1757 share the same backend. This is special case for combo use case
1758 with a2dp and sco devices which uses same backend.
1759 e.g. speaker-a2dp and speaker-btsco
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001760*/
1761static snd_device_t derive_playback_snd_device(void * platform,
1762 struct audio_usecase *uc,
1763 struct audio_usecase *new_uc,
1764 snd_device_t new_snd_device)
1765{
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001766 struct listnode a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001767
1768 snd_device_t d1 = uc->out_snd_device;
1769 snd_device_t d2 = new_snd_device;
1770
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001771 list_init(&a1);
1772 list_init(&a2);
1773
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301774 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301775 case TRANSCODE_LOOPBACK_RX :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001776 assign_devices(&a1, &uc->stream.inout->out_config.device_list);
1777 assign_devices(&a2, &new_uc->stream.inout->out_config.device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301778 break;
1779 default :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001780 assign_devices(&a1, &uc->stream.out->device_list);
1781 assign_devices(&a2, &new_uc->stream.out->device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301782 break;
1783 }
1784
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001785 // Treat as a special case when a1 and a2 are not disjoint
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001786 if (!compare_devices(&a1, &a2) &&
1787 compare_devices_for_any_match(&a1 ,&a2)) {
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001788 snd_device_t d3[2];
1789 int num_devices = 0;
1790 int ret = platform_split_snd_device(platform,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001791 list_length(&a1) > 1 ? d1 : d2,
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001792 &num_devices,
1793 d3);
1794 if (ret < 0) {
1795 if (ret != -ENOSYS) {
1796 ALOGW("%s failed to split snd_device %d",
1797 __func__,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001798 list_length(&a1) > 1 ? d1 : d2);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001799 }
1800 goto end;
1801 }
1802
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001803 if (platform_check_backends_match(d3[0], d3[1])) {
1804 return d2; // case 5
1805 } else {
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301806 if ((list_length(&a1) > 1) && (list_length(&a2) > 1) &&
1807 platform_check_backends_match(d1, d2))
1808 return d2; //case 9
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001809 if (list_length(&a1) > 1)
Samyak Jaind826b502019-07-17 16:16:42 +05301810 return d1; //case 7
Garmond Leungb9eeba42018-09-18 11:10:41 -07001811 // check if d1 is related to any of d3's
1812 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001813 return d1; // case 1
1814 else
1815 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001816 }
1817 } else {
1818 if (platform_check_backends_match(d1, d2)) {
1819 return d2; // case 2, 4
1820 } else {
1821 return d1; // case 6, 3
1822 }
1823 }
1824
1825end:
1826 return d2; // return whatever was calculated before.
1827}
1828
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001829static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301830 struct audio_usecase *uc_info,
1831 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001832{
1833 struct listnode *node;
1834 struct audio_usecase *usecase;
1835 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301836 snd_device_t uc_derive_snd_device;
1837 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001838 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1839 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001840 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301841 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001842 /*
1843 * This function is to make sure that all the usecases that are active on
1844 * the hardware codec backend are always routed to any one device that is
1845 * handled by the hardware codec.
1846 * For example, if low-latency and deep-buffer usecases are currently active
1847 * on speaker and out_set_parameters(headset) is received on low-latency
1848 * output, then we have to make sure deep-buffer is also switched to headset,
1849 * because of the limitation that both the devices cannot be enabled
1850 * at the same time as they share the same backend.
1851 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001852 /*
1853 * This call is to check if we need to force routing for a particular stream
1854 * If there is a backend configuration change for the device when a
1855 * new stream starts, then ADM needs to be closed and re-opened with the new
1856 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001857 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001858 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001859 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1860 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301861 /* For a2dp device reconfigure all active sessions
1862 * with new AFE encoder format based on a2dp state
1863 */
1864 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301865 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device ||
1866 SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP == snd_device) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301867 audio_extn_a2dp_is_force_device_switch()) {
1868 force_routing = true;
1869 force_restart_session = true;
1870 }
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001871
1872 /*
1873 * Island cfg and power mode config needs to set before AFE port start.
1874 * Set force routing in case of voice device was enable before.
1875 */
1876 if (uc_info->type == VOICE_CALL &&
1877 voice_extn_is_voice_power_mode_supported() &&
Kunlei Zhang67cc7072020-12-18 17:16:49 +08001878 is_supported_conc_usecase_for_power_mode_call(adev) &&
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001879 platform_check_and_update_island_power_status(adev->platform,
1880 uc_info,
1881 snd_device)) {
1882 force_routing = true;
1883 ALOGD("%s:becf: force routing %d for power mode supported device",
1884 __func__, force_routing);
1885 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301886 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1887
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001888 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001889 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001890 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001891 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1892 switch_device[i] = false;
1893
1894 list_for_each(node, &adev->usecase_list) {
1895 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001896
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301897 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1898 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301899 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301900 platform_get_snd_device_name(usecase->out_snd_device),
1901 platform_check_backends_match(snd_device, usecase->out_snd_device));
Rahul Sharma99770982019-03-06 17:05:26 +05301902 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
1903 (usecase->type != PCM_PASSTHROUGH)) {
Ashish Jain6a65b352017-03-21 17:24:40 +05301904 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1905 usecase, uc_info, snd_device);
1906 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001907 (is_codec_backend_out_device_type(&usecase->device_list) ||
1908 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1909 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_DEVICE) ||
1910 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_HEADSET) ||
1911 is_a2dp_out_device_type(&usecase->device_list) ||
1912 is_sco_out_device_type(&usecase->device_list)) &&
Ashish Jain6a65b352017-03-21 17:24:40 +05301913 ((force_restart_session) ||
1914 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301915 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1916 __func__, use_case_table[usecase->id],
1917 platform_get_snd_device_name(usecase->out_snd_device));
1918 disable_audio_route(adev, usecase);
1919 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301920 /* Enable existing usecase on derived playback device */
1921 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301922 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301923 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001924 }
1925 }
1926
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301927 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1928 num_uc_to_switch);
1929
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001930 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001931 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001932
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301933 /* Make sure the previous devices to be disabled first and then enable the
1934 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001935 list_for_each(node, &adev->usecase_list) {
1936 usecase = node_to_item(node, struct audio_usecase, list);
1937 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001938 /* Check if output sound device to be switched can be split and if any
1939 of the split devices match with derived sound device */
1940 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1941 &num_devices, split_snd_devices) == 0) {
1942 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
1943 for (i = 0; i < num_devices; i++) {
1944 /* Disable devices that do not match with derived sound device */
1945 if (split_snd_devices[i] != derive_snd_device[usecase->id])
1946 disable_snd_device(adev, split_snd_devices[i]);
1947 }
1948 } else {
1949 disable_snd_device(adev, usecase->out_snd_device);
1950 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001951 }
1952 }
1953
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001954 list_for_each(node, &adev->usecase_list) {
1955 usecase = node_to_item(node, struct audio_usecase, list);
1956 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001957 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1958 &num_devices, split_snd_devices) == 0) {
1959 /* Enable derived sound device only if it does not match with
1960 one of the split sound devices. This is because the matching
1961 sound device was not disabled */
1962 bool should_enable = true;
1963 for (i = 0; i < num_devices; i++) {
1964 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
1965 should_enable = false;
1966 break;
1967 }
1968 }
1969 if (should_enable)
1970 enable_snd_device(adev, derive_snd_device[usecase->id]);
1971 } else {
1972 enable_snd_device(adev, derive_snd_device[usecase->id]);
1973 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001974 }
1975 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001976
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001977 /* Re-route all the usecases on the shared backend other than the
1978 specified usecase to new snd devices */
1979 list_for_each(node, &adev->usecase_list) {
1980 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301981 /* Update the out_snd_device only before enabling the audio route */
1982 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301983 usecase->out_snd_device = derive_snd_device[usecase->id];
Lakshman Chaluvarajuab7e5572020-10-28 19:29:23 +05301984 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
1985 use_case_table[usecase->id],
1986 platform_get_snd_device_name(usecase->out_snd_device));
1987 /* Update voc calibration before enabling Voice/VoIP route */
1988 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL)
1989 status = platform_switch_voice_call_device_post(adev->platform,
1990 usecase->out_snd_device,
1991 platform_get_input_snd_device(
1992 adev->platform, NULL,
1993 &uc_info->device_list,
1994 usecase->type));
1995 enable_audio_route(adev, usecase);
1996 if (usecase->stream.out && usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
1997 out_set_voip_volume(&usecase->stream.out->stream,
1998 usecase->stream.out->volume_l,
1999 usecase->stream.out->volume_r);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05302000 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002001 }
2002 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002003 }
2004}
2005
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302006static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002007 struct audio_usecase *uc_info,
2008 snd_device_t snd_device)
2009{
2010 struct listnode *node;
2011 struct audio_usecase *usecase;
2012 bool switch_device[AUDIO_USECASE_MAX];
2013 int i, num_uc_to_switch = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002014 int backend_check_cond = is_codec_backend_out_device_type(&uc_info->device_list);
kunleiz5cd52b82016-11-07 17:22:52 +08002015 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002016
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302017 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
2018 snd_device);
2019 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05302020
2021 /*
2022 * Make sure out devices is checked against out codec backend device and
2023 * also in devices against in codec backend. Checking out device against in
2024 * codec backend or vice versa causes issues.
2025 */
2026 if (uc_info->type == PCM_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002027 backend_check_cond = is_codec_backend_in_device_type(&uc_info->device_list);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08002028
2029 /*
2030 * Island cfg and power mode config needs to set before AFE port start.
2031 * Set force routing in case of voice device was enable before.
2032 */
2033
2034 if (uc_info->type == VOICE_CALL &&
2035 voice_extn_is_voice_power_mode_supported() &&
Kunlei Zhang67cc7072020-12-18 17:16:49 +08002036 is_supported_conc_usecase_for_power_mode_call(adev) &&
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08002037 platform_check_and_update_island_power_status(adev->platform,
2038 uc_info,
2039 snd_device)) {
2040 force_routing = true;
2041 ALOGD("%s:becf: force routing %d for power mode supported device",
2042 __func__, force_routing);
2043 }
2044
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002045 /*
2046 * This function is to make sure that all the active capture usecases
2047 * are always routed to the same input sound device.
2048 * For example, if audio-record and voice-call usecases are currently
2049 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
2050 * is received for voice call then we have to make sure that audio-record
2051 * usecase is also switched to earpiece i.e. voice-dmic-ef,
2052 * because of the limitation that two devices cannot be enabled
2053 * at the same time if they share the same backend.
2054 */
2055 for (i = 0; i < AUDIO_USECASE_MAX; i++)
2056 switch_device[i] = false;
2057
2058 list_for_each(node, &adev->usecase_list) {
2059 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05302060 /*
2061 * TODO: Enhance below condition to handle BT sco/USB multi recording
2062 */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302063
2064 bool capture_uc_needs_routing = usecase->type != PCM_PLAYBACK && (usecase != uc_info &&
2065 (usecase->in_snd_device != snd_device || force_routing));
2066 bool call_proxy_snd_device = platform_is_call_proxy_snd_device(snd_device) ||
2067 platform_is_call_proxy_snd_device(usecase->in_snd_device);
2068 if (capture_uc_needs_routing && !call_proxy_snd_device &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002069 ((backend_check_cond &&
2070 (is_codec_backend_in_device_type(&usecase->device_list) ||
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08002071 (usecase->type == VOIP_CALL))) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08002072 ((uc_info->type == VOICE_CALL &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002073 is_single_device_type_equal(&usecase->device_list,
2074 AUDIO_DEVICE_IN_VOICE_CALL)) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08002075 platform_check_backends_match(snd_device,\
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002076 usecase->in_snd_device))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07002077 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05302078 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..",
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002079 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07002080 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002081 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002082 switch_device[usecase->id] = true;
2083 num_uc_to_switch++;
2084 }
2085 }
2086
2087 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07002088 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002089
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05302090 /* Make sure the previous devices to be disabled first and then enable the
2091 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002092 list_for_each(node, &adev->usecase_list) {
2093 usecase = node_to_item(node, struct audio_usecase, list);
2094 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002095 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08002096 }
2097 }
2098
2099 list_for_each(node, &adev->usecase_list) {
2100 usecase = node_to_item(node, struct audio_usecase, list);
2101 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002102 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002103 }
2104 }
2105
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002106 /* Re-route all the usecases on the shared backend other than the
2107 specified usecase to new snd devices */
2108 list_for_each(node, &adev->usecase_list) {
2109 usecase = node_to_item(node, struct audio_usecase, list);
2110 /* Update the in_snd_device only before enabling the audio route */
2111 if (switch_device[usecase->id] ) {
2112 usecase->in_snd_device = snd_device;
Lakshman Chaluvarajuab7e5572020-10-28 19:29:23 +05302113 /* Update voc calibration before enabling Voice/VoIP route */
2114 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
2115 snd_device_t voip_snd_device;
2116 voip_snd_device = platform_get_output_snd_device(adev->platform,
2117 usecase->stream.out,
2118 usecase->type);
2119 status = platform_switch_voice_call_device_post(adev->platform,
2120 voip_snd_device,
2121 usecase->in_snd_device);
kunleiz5cd52b82016-11-07 17:22:52 +08002122 }
Lakshman Chaluvarajuab7e5572020-10-28 19:29:23 +05302123 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002124 }
2125 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002126 }
2127}
2128
Mingming Yin3a941d42016-02-17 18:08:05 -08002129static void reset_hdmi_sink_caps(struct stream_out *out) {
2130 int i = 0;
2131
2132 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
2133 out->supported_channel_masks[i] = 0;
2134 }
2135 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
2136 out->supported_formats[i] = 0;
2137 }
2138 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
2139 out->supported_sample_rates[i] = 0;
2140 }
2141}
2142
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002143/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08002144static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002145{
Mingming Yin3a941d42016-02-17 18:08:05 -08002146 int ret = 0, i = 0, j = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002147 int channels = platform_edid_get_max_channels_v2(out->dev->platform,
2148 out->extconn.cs.controller,
2149 out->extconn.cs.stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002150
Mingming Yin3a941d42016-02-17 18:08:05 -08002151 reset_hdmi_sink_caps(out);
2152
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002153 /* Cache ext disp type */
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002154 ret = platform_get_ext_disp_type_v2(adev->platform,
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002155 out->extconn.cs.controller,
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002156 out->extconn.cs.stream);
2157 if(ret < 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002158 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07002159 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002160 }
2161
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002162 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002163 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08002164 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002165 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08002166 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
2167 case 6:
2168 ALOGV("%s: HDMI supports 5.1 channels", __func__);
2169 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
2170 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
2171 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
2172 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
2173 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002174 break;
2175 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08002176 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002177 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002178 break;
2179 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002180
2181 // check channel format caps
2182 i = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002183 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_AC3,
2184 out->extconn.cs.controller,
2185 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002186 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
2187 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
2188 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
2189 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
2190 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
2191 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
2192 }
2193
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002194 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD,
2195 out->extconn.cs.controller,
2196 out->extconn.cs.stream)) {
Ben Romberger1aaaf862017-04-06 17:49:46 -07002197 ALOGV(":%s HDMI supports TRUE HD format", __func__);
2198 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
2199 }
2200
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002201 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS,
2202 out->extconn.cs.controller,
2203 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002204 ALOGV(":%s HDMI supports DTS format", __func__);
2205 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
2206 }
2207
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002208 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS_HD,
2209 out->extconn.cs.controller,
2210 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002211 ALOGV(":%s HDMI supports DTS HD format", __func__);
2212 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
2213 }
2214
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002215 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_IEC61937,
2216 out->extconn.cs.controller,
2217 out->extconn.cs.stream)) {
Naresh Tanniru928f0862017-04-07 16:44:23 -07002218 ALOGV(":%s HDMI supports IEC61937 format", __func__);
2219 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
2220 }
2221
Mingming Yin3a941d42016-02-17 18:08:05 -08002222
2223 // check sample rate caps
2224 i = 0;
2225 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002226 if (platform_is_edid_supported_sample_rate_v2(out->dev->platform, out_hdmi_sample_rates[j],
2227 out->extconn.cs.controller,
2228 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002229 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
2230 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
2231 }
2232 }
2233
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002234 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002235}
2236
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002237static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
2238 uint32_t *supported_sample_rates __unused,
2239 uint32_t max_rates __unused)
2240{
2241 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
2242 supported_sample_rates,
2243 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05302244 ssize_t i = 0;
2245
2246 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002247 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
2248 supported_sample_rates[i]);
2249 }
2250 return count;
2251}
2252
2253static inline int read_usb_sup_channel_masks(bool is_playback,
2254 audio_channel_mask_t *supported_channel_masks,
2255 uint32_t max_masks)
2256{
2257 int channels = audio_extn_usb_get_max_channels(is_playback);
2258 int channel_count;
2259 uint32_t num_masks = 0;
2260 if (channels > MAX_HIFI_CHANNEL_COUNT)
2261 channels = MAX_HIFI_CHANNEL_COUNT;
2262
2263 if (is_playback) {
Eric Laurent68a87112019-05-01 18:07:29 -07002264 // start from 2 channels as framework currently doesn't support mono.
2265 if (channels >= FCC_2) {
2266 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(FCC_2);
2267 }
2268 for (channel_count = FCC_2;
2269 channel_count <= channels && num_masks < max_masks;
2270 ++channel_count) {
2271 supported_channel_masks[num_masks++] =
2272 audio_channel_mask_for_index_assignment_from_count(channel_count);
2273 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002274 } else {
vincenttewf51c94e2019-05-07 10:28:53 +08002275 // For capture we report all supported channel masks from 1 channel up.
2276 channel_count = MIN_CHANNEL_COUNT;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002277 // audio_channel_in_mask_from_count() does the right conversion to either positional or
2278 // indexed mask
Eric Laurent68a87112019-05-01 18:07:29 -07002279 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
2280 audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
2281 if (channel_count <= FCC_2) {
2282 mask = audio_channel_in_mask_from_count(channel_count);
2283 supported_channel_masks[num_masks++] = mask;
2284 }
2285 const audio_channel_mask_t index_mask =
2286 audio_channel_mask_for_index_assignment_from_count(channel_count);
2287 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
2288 supported_channel_masks[num_masks++] = index_mask;
2289 }
2290 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002291 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302292
vincenttewf51c94e2019-05-07 10:28:53 +08002293 for (size_t i = 0; i < num_masks; ++i) {
2294 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
2295 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302296 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002297 return num_masks;
2298}
2299
2300static inline int read_usb_sup_formats(bool is_playback __unused,
2301 audio_format_t *supported_formats,
2302 uint32_t max_formats __unused)
2303{
2304 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
2305 switch (bitwidth) {
2306 case 24:
2307 // XXX : usb.c returns 24 for s24 and s24_le?
2308 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
2309 break;
2310 case 32:
2311 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
2312 break;
2313 case 16:
2314 default :
2315 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
2316 break;
2317 }
2318 ALOGV("%s: %s supported format %d", __func__,
2319 is_playback ? "P" : "C", bitwidth);
2320 return 1;
2321}
2322
2323static inline int read_usb_sup_params_and_compare(bool is_playback,
2324 audio_format_t *format,
2325 audio_format_t *supported_formats,
2326 uint32_t max_formats,
2327 audio_channel_mask_t *mask,
2328 audio_channel_mask_t *supported_channel_masks,
2329 uint32_t max_masks,
2330 uint32_t *rate,
2331 uint32_t *supported_sample_rates,
2332 uint32_t max_rates) {
2333 int ret = 0;
2334 int num_formats;
2335 int num_masks;
2336 int num_rates;
2337 int i;
2338
2339 num_formats = read_usb_sup_formats(is_playback, supported_formats,
2340 max_formats);
2341 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
2342 max_masks);
2343
2344 num_rates = read_usb_sup_sample_rates(is_playback,
2345 supported_sample_rates, max_rates);
2346
2347#define LUT(table, len, what, dflt) \
2348 for (i=0; i<len && (table[i] != what); i++); \
2349 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
2350
2351 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
2352 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
2353 LUT(supported_sample_rates, num_rates, *rate, 0);
2354
2355#undef LUT
2356 return ret < 0 ? -EINVAL : 0; // HACK TBD
2357}
2358
Alexy Josephb1379942016-01-29 15:49:38 -08002359audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002360 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002361{
2362 struct audio_usecase *usecase;
2363 struct listnode *node;
2364
2365 list_for_each(node, &adev->usecase_list) {
2366 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002367 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002368 ALOGV("%s: usecase id %d", __func__, usecase->id);
2369 return usecase->id;
2370 }
2371 }
2372 return USECASE_INVALID;
2373}
2374
Alexy Josephb1379942016-01-29 15:49:38 -08002375struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002376 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002377{
2378 struct audio_usecase *usecase;
2379 struct listnode *node;
2380
2381 list_for_each(node, &adev->usecase_list) {
2382 usecase = node_to_item(node, struct audio_usecase, list);
2383 if (usecase->id == uc_id)
2384 return usecase;
2385 }
2386 return NULL;
2387}
2388
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302389/*
2390 * is a true native playback active
2391 */
2392bool audio_is_true_native_stream_active(struct audio_device *adev)
2393{
2394 bool active = false;
2395 int i = 0;
2396 struct listnode *node;
2397
2398 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
2399 ALOGV("%s:napb: not in true mode or non hdphones device",
2400 __func__);
2401 active = false;
2402 goto exit;
2403 }
2404
2405 list_for_each(node, &adev->usecase_list) {
2406 struct audio_usecase *uc;
2407 uc = node_to_item(node, struct audio_usecase, list);
2408 struct stream_out *curr_out =
2409 (struct stream_out*) uc->stream.out;
2410
2411 if (curr_out && PCM_PLAYBACK == uc->type) {
2412 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
2413 "(%d) device %s", __func__, i++, use_case_table[uc->id],
2414 uc->id, curr_out->sample_rate,
2415 curr_out->bit_width,
2416 platform_get_snd_device_name(uc->out_snd_device));
2417
2418 if (is_offload_usecase(uc->id) &&
2419 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
2420 active = true;
2421 ALOGD("%s:napb:native stream detected", __func__);
2422 }
2423 }
2424 }
2425exit:
2426 return active;
2427}
2428
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002429uint32_t adev_get_dsp_bit_width_enforce_mode()
2430{
2431 if (adev == NULL) {
2432 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
2433 return 0;
2434 }
2435 return adev->dsp_bit_width_enforce_mode;
2436}
2437
2438static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
2439{
2440 char value[PROPERTY_VALUE_MAX];
2441 int trial;
2442 uint32_t dsp_bit_width_enforce_mode = 0;
2443
2444 if (!mixer) {
2445 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
2446 __func__);
2447 return 0;
2448 }
2449
2450 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
2451 value, NULL) > 0) {
2452 trial = atoi(value);
2453 switch (trial) {
2454 case 16:
2455 dsp_bit_width_enforce_mode = 16;
2456 break;
2457 case 24:
2458 dsp_bit_width_enforce_mode = 24;
2459 break;
2460 case 32:
2461 dsp_bit_width_enforce_mode = 32;
2462 break;
2463 default:
2464 dsp_bit_width_enforce_mode = 0;
2465 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
2466 break;
2467 }
2468 }
2469
2470 return dsp_bit_width_enforce_mode;
2471}
2472
2473static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
2474 uint32_t enforce_mode,
2475 bool enable)
2476{
2477 struct mixer_ctl *ctl = NULL;
2478 const char *mixer_ctl_name = "ASM Bit Width";
2479 uint32_t asm_bit_width_mode = 0;
2480
2481 if (enforce_mode == 0) {
2482 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
2483 return;
2484 }
2485
2486 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
2487 if (!ctl) {
2488 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2489 __func__, mixer_ctl_name);
2490 return;
2491 }
2492
2493 if (enable)
2494 asm_bit_width_mode = enforce_mode;
2495 else
2496 asm_bit_width_mode = 0;
2497
2498 ALOGV("%s DSP bit width feature status is %d width=%d",
2499 __func__, enable, asm_bit_width_mode);
2500 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2501 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2502 asm_bit_width_mode);
2503
2504 return;
2505}
2506
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302507/*
2508 * if native DSD playback active
2509 */
2510bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2511{
2512 bool active = false;
2513 struct listnode *node = NULL;
2514 struct audio_usecase *uc = NULL;
2515 struct stream_out *curr_out = NULL;
2516
2517 list_for_each(node, &adev->usecase_list) {
2518 uc = node_to_item(node, struct audio_usecase, list);
2519 curr_out = (struct stream_out*) uc->stream.out;
2520
2521 if (curr_out && PCM_PLAYBACK == uc->type &&
2522 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2523 active = true;
2524 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302525 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302526 }
2527 }
2528 return active;
2529}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302530
2531static bool force_device_switch(struct audio_usecase *usecase)
2532{
2533 bool ret = false;
2534 bool is_it_true_mode = false;
2535
Zhou Song30f2c3e2018-02-08 14:02:15 +08002536 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302537 usecase->type == TRANSCODE_LOOPBACK_RX ||
2538 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002539 return false;
2540 }
2541
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002542 if(usecase->stream.out == NULL) {
2543 ALOGE("%s: stream.out is NULL", __func__);
2544 return false;
2545 }
2546
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302547 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002548 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002549 (compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADSET) ||
2550 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADPHONE))) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302551 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2552 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2553 (!is_it_true_mode && adev->native_playback_enabled)){
2554 ret = true;
2555 ALOGD("napb: time to toggle native mode");
2556 }
2557 }
2558
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302559 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302560 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2561 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002562 if(is_a2dp_out_device_type(&usecase->stream.out->device_list) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302563 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302564 ALOGD("Force a2dp device switch to update new encoder config");
2565 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002566 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302567
Florian Pfister1a84f312018-07-19 14:38:18 +02002568 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302569 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2570 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002571 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302572 return ret;
2573}
2574
Aalique Grahame22e49102018-12-18 14:23:57 -08002575static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2576{
2577 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2578}
2579
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302580bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2581{
2582 bool ret=false;
2583 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
Zhou Song5657f492019-08-07 11:30:39 +08002584 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
2585 out_snd_device == SND_DEVICE_OUT_BT_SCO_SWB) ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302586 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2587 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
Zhou Song5657f492019-08-07 11:30:39 +08002588 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302589 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
Mingshu Pang16093502020-04-20 11:21:16 +08002590 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC ||
2591 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC)
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302592 ret = true;
2593
2594 return ret;
2595}
2596
2597bool is_a2dp_device(snd_device_t out_snd_device)
2598{
2599 bool ret=false;
2600 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2601 ret = true;
2602
2603 return ret;
2604}
2605
2606bool is_bt_soc_on(struct audio_device *adev)
2607{
2608 struct mixer_ctl *ctl;
2609 char *mixer_ctl_name = "BT SOC status";
2610 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2611 bool bt_soc_status = true;
2612 if (!ctl) {
2613 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2614 __func__, mixer_ctl_name);
2615 /*This is to ensure we dont break targets which dont have the kernel change*/
2616 return true;
2617 }
2618 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2619 ALOGD("BT SOC status: %d",bt_soc_status);
2620 return bt_soc_status;
2621}
2622
Zhou Song331c8e52019-08-26 14:16:12 +08002623static int configure_btsco_sample_rate(snd_device_t snd_device)
2624{
2625 struct mixer_ctl *ctl = NULL;
2626 struct mixer_ctl *ctl_sr_rx = NULL, *ctl_sr_tx = NULL, *ctl_sr = NULL;
2627 char *rate_str = NULL;
2628 bool is_rx_dev = true;
2629
2630 if (is_btsco_device(snd_device, snd_device)) {
2631 ctl_sr_tx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate TX");
2632 ctl_sr_rx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate RX");
2633 if (!ctl_sr_tx || !ctl_sr_rx) {
2634 ctl_sr = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate");
2635 if (!ctl_sr)
2636 return -ENOSYS;
2637 }
2638
2639 switch (snd_device) {
2640 case SND_DEVICE_OUT_BT_SCO:
2641 rate_str = "KHZ_8";
2642 break;
2643 case SND_DEVICE_IN_BT_SCO_MIC_NREC:
2644 case SND_DEVICE_IN_BT_SCO_MIC:
2645 rate_str = "KHZ_8";
2646 is_rx_dev = false;
2647 break;
2648 case SND_DEVICE_OUT_BT_SCO_WB:
2649 rate_str = "KHZ_16";
2650 break;
2651 case SND_DEVICE_IN_BT_SCO_MIC_WB_NREC:
2652 case SND_DEVICE_IN_BT_SCO_MIC_WB:
2653 rate_str = "KHZ_16";
2654 is_rx_dev = false;
2655 break;
2656 default:
2657 return 0;
2658 }
2659
2660 ctl = (ctl_sr == NULL) ? (is_rx_dev ? ctl_sr_rx : ctl_sr_tx) : ctl_sr;
2661 if (mixer_ctl_set_enum_by_string(ctl, rate_str) != 0)
2662 return -ENOSYS;
2663 }
2664 return 0;
2665}
2666
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302667int out_standby_l(struct audio_stream *stream);
2668
Eric Laurent637e2d42018-11-15 12:24:31 -08002669struct stream_in *adev_get_active_input(const struct audio_device *adev)
2670{
2671 struct listnode *node;
2672 struct stream_in *last_active_in = NULL;
2673
2674 /* Get last added active input.
2675 * TODO: We may use a priority mechanism to pick highest priority active source */
2676 list_for_each(node, &adev->usecase_list)
2677 {
2678 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2679 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL)
2680 last_active_in = usecase->stream.in;
2681 }
2682
2683 return last_active_in;
2684}
2685
2686struct stream_in *get_voice_communication_input(const struct audio_device *adev)
2687{
2688 struct listnode *node;
2689
2690 /* First check active inputs with voice communication source and then
2691 * any input if audio mode is in communication */
2692 list_for_each(node, &adev->usecase_list)
2693 {
2694 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2695 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
2696 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
2697 return usecase->stream.in;
2698 }
2699 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION)
2700 return adev_get_active_input(adev);
2701
2702 return NULL;
2703}
2704
Carter Hsu2e429db2019-05-14 18:50:52 +08002705/*
2706 * Aligned with policy.h
2707 */
2708static inline int source_priority(int inputSource)
2709{
2710 switch (inputSource) {
2711 case AUDIO_SOURCE_VOICE_COMMUNICATION:
2712 return 9;
2713 case AUDIO_SOURCE_CAMCORDER:
2714 return 8;
2715 case AUDIO_SOURCE_VOICE_PERFORMANCE:
2716 return 7;
2717 case AUDIO_SOURCE_UNPROCESSED:
2718 return 6;
2719 case AUDIO_SOURCE_MIC:
2720 return 5;
2721 case AUDIO_SOURCE_ECHO_REFERENCE:
2722 return 4;
2723 case AUDIO_SOURCE_FM_TUNER:
2724 return 3;
2725 case AUDIO_SOURCE_VOICE_RECOGNITION:
2726 return 2;
2727 case AUDIO_SOURCE_HOTWORD:
2728 return 1;
2729 default:
2730 break;
2731 }
2732 return 0;
2733}
2734
2735static struct stream_in *get_priority_input(struct audio_device *adev)
2736{
2737 struct listnode *node;
2738 struct audio_usecase *usecase;
2739 int last_priority = 0, priority;
2740 struct stream_in *priority_in = NULL;
2741 struct stream_in *in;
2742
2743 list_for_each(node, &adev->usecase_list) {
2744 usecase = node_to_item(node, struct audio_usecase, list);
2745 if (usecase->type == PCM_CAPTURE) {
2746 in = usecase->stream.in;
2747 if (!in)
2748 continue;
2749 priority = source_priority(in->source);
2750
2751 if (priority > last_priority) {
2752 last_priority = priority;
2753 priority_in = in;
2754 }
2755 }
2756 }
2757 return priority_in;
2758}
2759
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002760int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002761{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002762 snd_device_t out_snd_device = SND_DEVICE_NONE;
2763 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002764 struct audio_usecase *usecase = NULL;
2765 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002766 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002767 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302768 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002769 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002770 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002771
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302772 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2773
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002774 usecase = get_usecase_from_list(adev, uc_id);
2775 if (usecase == NULL) {
2776 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2777 return -EINVAL;
2778 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002779
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002780 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002781 (usecase->type == VOIP_CALL) ||
Derek Chena30a5f42019-12-03 11:17:09 -05002782 (usecase->type == PCM_HFP_CALL)||
Fei Tongaffdf732020-02-20 20:39:05 +08002783 (usecase->type == ICC_CALL) ||
2784 (usecase->type == SYNTH_LOOPBACK)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302785 if(usecase->stream.out == NULL) {
2786 ALOGE("%s: stream.out is NULL", __func__);
2787 return -EINVAL;
2788 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002789 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS)) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002790 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev,
2791 uc_id);
2792 in_snd_device = audio_extn_auto_hal_get_input_snd_device(adev,
2793 uc_id);
2794 } else {
2795 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302796 usecase->stream.out, usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002797 in_snd_device = platform_get_input_snd_device(adev->platform,
2798 NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302799 &usecase->stream.out->device_list,
2800 usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002801 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002802 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302803 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302804 if (usecase->stream.inout == NULL) {
2805 ALOGE("%s: stream.inout is NULL", __func__);
2806 return -EINVAL;
2807 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002808 assign_devices(&stream_out.device_list, &usecase->stream.inout->out_config.device_list);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302809 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2810 stream_out.format = usecase->stream.inout->out_config.format;
2811 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
Jaideep Sharma477917f2020-03-13 18:13:33 +05302812 out_snd_device = platform_get_output_snd_device(adev->platform, &stream_out, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002813 assign_devices(&usecase->device_list,
2814 &usecase->stream.inout->out_config.device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302815 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2816 if (usecase->stream.inout == NULL) {
2817 ALOGE("%s: stream.inout is NULL", __func__);
2818 return -EINVAL;
2819 }
Manisha Agarwal03297972020-04-17 15:36:55 +05302820 struct listnode out_devices;
2821 list_init(&out_devices);
2822 in_snd_device = platform_get_input_snd_device(adev->platform, NULL,
2823 &out_devices, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002824 assign_devices(&usecase->device_list,
2825 &usecase->stream.inout->in_config.device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002826 } else {
2827 /*
2828 * If the voice call is active, use the sound devices of voice call usecase
2829 * so that it would not result any device switch. All the usecases will
2830 * be switched to new device when select_devices() is called for voice call
2831 * usecase. This is to avoid switching devices for voice call when
2832 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002833 * choose voice call device only if the use case device is
2834 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002835 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002836 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002837 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002838 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002839 if ((vc_usecase) && ((is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2840 is_codec_backend_out_device_type(&usecase->device_list)) ||
2841 (is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2842 is_codec_backend_in_device_type(&usecase->device_list)) ||
2843 is_single_device_type_equal(&vc_usecase->device_list,
2844 AUDIO_DEVICE_OUT_HEARING_AID) ||
2845 is_single_device_type_equal(&usecase->device_list,
Robert Lee8a6aaf32019-09-20 16:40:19 +08002846 AUDIO_DEVICE_IN_VOICE_CALL) ||
2847 (is_single_device_type_equal(&usecase->device_list,
Gautam Manam8fa06162021-09-24 10:41:29 +05302848 AUDIO_DEVICE_IN_BUILTIN_MIC) &&
2849 is_single_device_type_equal(&vc_usecase->device_list,
2850 AUDIO_DEVICE_OUT_USB_HEADSET)) ||
2851 (is_single_device_type_equal(&usecase->device_list,
Robert Lee8a6aaf32019-09-20 16:40:19 +08002852 AUDIO_DEVICE_IN_USB_HEADSET) &&
2853 is_single_device_type_equal(&vc_usecase->device_list,
Kamalakar Yalasiri5edba852021-01-28 14:52:38 +05302854 AUDIO_DEVICE_OUT_USB_HEADSET))||
Gautam Manamf4002142021-09-13 22:05:56 +05302855 (is_single_device_type_equal(&usecase->device_list,
2856 AUDIO_DEVICE_IN_USB_HEADSET) &&
2857 is_codec_backend_out_device_type(&vc_usecase->device_list)) ||
Kamalakar Yalasiri5edba852021-01-28 14:52:38 +05302858 (is_single_device_type_equal(&usecase->device_list,
2859 AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) &&
2860 is_codec_backend_out_device_type(&vc_usecase->device_list)))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002861 in_snd_device = vc_usecase->in_snd_device;
2862 out_snd_device = vc_usecase->out_snd_device;
2863 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002864 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002865 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002866 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002867 if ((voip_usecase != NULL) &&
2868 (usecase->type == PCM_PLAYBACK) &&
2869 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002870 out_snd_device_backend_match = platform_check_backends_match(
2871 voip_usecase->out_snd_device,
2872 platform_get_output_snd_device(
2873 adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302874 usecase->stream.out, usecase->type));
yidongh02ef86f2017-04-21 15:36:04 +08002875 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002876 if ((voip_usecase) && (is_codec_backend_out_device_type(&voip_usecase->device_list) &&
2877 (is_codec_backend_out_device_type(&usecase->device_list) ||
2878 is_codec_backend_in_device_type(&usecase->device_list)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002879 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002880 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002881 in_snd_device = voip_usecase->in_snd_device;
2882 out_snd_device = voip_usecase->out_snd_device;
2883 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002884 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002885 hfp_ucid = audio_extn_hfp_get_usecase();
2886 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002887 if ((hfp_usecase) && is_codec_backend_out_device_type(&hfp_usecase->device_list)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002888 in_snd_device = hfp_usecase->in_snd_device;
2889 out_snd_device = hfp_usecase->out_snd_device;
2890 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002891 }
2892 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302893 if (usecase->stream.out == NULL) {
2894 ALOGE("%s: stream.out is NULL", __func__);
2895 return -EINVAL;
2896 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002897 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002898 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002899 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002900 struct stream_out *voip_out = adev->primary_output;
2901 struct stream_in *voip_in = get_voice_communication_input(adev);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002902 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS))
Guodong Hu267bdf82019-08-12 19:22:32 +08002903 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev, uc_id);
2904 else
2905 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302906 usecase->stream.out,
2907 usecase->type);
kunleizdcf967a2018-08-07 17:09:11 +08002908 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizdcf967a2018-08-07 17:09:11 +08002909
Eric Laurent637e2d42018-11-15 12:24:31 -08002910 if (voip_usecase)
2911 voip_out = voip_usecase->stream.out;
2912
2913 if (usecase->stream.out == voip_out && voip_in != NULL)
2914 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002915 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002916 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302917 if (usecase->stream.in == NULL) {
2918 ALOGE("%s: stream.in is NULL", __func__);
2919 return -EINVAL;
2920 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002921 assign_devices(&usecase->device_list, &usecase->stream.in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002922 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002923 if (in_snd_device == SND_DEVICE_NONE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002924 struct listnode out_devices;
Eric Laurent637e2d42018-11-15 12:24:31 -08002925 struct stream_in *voip_in = get_voice_communication_input(adev);
Carter Hsu2e429db2019-05-14 18:50:52 +08002926 struct stream_in *priority_in = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08002927
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002928 list_init(&out_devices);
Eric Laurent637e2d42018-11-15 12:24:31 -08002929 if (voip_in != NULL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002930 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
2931 USECASE_AUDIO_PLAYBACK_VOIP);
2932
Carter Hsu2e429db2019-05-14 18:50:52 +08002933 usecase->stream.in->enable_ec_port = false;
2934
Zhou Song503196b2021-07-23 17:31:05 +08002935 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY ||
2936 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY2) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002937 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_TELEPHONY_TX, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002938 } else if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002939 assign_devices(&out_devices, &voip_usecase->stream.out->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002940 } else if (adev->primary_output &&
2941 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002942 assign_devices(&out_devices, &adev->primary_output->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002943 } else {
2944 /* forcing speaker o/p device to get matching i/p pair
2945 in case o/p is not routed from same primary HAL */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002946 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002947 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002948 priority_in = voip_in;
2949 } else {
2950 /* get the input with the highest priority source*/
2951 priority_in = get_priority_input(adev);
2952
Susan Wang727dd6b2021-03-26 11:28:59 -04002953 if (!priority_in ||
2954 audio_extn_auto_hal_overwrite_priority_for_auto(usecase->stream.in))
Carter Hsu2e429db2019-05-14 18:50:52 +08002955 priority_in = usecase->stream.in;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002956 }
Huicheng Liu1404ba12020-09-11 01:03:25 -04002957 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_IN_BUS)){
2958 in_snd_device = audio_extn_auto_hal_get_snd_device_for_car_audio_stream(priority_in->car_audio_stream);
2959 }
2960 else
2961 in_snd_device = platform_get_input_snd_device(adev->platform,
2962 priority_in,
2963 &out_devices,
2964 usecase->type);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002965 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002966 }
2967 }
2968
2969 if (out_snd_device == usecase->out_snd_device &&
2970 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302971
2972 if (!force_device_switch(usecase))
2973 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002974 }
2975
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002976 if (!compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS) &&
Guodong Hu267bdf82019-08-12 19:22:32 +08002977 ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002978 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready()))) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002979 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2980 return 0;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302981 }
2982
Aalique Grahame22e49102018-12-18 14:23:57 -08002983 if (out_snd_device != SND_DEVICE_NONE &&
2984 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
2985 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2986 __func__,
2987 use_case_table[uc_id],
2988 adev->last_logged_snd_device[uc_id][0],
2989 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
2990 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
2991 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
2992 -1,
2993 out_snd_device,
2994 platform_get_snd_device_name(out_snd_device),
2995 platform_get_snd_device_acdb_id(out_snd_device));
2996 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
2997 }
2998 if (in_snd_device != SND_DEVICE_NONE &&
2999 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
3000 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
3001 __func__,
3002 use_case_table[uc_id],
3003 adev->last_logged_snd_device[uc_id][1],
3004 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
3005 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
3006 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
3007 -1,
3008 in_snd_device,
3009 platform_get_snd_device_name(in_snd_device),
3010 platform_get_snd_device_acdb_id(in_snd_device));
3011 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
3012 }
3013
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003014
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003015 /*
3016 * Limitation: While in call, to do a device switch we need to disable
3017 * and enable both RX and TX devices though one of them is same as current
3018 * device.
3019 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07003020 if ((usecase->type == VOICE_CALL) &&
3021 (usecase->in_snd_device != SND_DEVICE_NONE) &&
3022 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07003023 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07003024 }
3025
3026 if (((usecase->type == VOICE_CALL) ||
3027 (usecase->type == VOIP_CALL)) &&
3028 (usecase->out_snd_device != SND_DEVICE_NONE)) {
3029 /* Disable sidetone only if voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303030 if (voice_is_call_state_active_in_call(adev) ||
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07003031 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07003032 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003033
3034 /* Disable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303035 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003036 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08003037 }
3038
Aalique Grahame22e49102018-12-18 14:23:57 -08003039 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
3040 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003041 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303042 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08003043 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
3044 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
3045 else
3046 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303047 }
3048
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003049 /* Disable current sound devices */
3050 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003051 disable_audio_route(adev, usecase);
3052 disable_snd_device(adev, usecase->out_snd_device);
Gautam Manam274f4752021-09-24 10:58:49 +05303053 if (usecase->id == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
3054 disable_snd_device(adev, SND_DEVICE_OUT_HAPTICS);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003055 }
3056
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003057 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003058 disable_audio_route(adev, usecase);
3059 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003060 }
3061
Daniel Hillenbrand17873952013-05-23 10:10:00 +05303062 /* Rely on amplifier_set_devices to distinguish between in/out devices */
3063 amplifier_set_input_devices(in_snd_device);
3064 amplifier_set_output_devices(out_snd_device);
3065
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08003066 /* Applicable only on the targets that has external modem.
3067 * New device information should be sent to modem before enabling
3068 * the devices to reduce in-call device switch time.
3069 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07003070 if ((usecase->type == VOICE_CALL) &&
3071 (usecase->in_snd_device != SND_DEVICE_NONE) &&
3072 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08003073 status = platform_switch_voice_call_enable_device_config(adev->platform,
3074 out_snd_device,
3075 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07003076 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08003077
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003078 /* Enable new sound devices */
3079 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08003080 check_usecases_codec_backend(adev, usecase, out_snd_device);
Saurav Kumarc1411662020-10-14 10:50:45 +05303081 check_and_configure_headphone(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05303082 if (platform_check_codec_asrc_support(adev->platform))
3083 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003084 enable_snd_device(adev, out_snd_device);
Zhou Songd9bd9302020-08-04 16:34:45 +08003085 /* Enable haptics device for haptic usecase */
3086 if (usecase->id == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
3087 enable_snd_device(adev, SND_DEVICE_OUT_HAPTICS);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003088 }
3089
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07003090 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303091 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003092 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07003093 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003094
Lakshman Chaluvarajuab7e5572020-10-28 19:29:23 +05303095 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL)
Eric Laurentb23d5282013-05-14 15:27:20 -07003096 status = platform_switch_voice_call_device_post(adev->platform,
3097 out_snd_device,
3098 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08003099
sangwoo170731f2013-06-08 15:36:36 +09003100 usecase->in_snd_device = in_snd_device;
3101 usecase->out_snd_device = out_snd_device;
3102
Dhananjay Kumard6d32152016-10-13 16:11:03 +05303103 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
3104 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05303105 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003106 if ((24 == usecase->stream.out->bit_width) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003107 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_SPEAKER)) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003108 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3109 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
3110 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
3111 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
3112 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
3113 /*
3114 * To best utlize DSP, check if the stream sample rate is supported/multiple of
3115 * configured device sample rate, if not update the COPP rate to be equal to the
3116 * device sample rate, else open COPP at stream sample rate
3117 */
3118 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
3119 usecase->stream.out->sample_rate,
3120 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05303121 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
Preetam Singh Ranawat590d0432019-09-30 14:39:47 +05303122 out_snd_device != SND_DEVICE_OUT_HEADPHONES &&
3123 out_snd_device != SND_DEVICE_OUT_HEADPHONES_HIFI_FILTER &&
Ashish Jain4826f6c2017-02-06 13:33:20 +05303124 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003125 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
3126 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
3127 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3128 }
Weiyin Jiangcdece202019-07-08 16:13:16 +08003129 }
3130 enable_audio_route(adev, usecase);
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003131
Shalini Manjunatha5e610912020-12-29 13:02:25 +05303132 if (uc_id == USECASE_AUDIO_PLAYBACK_VOIP) {
3133 struct stream_in *voip_in = get_voice_communication_input(adev);
3134 struct audio_usecase *voip_in_usecase = NULL;
3135 voip_in_usecase = get_usecase_from_list(adev, USECASE_AUDIO_RECORD_VOIP);
3136 if (voip_in != NULL &&
3137 voip_in_usecase != NULL &&
3138 !(out_snd_device == AUDIO_DEVICE_OUT_SPEAKER ||
3139 out_snd_device == AUDIO_DEVICE_OUT_SPEAKER_SAFE) &&
3140 (voip_in_usecase->in_snd_device ==
3141 platform_get_input_snd_device(adev->platform, voip_in,
3142 &usecase->stream.out->device_list,usecase->type))) {
3143 /*
3144 * if VOIP TX is enabled before VOIP RX, needs to re-route the TX path
3145 * for enabling echo-reference-voip with correct port
3146 */
3147 ALOGD("%s: VOIP TX is enabled before VOIP RX,needs to re-route the TX path",__func__);
3148 disable_audio_route(adev, voip_in_usecase);
3149 disable_snd_device(adev, voip_in_usecase->in_snd_device);
3150 enable_snd_device(adev, voip_in_usecase->in_snd_device);
3151 enable_audio_route(adev, voip_in_usecase);
3152 }
3153 }
Ramjee Singhcdf67af2021-09-29 14:20:27 +05303154 if (voice_extn_compress_voip_is_active(adev)) {
3155 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
3156 USECASE_COMPRESS_VOIP_CALL);
3157 /*
3158 * If only compress voip input is opened voip out will be primary out.
3159 * Need to consider re-routing to select correct i/p pair
3160 */
3161 if ((voip_usecase != NULL) &&
3162 (usecase->type == PCM_PLAYBACK) &&
3163 (usecase->stream.out == voip_usecase->stream.out)) {
3164 in_snd_device = platform_get_input_snd_device(adev->platform,
3165 NULL,
3166 &usecase->stream.out->device_list,
3167 usecase->type);
3168 if (voip_usecase->in_snd_device != in_snd_device ) {
3169 ALOGD("%s:Re routing compress voip tx snd device matching voip rx pair",
3170 __func__);
3171 disable_audio_route(adev, voip_usecase);
3172 disable_snd_device(adev, voip_usecase->in_snd_device);
3173 voip_usecase->in_snd_device = in_snd_device;
3174 voip_usecase->out_snd_device = usecase->out_snd_device;
3175 /* Route all TX usecase to Compress voip BE */
3176 check_usecases_capture_codec_backend(adev, voip_usecase, in_snd_device);
3177 enable_snd_device(adev, in_snd_device);
3178 /* Send Voice related calibration for RX /TX pair */
3179 status = platform_switch_voice_call_device_post(adev->platform,
3180 out_snd_device,
3181 in_snd_device);
3182 enable_audio_route(adev, voip_usecase);
3183 }
3184 }
3185 }
Shalini Manjunatha5e610912020-12-29 13:02:25 +05303186
3187
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08003188 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08003189
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003190 /* If input stream is already running then effect needs to be
3191 applied on the new input device that's being enabled here. */
Eric Laurent637e2d42018-11-15 12:24:31 -08003192 if (in_snd_device != SND_DEVICE_NONE)
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003193 check_and_enable_effect(adev);
3194
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003195 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003196 /* Enable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303197 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003198 voice_check_and_update_aanc_path(adev, out_snd_device, true);
3199
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003200 /* Enable sidetone only if other voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303201 if (voice_is_call_state_active_in_call(adev) ||
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003202 voice_extn_compress_voip_is_started(adev))
3203 voice_set_sidetone(adev, out_snd_device, true);
3204 }
3205
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003206 /* Applicable only on the targets that has external modem.
3207 * Enable device command should be sent to modem only after
3208 * enabling voice call mixer controls
3209 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07003210 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003211 status = platform_switch_voice_call_usecase_route_post(adev->platform,
3212 out_snd_device,
3213 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303214
3215 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003216 struct stream_in *in = adev_get_active_input(adev);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303217 if (usecase->type == VOIP_CALL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003218 if (in != NULL && !in->standby) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303219 if (is_bt_soc_on(adev) == false){
3220 ALOGD("BT SCO MIC disconnected while in connection");
Eric Laurent637e2d42018-11-15 12:24:31 -08003221 if (in->pcm != NULL)
3222 pcm_stop(in->pcm);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303223 }
3224 }
3225 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
3226 && usecase->stream.out->started) {
3227 if (is_bt_soc_on(adev) == false) {
3228 ALOGD("BT SCO/A2DP disconnected while in connection");
3229 out_standby_l(&usecase->stream.out->stream.common);
3230 }
3231 }
3232 } else if ((usecase->stream.out != NULL) &&
3233 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05303234 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
3235 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Weiyin Jiang0d373242019-07-25 13:18:17 +08003236 (usecase->type != PCM_CAPTURE) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303237 usecase->stream.out->started) {
3238 if (is_bt_soc_on(adev) == false) {
3239 ALOGD("BT SCO/A2dp disconnected while in connection");
3240 out_standby_l(&usecase->stream.out->stream.common);
3241 }
3242 }
3243 }
3244
Yung Ti Su70cb8242018-06-22 17:38:47 +08003245 if (usecase->type != PCM_CAPTURE && usecase == voip_usecase) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003246 struct stream_out *voip_out = voip_usecase->stream.out;
3247 audio_extn_utils_send_app_type_gain(adev,
3248 voip_out->app_type_cfg.app_type,
3249 &voip_out->app_type_cfg.gain[0]);
3250 }
3251
Ajender Reddyb940b832021-07-07 11:51:42 +05303252 ALOGD("%s: done",__func__);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303253
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003254 return status;
3255}
3256
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003257static int stop_input_stream(struct stream_in *in)
3258{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303259 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003260 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05303261
3262 if (in == NULL) {
3263 ALOGE("%s: stream_in ptr is NULL", __func__);
3264 return -EINVAL;
3265 }
3266
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003267 struct audio_device *adev = in->dev;
Carter Hsu2e429db2019-05-14 18:50:52 +08003268 struct stream_in *priority_in = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003269
Eric Laurent994a6932013-07-17 11:51:42 -07003270 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003271 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003272 uc_info = get_usecase_from_list(adev, in->usecase);
3273 if (uc_info == NULL) {
3274 ALOGE("%s: Could not find the usecase (%d) in the list",
3275 __func__, in->usecase);
3276 return -EINVAL;
3277 }
3278
Carter Hsu2e429db2019-05-14 18:50:52 +08003279 priority_in = get_priority_input(adev);
3280
Derek Chenea197282019-01-07 17:35:01 -08003281 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3282 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003283
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003284 /* Close in-call recording streams */
3285 voice_check_and_stop_incall_rec_usecase(adev, in);
3286
Eric Laurent150dbfe2013-02-27 14:31:02 -08003287 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003288 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003289
3290 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003291 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003292
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003293 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303294 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_PRIMARY);
3295
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003296 list_remove(&uc_info->list);
3297 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003298
Carter Hsu2e429db2019-05-14 18:50:52 +08003299 if (priority_in == in) {
3300 priority_in = get_priority_input(adev);
Sujin Panicker110f7942021-08-26 17:01:22 +05303301 if (priority_in) {
3302 if (is_usb_in_device_type(&priority_in->device_list)) {
3303 if (audio_extn_usb_connected(NULL))
3304 select_devices(adev, priority_in->usecase);
3305 } else {
3306 select_devices(adev, priority_in->usecase);
3307 }
3308 }
Carter Hsu2e429db2019-05-14 18:50:52 +08003309 }
3310
Vatsal Buchac09ae062018-11-14 13:25:08 +05303311 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07003312 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003313 return ret;
3314}
3315
3316int start_input_stream(struct stream_in *in)
3317{
3318 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08003319 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003320 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05303321
3322 if (in == NULL) {
3323 ALOGE("%s: stream_in ptr is NULL", __func__);
3324 return -EINVAL;
3325 }
3326
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003327 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07003328 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07003329 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003330
Mingming Yin2664a5b2015-09-03 10:53:11 -07003331 if (get_usecase_from_list(adev, usecase) == NULL)
3332 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303333 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
3334 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003335
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303336 if (CARD_STATUS_OFFLINE == in->card_status||
3337 CARD_STATUS_OFFLINE == adev->card_status) {
3338 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303339 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303340 goto error_config;
3341 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303342
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003343 if (is_sco_in_device_type(&in->device_list)) {
Lakshman Chaluvaraju87f53aa2021-02-02 15:50:11 +05303344 if (!adev->bt_sco_on || audio_extn_a2dp_source_is_ready()) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303345 ALOGE("%s: SCO profile is not ready, return error", __func__);
3346 ret = -EIO;
3347 goto error_config;
3348 }
3349 }
3350
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003351 /* Check if source matches incall recording usecase criteria */
3352 ret = voice_check_and_set_incall_rec_usecase(adev, in);
3353 if (ret)
3354 goto error_config;
3355 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07003356 ALOGV("%s: usecase(%d)", __func__, in->usecase);
3357
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303358 if (audio_extn_cin_attached_usecase(in))
3359 audio_extn_cin_acquire_usecase(in);
3360
Mingming Yin2664a5b2015-09-03 10:53:11 -07003361 if (get_usecase_from_list(adev, in->usecase) != NULL) {
3362 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
3363 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Weiyin Jiang38c0e612020-09-10 16:10:51 +08003364 ret = -EINVAL;
3365 goto error_config;
Mingming Yin2664a5b2015-09-03 10:53:11 -07003366 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003367
Eric Laurentb23d5282013-05-14 15:27:20 -07003368 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003369 if (in->pcm_device_id < 0) {
3370 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
3371 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08003372 ret = -EINVAL;
3373 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003374 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003375
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003376 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003377
3378 if (!uc_info) {
3379 ret = -ENOMEM;
3380 goto error_config;
3381 }
3382
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003383 uc_info->id = in->usecase;
3384 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003385 uc_info->stream.in = in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003386 list_init(&uc_info->device_list);
3387 assign_devices(&uc_info->device_list, &in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003388 uc_info->in_snd_device = SND_DEVICE_NONE;
3389 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003390
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003391 list_add_tail(&adev->usecase_list, &uc_info->list);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003392 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303393 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3394 adev->perf_lock_opts,
3395 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003396 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003397
Derek Chenea197282019-01-07 17:35:01 -08003398 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3399 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003400
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05303401 android_atomic_acquire_cas(true, false, &(in->capture_stopped));
3402
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303403 if (audio_extn_cin_attached_usecase(in)) {
Manish Dewangan46e07982018-12-13 18:18:59 +05303404 ret = audio_extn_cin_open_input_stream(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303405 if (ret)
3406 goto error_open;
3407 else
3408 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003409 }
3410
Haynes Mathew George16081042017-05-31 17:16:49 -07003411 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003412 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003413 ALOGE("%s: pcm stream not ready", __func__);
3414 goto error_open;
3415 }
3416 ret = pcm_start(in->pcm);
3417 if (ret < 0) {
3418 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3419 goto error_open;
3420 }
3421 } else {
3422 unsigned int flags = PCM_IN | PCM_MONOTONIC;
3423 unsigned int pcm_open_retry_count = 0;
3424
Zhou Song62ea0282020-03-22 19:53:01 +08003425 if ((in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) ||
3426 (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003427 flags |= PCM_MMAP | PCM_NOIRQ;
3428 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
3429 } else if (in->realtime) {
3430 flags |= PCM_MMAP | PCM_NOIRQ;
3431 }
3432
Garmond Leunge2433c32017-09-28 21:51:22 -07003433 if (audio_extn_ffv_get_stream() == in) {
3434 ALOGD("%s: ffv stream, update pcm config", __func__);
3435 audio_extn_ffv_update_pcm_config(&config);
3436 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003437 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3438 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3439
3440 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003441 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07003442 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07003443 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003444 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303445 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303446 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3447 adev->card_status = CARD_STATUS_OFFLINE;
3448 in->card_status = CARD_STATUS_OFFLINE;
3449 ret = -EIO;
3450 goto error_open;
3451 }
3452
Haynes Mathew George16081042017-05-31 17:16:49 -07003453 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3454 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3455 if (in->pcm != NULL) {
3456 pcm_close(in->pcm);
3457 in->pcm = NULL;
3458 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003459 if (pcm_open_retry_count == 0) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003460 ret = -EIO;
3461 goto error_open;
3462 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003463 pcm_open_retry_count--;
Haynes Mathew George16081042017-05-31 17:16:49 -07003464 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3465 continue;
3466 }
3467 break;
3468 }
3469
3470 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003471 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07003472 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003473 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003474 if (ret < 0) {
3475 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3476 pcm_close(in->pcm);
3477 in->pcm = NULL;
3478 goto error_open;
3479 }
3480 register_in_stream(in);
3481 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003482 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07003483 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003484 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003485 if (ret < 0) {
3486 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003487 pcm_close(in->pcm);
3488 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003489 goto error_open;
3490 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003491 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003492 }
3493
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003494 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07003495 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
3496 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003497
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003498 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303499 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
3500
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303501done_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003502 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303503 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Manisha Agarwal4c2402e2020-10-21 12:02:57 +05303504 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303505 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003506 return ret;
3507
3508error_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003509 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303510 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003511 stop_input_stream(in);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003512
Eric Laurentc8400632013-02-14 19:04:54 -08003513error_config:
Weiyin Jiang38c0e612020-09-10 16:10:51 +08003514 if (audio_extn_cin_attached_usecase(in))
3515 audio_extn_cin_close_input_stream(in);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303516 /*
3517 * sleep 50ms to allow sufficient time for kernel
3518 * drivers to recover incases like SSR.
3519 */
3520 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003521 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303522 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003523 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003524}
3525
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003526void lock_input_stream(struct stream_in *in)
3527{
3528 pthread_mutex_lock(&in->pre_lock);
3529 pthread_mutex_lock(&in->lock);
3530 pthread_mutex_unlock(&in->pre_lock);
3531}
3532
3533void lock_output_stream(struct stream_out *out)
3534{
3535 pthread_mutex_lock(&out->pre_lock);
3536 pthread_mutex_lock(&out->lock);
3537 pthread_mutex_unlock(&out->pre_lock);
3538}
3539
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003540/* must be called with out->lock locked */
3541static int send_offload_cmd_l(struct stream_out* out, int command)
3542{
3543 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
3544
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003545 if (!cmd) {
3546 ALOGE("failed to allocate mem for command 0x%x", command);
3547 return -ENOMEM;
3548 }
3549
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003550 ALOGVV("%s %d", __func__, command);
3551
3552 cmd->cmd = command;
3553 list_add_tail(&out->offload_cmd_list, &cmd->node);
3554 pthread_cond_signal(&out->offload_cond);
3555 return 0;
3556}
3557
Gautam Manam14c198b2020-12-24 14:08:04 +05303558/* must be called with out->lock */
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003559static void stop_compressed_output_l(struct stream_out *out)
3560{
Gautam Manam14c198b2020-12-24 14:08:04 +05303561 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003562 out->offload_state = OFFLOAD_STATE_IDLE;
Gautam Manam14c198b2020-12-24 14:08:04 +05303563 pthread_mutex_unlock(&out->latch_lock);
Weiyin Jiang906db3c2021-03-02 13:17:04 +08003564
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003565 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003566 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003567 if (out->compr != NULL) {
3568 compress_stop(out->compr);
3569 while (out->offload_thread_blocked) {
3570 pthread_cond_wait(&out->cond, &out->lock);
3571 }
3572 }
3573}
3574
Varun Balaraje49253e2017-07-06 19:48:56 +05303575bool is_interactive_usecase(audio_usecase_t uc_id)
3576{
3577 unsigned int i;
3578 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
3579 if (uc_id == interactive_usecases[i])
3580 return true;
3581 }
3582 return false;
3583}
3584
3585static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
3586{
3587 audio_usecase_t ret_uc = USECASE_INVALID;
3588 unsigned int intract_uc_index;
3589 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3590
3591 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
3592 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
3593 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
3594 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
3595 ret_uc = interactive_usecases[intract_uc_index];
3596 break;
3597 }
3598 }
3599
3600 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
3601 return ret_uc;
3602}
3603
3604static void free_interactive_usecase(struct audio_device *adev,
3605 audio_usecase_t uc_id)
3606{
3607 unsigned int interact_uc_index;
3608 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3609
3610 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
3611 if (interactive_usecases[interact_uc_index] == uc_id) {
3612 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
3613 break;
3614 }
3615 }
3616 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
3617}
3618
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003619bool is_offload_usecase(audio_usecase_t uc_id)
3620{
3621 unsigned int i;
3622 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
3623 if (uc_id == offload_usecases[i])
3624 return true;
3625 }
3626 return false;
3627}
3628
Dhananjay Kumarac341582017-02-23 23:42:25 +05303629static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003630{
vivek mehta446c3962015-09-14 10:57:35 -07003631 audio_usecase_t ret_uc = USECASE_INVALID;
3632 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003633 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003634 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05303635 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07003636 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
3637 else
3638 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003639
vivek mehta446c3962015-09-14 10:57:35 -07003640 pthread_mutex_lock(&adev->lock);
3641 if (get_usecase_from_list(adev, ret_uc) != NULL)
3642 ret_uc = USECASE_INVALID;
3643 pthread_mutex_unlock(&adev->lock);
3644
3645 return ret_uc;
3646 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003647
3648 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003649 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3650 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3651 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3652 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003653 break;
3654 }
3655 }
vivek mehta446c3962015-09-14 10:57:35 -07003656
3657 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3658 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003659}
3660
3661static void free_offload_usecase(struct audio_device *adev,
3662 audio_usecase_t uc_id)
3663{
vivek mehta446c3962015-09-14 10:57:35 -07003664 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003665 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003666
3667 if (!adev->multi_offload_enable)
3668 return;
3669
3670 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3671 if (offload_usecases[offload_uc_index] == uc_id) {
3672 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003673 break;
3674 }
3675 }
3676 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3677}
3678
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003679static void *offload_thread_loop(void *context)
3680{
3681 struct stream_out *out = (struct stream_out *) context;
3682 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003683 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003684
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003685 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08003686 set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003687 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3688
3689 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003690 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003691 out->offload_state = OFFLOAD_STATE_IDLE;
3692 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003693 for (;;) {
3694 struct offload_cmd *cmd = NULL;
3695 stream_callback_event_t event;
3696 bool send_callback = false;
3697
3698 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3699 __func__, list_empty(&out->offload_cmd_list),
3700 out->offload_state);
3701 if (list_empty(&out->offload_cmd_list)) {
3702 ALOGV("%s SLEEPING", __func__);
3703 pthread_cond_wait(&out->offload_cond, &out->lock);
3704 ALOGV("%s RUNNING", __func__);
3705 continue;
3706 }
3707
3708 item = list_head(&out->offload_cmd_list);
3709 cmd = node_to_item(item, struct offload_cmd, node);
3710 list_remove(item);
3711
3712 ALOGVV("%s STATE %d CMD %d out->compr %p",
3713 __func__, out->offload_state, cmd->cmd, out->compr);
3714
3715 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3716 free(cmd);
3717 break;
3718 }
3719
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003720 // allow OFFLOAD_CMD_ERROR reporting during standby
3721 // this is needed to handle failures during compress_open
3722 // Note however that on a pause timeout, the stream is closed
3723 // and no offload usecase will be active. Therefore this
3724 // special case is needed for compress_open failures alone
3725 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3726 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003727 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003728 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003729 pthread_cond_signal(&out->cond);
3730 continue;
3731 }
3732 out->offload_thread_blocked = true;
3733 pthread_mutex_unlock(&out->lock);
3734 send_callback = false;
3735 switch(cmd->cmd) {
3736 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003737 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003738 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003739 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003740 send_callback = true;
3741 event = STREAM_CBK_EVENT_WRITE_READY;
3742 break;
3743 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003744 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303745 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003746 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303747 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003748 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303749 if (ret < 0)
3750 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303751 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303752 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003753 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003754 else
3755 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003756 if (-ENETRESET != ret && !(-EINTR == ret &&
3757 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303758 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303759 pthread_mutex_lock(&out->lock);
3760 out->send_new_metadata = 1;
3761 out->send_next_track_params = true;
3762 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303763 event = STREAM_CBK_EVENT_DRAIN_READY;
3764 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3765 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303766 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003767 break;
3768 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003769 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003770 ret = compress_drain(out->compr);
3771 ALOGD("copl(%p):out of compress_drain", out);
3772 // EINTR check avoids drain interruption due to SSR
3773 if (-ENETRESET != ret && !(-EINTR == ret &&
3774 CARD_STATUS_OFFLINE == out->card_status)) {
3775 send_callback = true;
3776 event = STREAM_CBK_EVENT_DRAIN_READY;
3777 } else
3778 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003779 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303780 case OFFLOAD_CMD_ERROR:
3781 ALOGD("copl(%p): sending error callback to AF", out);
3782 send_callback = true;
3783 event = STREAM_CBK_EVENT_ERROR;
3784 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003785 default:
3786 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3787 break;
3788 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003789 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003790 out->offload_thread_blocked = false;
3791 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003792 if (send_callback && out->client_callback) {
3793 ALOGVV("%s: sending client_callback event %d", __func__, event);
3794 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003795 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003796 free(cmd);
3797 }
3798
3799 pthread_cond_signal(&out->cond);
3800 while (!list_empty(&out->offload_cmd_list)) {
3801 item = list_head(&out->offload_cmd_list);
3802 list_remove(item);
3803 free(node_to_item(item, struct offload_cmd, node));
3804 }
3805 pthread_mutex_unlock(&out->lock);
3806
3807 return NULL;
3808}
3809
3810static int create_offload_callback_thread(struct stream_out *out)
3811{
3812 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3813 list_init(&out->offload_cmd_list);
3814 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3815 offload_thread_loop, out);
3816 return 0;
3817}
3818
3819static int destroy_offload_callback_thread(struct stream_out *out)
3820{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003821 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003822 stop_compressed_output_l(out);
3823 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3824
3825 pthread_mutex_unlock(&out->lock);
3826 pthread_join(out->offload_thread, (void **) NULL);
3827 pthread_cond_destroy(&out->offload_cond);
3828
3829 return 0;
3830}
3831
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003832static int stop_output_stream(struct stream_out *out)
3833{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303834 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003835 struct audio_usecase *uc_info;
3836 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003837 bool has_voip_usecase =
3838 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003839
Eric Laurent994a6932013-07-17 11:51:42 -07003840 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003841 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003842 uc_info = get_usecase_from_list(adev, out->usecase);
3843 if (uc_info == NULL) {
3844 ALOGE("%s: Could not find the usecase (%d) in the list",
3845 __func__, out->usecase);
3846 return -EINVAL;
3847 }
3848
Zhou Songbaddf9f2020-11-20 13:57:39 +08003849 out->a2dp_muted = false;
3850
Derek Chenea197282019-01-07 17:35:01 -08003851 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3852 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003853
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003854 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303855 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003856 if (adev->visualizer_stop_output != NULL)
3857 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003858
3859 audio_extn_dts_remove_state_notifier_node(out->usecase);
3860
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003861 if (adev->offload_effects_stop_output != NULL)
3862 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07003863 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3864 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3865 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003866 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003867
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003868 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3869 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003870 voice_set_device_mute_flag(adev, false);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003871 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003872
Eric Laurent150dbfe2013-02-27 14:31:02 -08003873 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003874 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003875
3876 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003877 disable_snd_device(adev, uc_info->out_snd_device);
Zhou Songd9bd9302020-08-04 16:34:45 +08003878 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
3879 disable_snd_device(adev, SND_DEVICE_OUT_HAPTICS);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003880
Aalique Grahame22e49102018-12-18 14:23:57 -08003881 audio_extn_extspk_update(adev->extspk);
3882
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003883 if (is_offload_usecase(out->usecase)) {
3884 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3885 adev->dsp_bit_width_enforce_mode,
3886 false);
3887 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003888 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003889 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3890 false);
3891
3892 if (ret != 0)
3893 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3894 /* default service interval was successfully updated,
3895 reopen USB backend with new service interval */
3896 ret = 0;
3897 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003898
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003899 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303900 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003901 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303902 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003903 ALOGV("Disable passthrough , reset mixer to pcm");
3904 /* NO_PASSTHROUGH */
Meng Wang4c32fb42020-01-16 17:57:11 +08003905#ifdef AUDIO_GKI_ENABLED
3906 /* out->compr_config.codec->reserved[0] is for compr_passthr */
3907 out->compr_config.codec->reserved[0] = 0;
3908#else
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003909 out->compr_config.codec->compr_passthr = 0;
Meng Wang4c32fb42020-01-16 17:57:11 +08003910#endif
Mingming Yin21854652016-04-13 11:54:02 -07003911 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003912 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3913 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003914
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303915 /* Must be called after removing the usecase from list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003916 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL))
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303917 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303918
Manish Dewangan21a850a2017-08-14 12:03:55 +05303919 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003920 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3921 if (ret < 0)
3922 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3923 }
3924
Zhou Song642ec432020-12-23 16:11:10 +08003925 /* trigger voip input to reroute when voip output changes to hearing aid */
Aalique Grahame22e49102018-12-18 14:23:57 -08003926 if (has_voip_usecase ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003927 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003928 struct listnode *node;
3929 struct audio_usecase *usecase;
3930 list_for_each(node, &adev->usecase_list) {
3931 usecase = node_to_item(node, struct audio_usecase, list);
Zhou Song642ec432020-12-23 16:11:10 +08003932 if (usecase->type == PCM_PLAYBACK || usecase == uc_info ||
3933 (usecase->type == PCM_CAPTURE &&
Revathi Uddarajud9f23d92020-07-27 10:55:06 +05303934 usecase->id != USECASE_AUDIO_RECORD_VOIP &&
Zhou Song642ec432020-12-23 16:11:10 +08003935 usecase->id != USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY))
Aalique Grahame22e49102018-12-18 14:23:57 -08003936 continue;
3937
3938 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
3939 __func__, usecase->id, use_case_table[usecase->id],
3940 out->usecase, use_case_table[out->usecase]);
3941 select_devices(adev, usecase->id);
3942 }
3943 }
3944
Garmond Leung5fd0b552018-04-17 11:56:12 -07003945 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003946 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003947 return ret;
3948}
3949
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003950struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
3951 unsigned int flags, unsigned int pcm_open_retry_count,
3952 struct pcm_config *config)
3953{
3954 struct pcm* pcm = NULL;
3955
3956 while (1) {
3957 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
3958 if (pcm == NULL || !pcm_is_ready(pcm)) {
3959 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
3960 if (pcm != NULL) {
3961 pcm_close(pcm);
3962 pcm = NULL;
3963 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003964 if (pcm_open_retry_count == 0)
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003965 return NULL;
3966
Weiyin Jiang72197252019-10-09 11:49:32 +08003967 pcm_open_retry_count--;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003968 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3969 continue;
3970 }
3971 break;
3972 }
3973
3974 if (pcm_is_ready(pcm)) {
3975 int ret = pcm_prepare(pcm);
3976 if (ret < 0) {
3977 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3978 pcm_close(pcm);
3979 pcm = NULL;
3980 }
3981 }
3982
3983 return pcm;
3984}
3985
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003986int start_output_stream(struct stream_out *out)
3987{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003988 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003989 struct audio_usecase *uc_info;
3990 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003991 char mixer_ctl_name[128];
3992 struct mixer_ctl *ctl = NULL;
3993 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303994 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003995 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003996
Haynes Mathew George380745d2017-10-04 15:27:45 -07003997 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003998 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3999 ret = -EINVAL;
4000 goto error_config;
4001 }
4002
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004003 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304004 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004005 get_device_types(&out->device_list), is_haptic_usecase);
4006
4007 bool is_speaker_active = compare_device_type(&out->device_list,
4008 AUDIO_DEVICE_OUT_SPEAKER);
4009 bool is_speaker_safe_active = compare_device_type(&out->device_list,
4010 AUDIO_DEVICE_OUT_SPEAKER_SAFE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304011
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304012 if (CARD_STATUS_OFFLINE == out->card_status ||
4013 CARD_STATUS_OFFLINE == adev->card_status) {
4014 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05304015 ret = -EIO;
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004016 goto error_fatal;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304017 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05304018
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004019 //Update incall music usecase to reflect correct voice session
4020 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
4021 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
4022 if (ret != 0) {
4023 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
4024 __func__, ret);
4025 goto error_config;
4026 }
4027 }
4028
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004029 if (is_a2dp_out_device_type(&out->device_list)) {
Florian Pfister1a84f312018-07-19 14:38:18 +02004030 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004031 if (is_speaker_active || is_speaker_safe_active) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304032 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304033 } else {
Zhou Songd01e7a22020-09-23 22:49:01 +08004034 if (!is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304035 ALOGE("%s: A2DP profile is not ready, return error", __func__);
4036 ret = -EAGAIN;
4037 goto error_config;
4038 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304039 }
4040 }
4041 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004042 if (is_sco_out_device_type(&out->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304043 if (!adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004044 if (is_speaker_active) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304045 //combo usecase just by pass a2dp
4046 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004047 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304048 } else {
4049 ALOGE("%s: SCO profile is not ready, return error", __func__);
4050 ret = -EAGAIN;
4051 goto error_config;
4052 }
4053 }
4054 }
4055
Eric Laurentb23d5282013-05-14 15:27:20 -07004056 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004057 if (out->pcm_device_id < 0) {
4058 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
4059 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004060 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004061 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004062 }
4063
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004064 if (is_haptic_usecase) {
Meng Wang51d8c2a2020-04-27 15:23:21 +08004065 adev->haptic_pcm_device_id = platform_get_pcm_device_id(
4066 USECASE_AUDIO_PLAYBACK_HAPTICS, PCM_PLAYBACK);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004067 if (adev->haptic_pcm_device_id < 0) {
4068 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
4069 __func__, adev->haptic_pcm_device_id, out->usecase);
4070 ret = -EINVAL;
4071 goto error_config;
4072 }
4073 }
4074
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004075 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004076
4077 if (!uc_info) {
4078 ret = -ENOMEM;
4079 goto error_config;
4080 }
4081
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004082 uc_info->id = out->usecase;
4083 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004084 uc_info->stream.out = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004085 list_init(&uc_info->device_list);
4086 assign_devices(&uc_info->device_list, &out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004087 uc_info->in_snd_device = SND_DEVICE_NONE;
4088 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07004089
4090 /* This must be called before adding this usecase to the list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004091 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07004092 audio_extn_usb_check_and_set_svc_int(uc_info, true);
4093 /* USB backend is not reopened immediately.
4094 This is eventually done as part of select_devices */
4095 }
4096
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004097 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004098
Wei Wangf7ca6c92017-11-21 14:51:20 -08004099 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304100 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4101 adev->perf_lock_opts,
4102 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304103
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004104 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05304105 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304106 if (audio_extn_passthru_is_enabled() &&
4107 audio_extn_passthru_is_passthrough_stream(out)) {
4108 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304109 }
4110 }
4111
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004112 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02004113 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304114 if (!a2dp_combo) {
4115 check_a2dp_restore_l(adev, out, false);
4116 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004117 struct listnode dev;
4118 list_init(&dev);
4119 assign_devices(&dev, &out->device_list);
4120 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4121 reassign_device_list(&out->device_list,
4122 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aalique Grahame22e49102018-12-18 14:23:57 -08004123 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004124 reassign_device_list(&out->device_list,
4125 AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304126 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004127 assign_devices(&out->device_list, &dev);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304128 }
4129 } else {
Revathi Uddarajub26e3932020-06-10 14:51:02 +05304130 select_devices(adev, out->usecase);
4131 if (is_a2dp_out_device_type(&out->device_list) &&
4132 !adev->a2dp_started) {
4133 if (is_speaker_active || is_speaker_safe_active) {
4134 struct listnode dev;
4135 list_init(&dev);
4136 assign_devices(&dev, &out->device_list);
4137 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4138 reassign_device_list(&out->device_list,
4139 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
4140 else
4141 reassign_device_list(&out->device_list,
4142 AUDIO_DEVICE_OUT_SPEAKER, "");
4143 select_devices(adev, out->usecase);
4144 assign_devices(&out->device_list, &dev);
4145 } else {
4146 ret = -EINVAL;
4147 goto error_open;
4148 }
4149 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304150 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004151
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004152 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
4153 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07004154 voice_set_device_mute_flag(adev, true);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004155 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07004156
Derek Chenea197282019-01-07 17:35:01 -08004157 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
4158 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08004159
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004160 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
4161 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07004162
4163 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07004164 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07004165 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4166 ALOGE("%s: pcm stream not ready", __func__);
4167 goto error_open;
4168 }
4169 ret = pcm_start(out->pcm);
4170 if (ret < 0) {
4171 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
4172 goto error_open;
4173 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07004174 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07004175 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004176 unsigned int flags = PCM_OUT;
4177 unsigned int pcm_open_retry_count = 0;
4178 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
4179 flags |= PCM_MMAP | PCM_NOIRQ;
4180 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004181 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08004182 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004183 } else
4184 flags |= PCM_MONOTONIC;
4185
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004186 if ((adev->vr_audio_mode_enabled) &&
4187 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
4188 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4189 "PCM_Dev %d Topology", out->pcm_device_id);
4190 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4191 if (!ctl) {
4192 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
4193 __func__, mixer_ctl_name);
4194 } else {
4195 //if success use ULLPP
4196 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
4197 __func__, mixer_ctl_name, out->pcm_device_id);
4198 //There is a still a possibility that some sessions
4199 // that request for FAST|RAW when 3D audio is active
4200 //can go through ULLPP. Ideally we expects apps to
4201 //listen to audio focus and stop concurrent playback
4202 //Also, we will look for mode flag (voice_in_communication)
4203 //before enabling the realtime flag.
4204 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
4205 }
4206 }
4207
Vatsal Bucha3f39f222021-06-29 16:16:55 +05304208 platform_set_stream_channel_map(adev->platform, out->channel_mask,
4209 out->pcm_device_id, -1, &out->channel_map_param.channel_map[0]);
Surendar Karka91fa3682018-07-02 18:12:12 +05304210
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004211 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
4212 flags, pcm_open_retry_count,
4213 &(out->config));
4214 if (out->pcm == NULL) {
4215 ret = -EIO;
4216 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004217 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004218
4219 if (is_haptic_usecase) {
4220 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
4221 adev->haptic_pcm_device_id,
4222 flags, pcm_open_retry_count,
4223 &(adev->haptics_config));
4224 // failure to open haptics pcm shouldnt stop audio,
4225 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07004226
4227 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
4228 ALOGD("%s: enable haptic audio synchronization", __func__);
4229 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
4230 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004231 }
4232
Zhou Song2b8f28f2017-09-11 10:51:38 +08004233 // apply volume for voip playback after path is set up
4234 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
4235 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05304236 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
4237 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304238 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
4239 out->apply_volume = false;
Derek Chenf13dd492018-11-13 14:53:51 -08004240 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
4241 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304242 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004243 } else {
Zhou Song79929fe2020-01-20 17:57:43 +08004244 /*
4245 * set custom channel map if:
4246 * 1. neither mono nor stereo clips i.e. channels > 2 OR
4247 * 2. custom channel map has been set by client
4248 * else default channel map of FC/FR/FL can always be set to DSP
4249 */
4250 if (popcount(out->channel_mask) > 2 || out->channel_map_param.channel_map[0])
4251 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Weiyin Jiang810a80d2021-01-18 16:04:31 +08004252 out->pcm_device_id, -1, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08004253 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
4254 adev->dsp_bit_width_enforce_mode,
4255 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004256 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07004257 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004258 out->compr = compress_open(adev->snd_card,
4259 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004260 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004261 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05304262 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05304263 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
4264 adev->card_status = CARD_STATUS_OFFLINE;
4265 out->card_status = CARD_STATUS_OFFLINE;
4266 ret = -EIO;
4267 goto error_open;
4268 }
4269
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004270 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004271 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004272 compress_close(out->compr);
4273 out->compr = NULL;
4274 ret = -EIO;
4275 goto error_open;
4276 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304277 /* compress_open sends params of the track, so reset the flag here */
4278 out->is_compr_metadata_avail = false;
4279
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004280 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004281 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07004282
Fred Oh3f43e742015-03-04 18:42:34 -08004283 /* Since small bufs uses blocking writes, a write will be blocked
4284 for the default max poll time (20s) in the event of an SSR.
4285 Reduce the poll time to observe and deal with SSR faster.
4286 */
Ashish Jain5106d362016-05-11 19:23:33 +05304287 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08004288 compress_set_max_poll_wait(out->compr, 1000);
4289 }
4290
Manish Dewangan69426c82017-01-30 17:35:36 +05304291 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05304292 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05304293
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004294 audio_extn_dts_create_state_notifier_node(out->usecase);
4295 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4296 popcount(out->channel_mask),
4297 out->playback_started);
4298
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004299#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304300 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004301 audio_extn_dolby_send_ddp_endp_params(adev);
4302#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05304303 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
4304 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004305 if (adev->visualizer_start_output != NULL)
4306 adev->visualizer_start_output(out->handle, out->pcm_device_id);
4307 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05304308 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004309 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004310 }
Derek Chenf13dd492018-11-13 14:53:51 -08004311
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004312 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf13dd492018-11-13 14:53:51 -08004313 /* Update cached volume from media to offload/direct stream */
4314 struct listnode *node = NULL;
4315 list_for_each(node, &adev->active_outputs_list) {
4316 streams_output_ctxt_t *out_ctxt = node_to_item(node,
4317 streams_output_ctxt_t,
4318 list);
4319 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
4320 out->volume_l = out_ctxt->output->volume_l;
4321 out->volume_r = out_ctxt->output->volume_r;
4322 }
4323 }
4324 out_set_compr_volume(&out->stream,
4325 out->volume_l, out->volume_r);
4326 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004327 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004328
4329 if (ret == 0) {
4330 register_out_stream(out);
4331 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07004332 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4333 ALOGE("%s: pcm stream not ready", __func__);
4334 goto error_open;
4335 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004336 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004337 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004338 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004339 if (ret < 0)
4340 goto error_open;
4341 }
4342 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004343 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304344 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Jaideep Sharma0fa53812020-09-17 09:00:11 +05304345 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004346
vivek mehtad15d2bf2019-05-17 13:35:10 -07004347 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
4348 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4349 audio_low_latency_hint_start();
4350 }
4351
Manish Dewangan21a850a2017-08-14 12:03:55 +05304352 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07004353 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07004354 if (ret < 0)
4355 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
4356 }
4357
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004358 // consider a scenario where on pause lower layers are tear down.
4359 // so on resume, swap mixer control need to be sent only when
4360 // backend is active, hence rather than sending from enable device
4361 // sending it from start of streamtream
4362
4363 platform_set_swap_channels(adev, true);
4364
Haynes Mathew George380745d2017-10-04 15:27:45 -07004365 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304366 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004367 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004368error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004369 if (adev->haptic_pcm) {
4370 pcm_close(adev->haptic_pcm);
4371 adev->haptic_pcm = NULL;
4372 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004373 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304374 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004375 stop_output_stream(out);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004376error_fatal:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05304377 /*
4378 * sleep 50ms to allow sufficient time for kernel
4379 * drivers to recover incases like SSR.
4380 */
4381 usleep(50000);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004382error_config:
Haynes Mathew George380745d2017-10-04 15:27:45 -07004383 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304384 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004385 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004386}
4387
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004388static int check_input_parameters(uint32_t sample_rate,
4389 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08004390 int channel_count,
4391 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004392{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004393 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004394
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304395 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
4396 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
4397 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07004398 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02004399 !audio_extn_compr_cap_format_supported(format) &&
4400 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004401 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004402
Aalique Grahame22e49102018-12-18 14:23:57 -08004403 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
4404 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
4405 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
4406 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
4407 return -EINVAL;
4408 }
4409
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004410 switch (channel_count) {
4411 case 1:
4412 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304413 case 3:
4414 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004415 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07004416 case 8:
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05304417 case 10:
4418 case 12:
4419 case 14:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004420 break;
4421 default:
4422 ret = -EINVAL;
4423 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004424
4425 switch (sample_rate) {
4426 case 8000:
4427 case 11025:
4428 case 12000:
4429 case 16000:
4430 case 22050:
4431 case 24000:
4432 case 32000:
4433 case 44100:
4434 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004435 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304436 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004437 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304438 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004439 break;
4440 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004441 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004442 }
4443
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004444 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004445}
4446
Naresh Tanniru04f71882018-06-26 17:46:22 +05304447
4448/** Add a value in a list if not already present.
4449 * @return true if value was successfully inserted or already present,
4450 * false if the list is full and does not contain the value.
4451 */
4452static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
4453 for (size_t i = 0; i < list_length; i++) {
4454 if (list[i] == value) return true; // value is already present
4455 if (list[i] == 0) { // no values in this slot
4456 list[i] = value;
4457 return true; // value inserted
4458 }
4459 }
4460 return false; // could not insert value
4461}
4462
4463/** Add channel_mask in supported_channel_masks if not already present.
4464 * @return true if channel_mask was successfully inserted or already present,
4465 * false if supported_channel_masks is full and does not contain channel_mask.
4466 */
4467static void register_channel_mask(audio_channel_mask_t channel_mask,
4468 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
4469 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
4470 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
4471}
4472
4473/** Add format in supported_formats if not already present.
4474 * @return true if format was successfully inserted or already present,
4475 * false if supported_formats is full and does not contain format.
4476 */
4477static void register_format(audio_format_t format,
4478 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
4479 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
4480 "%s: stream can not declare supporting its format %x", __func__, format);
4481}
4482/** Add sample_rate in supported_sample_rates if not already present.
4483 * @return true if sample_rate was successfully inserted or already present,
4484 * false if supported_sample_rates is full and does not contain sample_rate.
4485 */
4486static void register_sample_rate(uint32_t sample_rate,
4487 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
4488 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
4489 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
4490}
4491
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004492static inline uint32_t lcm(uint32_t num1, uint32_t num2)
4493{
4494 uint32_t high = num1, low = num2, temp = 0;
4495
4496 if (!num1 || !num2)
4497 return 0;
4498
4499 if (num1 < num2) {
4500 high = num2;
4501 low = num1;
4502 }
4503
4504 while (low != 0) {
4505 temp = low;
4506 low = high % low;
4507 high = temp;
4508 }
4509 return (num1 * num2)/high;
4510}
4511
4512static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
4513{
4514 uint32_t remainder = 0;
4515
4516 if (!multiplier)
4517 return num;
4518
4519 remainder = num % multiplier;
4520 if (remainder)
4521 num += (multiplier - remainder);
4522
4523 return num;
4524}
4525
Aalique Grahame22e49102018-12-18 14:23:57 -08004526static size_t get_stream_buffer_size(size_t duration_ms,
4527 uint32_t sample_rate,
4528 audio_format_t format,
4529 int channel_count,
4530 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004531{
4532 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004533 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004534
Aalique Grahame22e49102018-12-18 14:23:57 -08004535 size = (sample_rate * duration_ms) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004536 if (is_low_latency)
4537 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304538
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004539 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08004540 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004541
Ralf Herzbd08d632018-09-28 15:50:49 +02004542 /* make sure the size is multiple of 32 bytes and additionally multiple of
4543 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004544 * At 48 kHz mono 16-bit PCM:
4545 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
4546 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004547 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004548 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004549 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07004550
4551 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004552}
4553
Aalique Grahame22e49102018-12-18 14:23:57 -08004554static size_t get_input_buffer_size(uint32_t sample_rate,
4555 audio_format_t format,
4556 int channel_count,
4557 bool is_low_latency)
4558{
4559 /* Don't know if USB HIFI in this context so use true to be conservative */
4560 if (check_input_parameters(sample_rate, format, channel_count,
4561 true /*is_usb_hifi */) != 0)
4562 return 0;
4563
4564 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4565 sample_rate,
4566 format,
4567 channel_count,
4568 is_low_latency);
4569}
4570
Derek Chenf6318be2017-06-12 17:16:24 -04004571size_t get_output_period_size(uint32_t sample_rate,
4572 audio_format_t format,
4573 int channel_count,
4574 int duration /*in millisecs*/)
Ashish Jain058165c2016-09-28 23:18:48 +05304575{
4576 size_t size = 0;
4577 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
4578
4579 if ((duration == 0) || (sample_rate == 0) ||
4580 (bytes_per_sample == 0) || (channel_count == 0)) {
4581 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
4582 bytes_per_sample, channel_count);
4583 return -EINVAL;
4584 }
4585
4586 size = (sample_rate *
4587 duration *
4588 bytes_per_sample *
4589 channel_count) / 1000;
4590 /*
4591 * To have same PCM samples for all channels, the buffer size requires to
4592 * be multiple of (number of channels * bytes per sample)
4593 * For writes to succeed, the buffer must be written at address which is multiple of 32
4594 */
4595 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
4596
4597 return (size/(channel_count * bytes_per_sample));
4598}
4599
Zhou Song48453a02018-01-10 17:50:59 +08004600static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05304601{
4602 uint64_t actual_frames_rendered = 0;
Weiyin Jiang4813da12020-05-28 00:37:28 +08004603 uint64_t written_frames = 0;
4604 uint64_t kernel_frames = 0;
4605 uint64_t dsp_frames = 0;
4606 uint64_t signed_frames = 0;
4607 size_t kernel_buffer_size = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304608
4609 /* This adjustment accounts for buffering after app processor.
4610 * It is based on estimated DSP latency per use case, rather than exact.
4611 */
George Gao9ba8a142020-07-23 14:30:03 -07004612 dsp_frames = platform_render_latency(out) *
Weiyin Jiang4813da12020-05-28 00:37:28 +08004613 out->sample_rate / 1000000LL;
Ashish Jain5106d362016-05-11 19:23:33 +05304614
Zhou Song48453a02018-01-10 17:50:59 +08004615 pthread_mutex_lock(&out->position_query_lock);
Weiyin Jiang4813da12020-05-28 00:37:28 +08004616 written_frames = out->written /
4617 (audio_bytes_per_sample(out->hal_ip_format) * popcount(out->channel_mask));
4618
Ashish Jain5106d362016-05-11 19:23:33 +05304619 /* not querying actual state of buffering in kernel as it would involve an ioctl call
4620 * which then needs protection, this causes delay in TS query for pcm_offload usecase
4621 * hence only estimate.
4622 */
Weiyin Jiang4813da12020-05-28 00:37:28 +08004623 kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
4624 kernel_frames = kernel_buffer_size /
4625 (audio_bytes_per_sample(out->hal_op_format) * popcount(out->channel_mask));
Ashish Jain5106d362016-05-11 19:23:33 +05304626
Weiyin Jiang4813da12020-05-28 00:37:28 +08004627 if (written_frames >= (kernel_frames + dsp_frames))
4628 signed_frames = written_frames - kernel_frames - dsp_frames;
Ashish Jain5106d362016-05-11 19:23:33 +05304629
Zhou Song48453a02018-01-10 17:50:59 +08004630 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05304631 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08004632 if (timestamp != NULL )
4633 *timestamp = out->writeAt;
4634 } else if (timestamp != NULL) {
4635 clock_gettime(CLOCK_MONOTONIC, timestamp);
4636 }
4637 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304638
Weiyin Jiang4813da12020-05-28 00:37:28 +08004639 ALOGVV("%s signed frames %lld written frames %lld kernel frames %lld dsp frames %lld",
4640 __func__, signed_frames, written_frames, kernel_frames, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05304641
4642 return actual_frames_rendered;
4643}
4644
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004645static uint32_t out_get_sample_rate(const struct audio_stream *stream)
4646{
4647 struct stream_out *out = (struct stream_out *)stream;
4648
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004649 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004650}
4651
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004652static int out_set_sample_rate(struct audio_stream *stream __unused,
4653 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004654{
4655 return -ENOSYS;
4656}
4657
4658static size_t out_get_buffer_size(const struct audio_stream *stream)
4659{
4660 struct stream_out *out = (struct stream_out *)stream;
4661
Varun Balaraje49253e2017-07-06 19:48:56 +05304662 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05304663 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05304664 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304665 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4666 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
4667 else
4668 return out->compr_config.fragment_size;
4669 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004670 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304671 else if (is_offload_usecase(out->usecase) &&
4672 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304673 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004674
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004675 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004676 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004677}
4678
4679static uint32_t out_get_channels(const struct audio_stream *stream)
4680{
4681 struct stream_out *out = (struct stream_out *)stream;
4682
4683 return out->channel_mask;
4684}
4685
4686static audio_format_t out_get_format(const struct audio_stream *stream)
4687{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004688 struct stream_out *out = (struct stream_out *)stream;
4689
4690 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004691}
4692
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004693static int out_set_format(struct audio_stream *stream __unused,
4694 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004695{
4696 return -ENOSYS;
4697}
4698
4699static int out_standby(struct audio_stream *stream)
4700{
4701 struct stream_out *out = (struct stream_out *)stream;
4702 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07004703 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004704
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304705 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4706 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004707
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004708 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004709 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004710 if (adev->adm_deregister_stream)
4711 adev->adm_deregister_stream(adev->adm_data, out->handle);
4712
Weiyin Jiang280ea742020-09-08 20:28:22 +08004713 if (is_offload_usecase(out->usecase)) {
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004714 stop_compressed_output_l(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08004715 }
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004716
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004717 pthread_mutex_lock(&adev->lock);
Daniel Hillenbrand17873952013-05-23 10:10:00 +05304718
4719 amplifier_output_stream_standby((struct audio_stream_out *) stream);
4720
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004721 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004722 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4723 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304724 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08004725 pthread_mutex_unlock(&adev->lock);
4726 pthread_mutex_unlock(&out->lock);
4727 ALOGD("VOIP output entered standby");
4728 return 0;
4729 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004730 if (out->pcm) {
4731 pcm_close(out->pcm);
4732 out->pcm = NULL;
4733 }
Meng Wanga09da002020-04-20 12:56:04 +08004734 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4735 if (adev->haptic_pcm) {
4736 pcm_close(adev->haptic_pcm);
4737 adev->haptic_pcm = NULL;
4738 }
4739
4740 if (adev->haptic_buffer != NULL) {
4741 free(adev->haptic_buffer);
4742 adev->haptic_buffer = NULL;
4743 adev->haptic_buffer_size = 0;
4744 }
4745 adev->haptic_pcm_device_id = 0;
4746 }
4747
Haynes Mathew George16081042017-05-31 17:16:49 -07004748 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4749 do_stop = out->playback_started;
4750 out->playback_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07004751
4752 if (out->mmap_shared_memory_fd >= 0) {
4753 ALOGV("%s: closing mmap_shared_memory_fd = %d",
4754 __func__, out->mmap_shared_memory_fd);
4755 close(out->mmap_shared_memory_fd);
4756 out->mmap_shared_memory_fd = -1;
4757 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004758 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004759 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004760 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304761 out->send_next_track_params = false;
4762 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004763 out->gapless_mdata.encoder_delay = 0;
4764 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004765 if (out->compr != NULL) {
4766 compress_close(out->compr);
4767 out->compr = NULL;
4768 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004769 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004770 if (do_stop) {
4771 stop_output_stream(out);
4772 }
Lakshman Chaluvaraju06677b42019-06-24 10:04:52 +05304773 // if fm is active route on selected device in UI
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004774 audio_extn_fm_route_on_selected_device(adev, &out->device_list);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004775 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004776 }
4777 pthread_mutex_unlock(&out->lock);
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07004778 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004779 return 0;
4780}
4781
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304782static int out_on_error(struct audio_stream *stream)
4783{
4784 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004785 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304786
4787 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004788 // always send CMD_ERROR for offload streams, this
4789 // is needed e.g. when SSR happens within compress_open
4790 // since the stream is active, offload_callback_thread is also active.
4791 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
4792 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004793 }
4794 pthread_mutex_unlock(&out->lock);
4795
4796 status = out_standby(&out->stream.common);
4797
4798 lock_output_stream(out);
4799 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004800 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304801 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05304802
4803 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
4804 ALOGD("Setting previous card status if offline");
4805 out->prev_card_status_offline = true;
4806 }
4807
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304808 pthread_mutex_unlock(&out->lock);
4809
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004810 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304811}
4812
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304813/*
Weiyin Jiang280ea742020-09-08 20:28:22 +08004814 * standby implementation without locks, assumes that the callee already
4815 * has taken adev and out lock.
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304816 */
4817int out_standby_l(struct audio_stream *stream)
4818{
4819 struct stream_out *out = (struct stream_out *)stream;
4820 struct audio_device *adev = out->dev;
4821
4822 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4823 stream, out->usecase, use_case_table[out->usecase]);
4824
4825 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07004826 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304827 if (adev->adm_deregister_stream)
4828 adev->adm_deregister_stream(adev->adm_data, out->handle);
4829
Weiyin Jiang280ea742020-09-08 20:28:22 +08004830 if (is_offload_usecase(out->usecase)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304831 stop_compressed_output_l(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08004832 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304833
4834 out->standby = true;
4835 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4836 voice_extn_compress_voip_close_output_stream(stream);
4837 out->started = 0;
4838 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07004839 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304840 return 0;
4841 } else if (!is_offload_usecase(out->usecase)) {
4842 if (out->pcm) {
4843 pcm_close(out->pcm);
4844 out->pcm = NULL;
4845 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004846 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4847 if (adev->haptic_pcm) {
4848 pcm_close(adev->haptic_pcm);
4849 adev->haptic_pcm = NULL;
4850 }
4851
4852 if (adev->haptic_buffer != NULL) {
4853 free(adev->haptic_buffer);
4854 adev->haptic_buffer = NULL;
4855 adev->haptic_buffer_size = 0;
4856 }
4857 adev->haptic_pcm_device_id = 0;
4858 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304859 } else {
4860 ALOGD("copl(%p):standby", out);
4861 out->send_next_track_params = false;
4862 out->is_compr_metadata_avail = false;
4863 out->gapless_mdata.encoder_delay = 0;
4864 out->gapless_mdata.encoder_padding = 0;
4865 if (out->compr != NULL) {
4866 compress_close(out->compr);
4867 out->compr = NULL;
4868 }
4869 }
4870 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004871 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304872 }
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07004873 ALOGV("%s: exit", __func__);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304874 return 0;
4875}
4876
Aalique Grahame22e49102018-12-18 14:23:57 -08004877static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004878{
Aalique Grahame22e49102018-12-18 14:23:57 -08004879 struct stream_out *out = (struct stream_out *)stream;
4880
4881 // We try to get the lock for consistency,
4882 // but it isn't necessary for these variables.
4883 // If we're not in standby, we may be blocked on a write.
4884 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
4885 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
4886 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
Dechen Chai22768452021-07-30 09:29:16 +05304887#ifndef LINUX_ENABLED
Andy Hunga1f48fa2019-07-01 18:14:53 -07004888 char buffer[256]; // for statistics formatting
4889 if (!is_offload_usecase(out->usecase)) {
4890 simple_stats_to_string(&out->fifo_underruns, buffer, sizeof(buffer));
4891 dprintf(fd, " Fifo frame underruns: %s\n", buffer);
4892 }
4893
Andy Hungc6bfd4a2019-07-01 18:26:00 -07004894 if (out->start_latency_ms.n > 0) {
4895 simple_stats_to_string(&out->start_latency_ms, buffer, sizeof(buffer));
4896 dprintf(fd, " Start latency ms: %s\n", buffer);
4897 }
Dechen Chai22768452021-07-30 09:29:16 +05304898#endif
Aalique Grahame22e49102018-12-18 14:23:57 -08004899 if (locked) {
4900 pthread_mutex_unlock(&out->lock);
4901 }
4902
Dechen Chai22768452021-07-30 09:29:16 +05304903#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -08004904 // dump error info
4905 (void)error_log_dump(
4906 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Dechen Chai22768452021-07-30 09:29:16 +05304907#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004908 return 0;
4909}
4910
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004911static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
4912{
4913 int ret = 0;
4914 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08004915
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004916 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004917 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004918 return -EINVAL;
4919 }
4920
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304921 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08004922
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004923 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
4924 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304925 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004926 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004927 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
4928 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304929 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004930 }
4931
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004932 ALOGV("%s new encoder delay %u and padding %u", __func__,
4933 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
4934
4935 return 0;
4936}
4937
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004938static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
4939{
4940 return out == adev->primary_output || out == adev->voice_tx_output;
4941}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004942
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304943// note: this call is safe only if the stream_cb is
4944// removed first in close_output_stream (as is done now).
4945static void out_snd_mon_cb(void * stream, struct str_parms * parms)
4946{
4947 if (!stream || !parms)
4948 return;
4949
4950 struct stream_out *out = (struct stream_out *)stream;
4951 struct audio_device *adev = out->dev;
4952
4953 card_status_t status;
4954 int card;
4955 if (parse_snd_card_status(parms, &card, &status) < 0)
4956 return;
4957
4958 pthread_mutex_lock(&adev->lock);
4959 bool valid_cb = (card == adev->snd_card);
4960 pthread_mutex_unlock(&adev->lock);
4961
4962 if (!valid_cb)
4963 return;
4964
4965 lock_output_stream(out);
4966 if (out->card_status != status)
4967 out->card_status = status;
4968 pthread_mutex_unlock(&out->lock);
4969
4970 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
4971 use_case_table[out->usecase],
4972 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4973
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304974 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304975 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304976 if (voice_is_call_state_active(adev) &&
4977 out == adev->primary_output) {
4978 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
4979 pthread_mutex_lock(&adev->lock);
4980 voice_stop_call(adev);
4981 adev->mode = AUDIO_MODE_NORMAL;
4982 pthread_mutex_unlock(&adev->lock);
4983 }
4984 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304985 return;
4986}
4987
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004988int route_output_stream(struct stream_out *out,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004989 struct listnode *devices)
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004990{
4991 struct audio_device *adev = out->dev;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004992 int ret = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004993 struct listnode new_devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004994 bool bypass_a2dp = false;
4995 bool reconfig = false;
4996 unsigned long service_interval = 0;
4997
4998 ALOGD("%s: enter: usecase(%d: %s) devices %x",
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004999 __func__, out->usecase, use_case_table[out->usecase], get_device_types(devices));
5000
5001 list_init(&new_devices);
5002 assign_devices(&new_devices, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005003
5004 lock_output_stream(out);
5005 pthread_mutex_lock(&adev->lock);
5006
5007 /*
5008 * When HDMI cable is unplugged the music playback is paused and
5009 * the policy manager sends routing=0. But the audioflinger continues
5010 * to write data until standby time (3sec). As the HDMI core is
5011 * turned off, the write gets blocked.
5012 * Avoid this by routing audio to speaker until standby.
5013 */
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08005014 if (is_single_device_type_equal(&out->device_list,
5015 AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005016 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005017 !audio_extn_passthru_is_passthrough_stream(out) &&
5018 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005019 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005020 }
5021 /*
5022 * When A2DP is disconnected the
5023 * music playback is paused and the policy manager sends routing=0
5024 * But the audioflinger continues to write data until standby time
5025 * (3sec). As BT is turned off, the write gets blocked.
5026 * Avoid this by routing audio to speaker until standby.
5027 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005028 if (is_a2dp_out_device_type(&out->device_list) &&
5029 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005030 !audio_extn_a2dp_source_is_ready() &&
5031 !adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005032 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005033 }
5034 /*
Weiyin Jiangabedea32020-12-09 12:49:19 +08005035 * When USB headset is disconnected the music playback paused
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005036 * and the policy manager send routing=0. But if the USB is connected
5037 * back before the standby time, AFE is not closed and opened
5038 * when USB is connected back. So routing to speker will guarantee
5039 * AFE reconfiguration and AFE will be opend once USB is connected again
5040 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005041 if (is_usb_out_device_type(&out->device_list) &&
5042 list_empty(&new_devices) &&
5043 !audio_extn_usb_connected(NULL)) {
Sujin Panicker84d953a2020-11-16 17:39:54 +05305044 if (adev->mode == AUDIO_MODE_IN_CALL || adev->mode == AUDIO_MODE_IN_COMMUNICATION)
5045 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_EARPIECE, "");
5046 else
5047 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005048 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005049 /* To avoid a2dp to sco overlapping / BT device improper state
5050 * check with BT lib about a2dp streaming support before routing
5051 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005052 if (is_a2dp_out_device_type(&new_devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005053 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005054 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER) ||
5055 compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005056 //combo usecase just by pass a2dp
5057 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
5058 bypass_a2dp = true;
5059 } else {
5060 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
5061 /* update device to a2dp and don't route as BT returned error
5062 * However it is still possible a2dp routing called because
5063 * of current active device disconnection (like wired headset)
5064 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005065 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005066 pthread_mutex_unlock(&adev->lock);
5067 pthread_mutex_unlock(&out->lock);
5068 goto error;
5069 }
5070 }
5071 }
5072
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005073 // Workaround: If routing to an non existing usb device, fail gracefully
5074 // The routing request will otherwise block during 10 second
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005075 if (is_usb_out_device_type(&new_devices)) {
5076 struct str_parms *parms =
5077 str_parms_create_str(get_usb_device_address(&new_devices));
5078 if (!parms)
5079 goto error;
Weiyin Jiangabedea32020-12-09 12:49:19 +08005080 if (!audio_extn_usb_connected(NULL)) {
5081 ALOGW("%s: ignoring rerouting to non existing USB card", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005082 pthread_mutex_unlock(&adev->lock);
5083 pthread_mutex_unlock(&out->lock);
5084 str_parms_destroy(parms);
5085 ret = -ENOSYS;
5086 goto error;
5087 }
5088 str_parms_destroy(parms);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005089 }
5090
Weiyin Jiang80c8f9a2020-01-10 20:42:08 +08005091 // Workaround: If routing to an non existing hdmi device, fail gracefully
5092 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
5093 (platform_get_edid_info_v2(adev->platform,
5094 out->extconn.cs.controller,
5095 out->extconn.cs.stream) != 0)) {
5096 ALOGW("out_set_parameters() ignoring rerouting to non existing HDMI/DP");
5097 pthread_mutex_unlock(&adev->lock);
5098 pthread_mutex_unlock(&out->lock);
5099 ret = -ENOSYS;
5100 goto error;
5101 }
5102
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005103 /*
5104 * select_devices() call below switches all the usecases on the same
5105 * backend to the new device. Refer to check_usecases_codec_backend() in
5106 * the select_devices(). But how do we undo this?
5107 *
5108 * For example, music playback is active on headset (deep-buffer usecase)
5109 * and if we go to ringtones and select a ringtone, low-latency usecase
5110 * will be started on headset+speaker. As we can't enable headset+speaker
5111 * and headset devices at the same time, select_devices() switches the music
5112 * playback to headset+speaker while starting low-lateny usecase for ringtone.
5113 * So when the ringtone playback is completed, how do we undo the same?
5114 *
5115 * We are relying on the out_set_parameters() call on deep-buffer output,
5116 * once the ringtone playback is ended.
5117 * NOTE: We should not check if the current devices are same as new devices.
5118 * Because select_devices() must be called to switch back the music
5119 * playback to headset.
5120 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005121 if (!list_empty(&new_devices)) {
5122 bool same_dev = compare_devices(&out->device_list, &new_devices);
5123 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005124
5125 if (output_drives_call(adev, out)) {
5126 if (!voice_is_call_state_active(adev)) {
5127 if (adev->mode == AUDIO_MODE_IN_CALL) {
5128 adev->current_call_output = out;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005129 ret = voice_start_call(adev);
5130 }
5131 } else {
Kunlei Zhang253ad102020-10-14 16:21:28 +08005132 platform_is_volume_boost_supported_device(adev->platform, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005133 adev->current_call_output = out;
5134 voice_update_devices_for_all_voice_usecases(adev);
5135 }
5136 }
5137
Mingshu Pang971ff702020-09-09 15:28:22 +08005138 if (is_usb_out_device_type(&out->device_list)) {
5139 service_interval = audio_extn_usb_find_service_interval(false, true /*playback*/);
5140 audio_extn_usb_set_service_interval(true /*playback*/,
5141 service_interval,
5142 &reconfig);
5143 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
5144 }
5145
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005146 if (!out->standby) {
5147 if (!same_dev) {
5148 ALOGV("update routing change");
5149 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
5150 adev->perf_lock_opts,
5151 adev->perf_lock_opts_size);
5152 if (adev->adm_on_routing_change)
5153 adev->adm_on_routing_change(adev->adm_data,
5154 out->handle);
5155 }
5156 if (!bypass_a2dp) {
5157 select_devices(adev, out->usecase);
5158 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005159 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
5160 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005161 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005162 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005163 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005164 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005165 }
5166
5167 if (!same_dev) {
5168 // on device switch force swap, lower functions will make sure
5169 // to check if swap is allowed or not.
5170 platform_set_swap_channels(adev, true);
5171 audio_extn_perf_lock_release(&adev->perf_lock_handle);
5172 }
Zhou Songbaddf9f2020-11-20 13:57:39 +08005173 pthread_mutex_lock(&out->latch_lock);
5174 if (!is_a2dp_out_device_type(&out->device_list) || audio_extn_a2dp_source_is_ready()) {
5175 if (out->a2dp_muted) {
5176 out->a2dp_muted = false;
5177 if (is_offload_usecase(out->usecase))
5178 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5179 else if (out->usecase != USECASE_AUDIO_PLAYBACK_VOIP)
5180 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Weiyin Jiang280ea742020-09-08 20:28:22 +08005181 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005182 }
Zhou Songbaddf9f2020-11-20 13:57:39 +08005183 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP && !out->a2dp_muted)
5184 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
5185 pthread_mutex_unlock(&out->latch_lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005186 }
5187 }
5188
5189 pthread_mutex_unlock(&adev->lock);
5190 pthread_mutex_unlock(&out->lock);
5191
5192 /*handles device and call state changes*/
5193 audio_extn_extspk_update(adev->extspk);
5194
5195error:
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005196 ALOGV("%s: exit: code(%d)", __func__, ret);
5197 return ret;
5198}
5199
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005200static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
5201{
5202 struct stream_out *out = (struct stream_out *)stream;
5203 struct audio_device *adev = out->dev;
5204 struct str_parms *parms;
5205 char value[32];
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005206 int ret = 0, err;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005207 int ext_controller = -1;
5208 int ext_stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005209
sangwoobc677242013-08-08 16:53:43 +09005210 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005211 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005212 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305213 if (!parms)
5214 goto error;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005215
Daniel Hillenbrand17873952013-05-23 10:10:00 +05305216 amplifier_out_set_parameters(parms);
5217
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005218 err = platform_get_controller_stream_from_params(parms, &ext_controller,
5219 &ext_stream);
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08005220 if (err == 0) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005221 out->extconn.cs.controller = ext_controller;
5222 out->extconn.cs.stream = ext_stream;
5223 ALOGD("%s: usecase(%s) new controller/stream (%d/%d)", __func__,
5224 use_case_table[out->usecase], out->extconn.cs.controller,
5225 out->extconn.cs.stream);
5226 }
5227
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005228 if (out == adev->primary_output) {
5229 pthread_mutex_lock(&adev->lock);
5230 audio_extn_set_parameters(adev, parms);
5231 pthread_mutex_unlock(&adev->lock);
5232 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005233 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005234 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005235 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005236
5237 audio_extn_dts_create_state_notifier_node(out->usecase);
5238 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5239 popcount(out->channel_mask),
5240 out->playback_started);
5241
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08005242 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005243 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005244
Surendar Karkaf51b5842018-04-26 11:28:38 +05305245 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
5246 sizeof(value));
5247 if (err >= 0) {
5248 if (!strncmp("true", value, sizeof("true")) || atoi(value))
5249 audio_extn_send_dual_mono_mixing_coefficients(out);
5250 }
5251
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305252 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5253 if (err >= 0) {
5254 strlcpy(out->profile, value, sizeof(out->profile));
5255 ALOGV("updating stream profile with value '%s'", out->profile);
5256 lock_output_stream(out);
5257 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
5258 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005259 &out->device_list, out->flags,
5260 out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305261 out->sample_rate, out->bit_width,
5262 out->channel_mask, out->profile,
5263 &out->app_type_cfg);
5264 pthread_mutex_unlock(&out->lock);
5265 }
5266
Alexy Joseph98988832017-01-13 14:56:59 -08005267 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005268 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
5269 // and vendor.audio.hal.output.suspend.supported is set to true
5270 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08005271 //check suspend parameter only for low latency and if the property
5272 //is enabled
5273 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
5274 ALOGI("%s: got suspend_playback %s", __func__, value);
5275 lock_output_stream(out);
5276 if (!strncmp(value, "false", 5)) {
5277 //suspend_playback=false is supposed to set QOS value back to 75%
5278 //the mixer control sent with value Enable will achieve that
5279 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5280 } else if (!strncmp (value, "true", 4)) {
5281 //suspend_playback=true is supposed to remove QOS value
5282 //resetting the mixer control will set the default value
5283 //for the mixer control which is Disable and this removes the QOS vote
5284 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5285 } else {
5286 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
5287 " got %s", __func__, value);
5288 ret = -1;
5289 }
5290
5291 if (ret != 0) {
5292 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
5293 __func__, out->pm_qos_mixer_path, ret);
5294 }
5295
5296 pthread_mutex_unlock(&out->lock);
5297 }
5298 }
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005299
Alexy Joseph98988832017-01-13 14:56:59 -08005300 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005301 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305302error:
Eric Laurent994a6932013-07-17 11:51:42 -07005303 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005304 return ret;
5305}
5306
Paul McLeana50b7332018-12-17 08:24:21 -07005307static int in_set_microphone_direction(const struct audio_stream_in *stream,
5308 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07005309 struct stream_in *in = (struct stream_in *)stream;
5310
5311 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
5312
5313 in->direction = dir;
5314
5315 if (in->standby)
5316 return 0;
5317
5318 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07005319}
5320
5321static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07005322 struct stream_in *in = (struct stream_in *)stream;
5323
5324 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
5325
5326 if (zoom > 1.0 || zoom < -1.0)
5327 return -EINVAL;
5328
5329 in->zoom = zoom;
5330
5331 if (in->standby)
5332 return 0;
5333
5334 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07005335}
5336
5337
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005338static bool stream_get_parameter_channels(struct str_parms *query,
5339 struct str_parms *reply,
5340 audio_channel_mask_t *supported_channel_masks) {
5341 int ret = -1;
5342 char value[512];
5343 bool first = true;
5344 size_t i, j;
5345
5346 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
5347 ret = 0;
5348 value[0] = '\0';
5349 i = 0;
5350 while (supported_channel_masks[i] != 0) {
5351 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5352 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
5353 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305354 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005355
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305356 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005357 first = false;
5358 break;
5359 }
5360 }
5361 i++;
5362 }
5363 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5364 }
5365 return ret == 0;
5366}
5367
5368static bool stream_get_parameter_formats(struct str_parms *query,
5369 struct str_parms *reply,
5370 audio_format_t *supported_formats) {
5371 int ret = -1;
5372 char value[256];
5373 size_t i, j;
5374 bool first = true;
5375
5376 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
5377 ret = 0;
5378 value[0] = '\0';
5379 i = 0;
5380 while (supported_formats[i] != 0) {
5381 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5382 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
5383 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305384 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005385 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305386 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005387 first = false;
5388 break;
5389 }
5390 }
5391 i++;
5392 }
5393 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
5394 }
5395 return ret == 0;
5396}
5397
5398static bool stream_get_parameter_rates(struct str_parms *query,
5399 struct str_parms *reply,
5400 uint32_t *supported_sample_rates) {
5401
5402 int i;
5403 char value[256];
5404 int ret = -1;
5405 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
5406 ret = 0;
5407 value[0] = '\0';
5408 i=0;
5409 int cursor = 0;
5410 while (supported_sample_rates[i]) {
5411 int avail = sizeof(value) - cursor;
5412 ret = snprintf(value + cursor, avail, "%s%d",
5413 cursor > 0 ? "|" : "",
5414 supported_sample_rates[i]);
5415 if (ret < 0 || ret >= avail) {
5416 // if cursor is at the last element of the array
5417 // overwrite with \0 is duplicate work as
5418 // snprintf already put a \0 in place.
5419 // else
5420 // we had space to write the '|' at value[cursor]
5421 // (which will be overwritten) or no space to fill
5422 // the first element (=> cursor == 0)
5423 value[cursor] = '\0';
5424 break;
5425 }
5426 cursor += ret;
5427 ++i;
5428 }
5429 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
5430 value);
5431 }
5432 return ret >= 0;
5433}
5434
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005435static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
5436{
5437 struct stream_out *out = (struct stream_out *)stream;
5438 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005439 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005440 char value[256];
5441 struct str_parms *reply = str_parms_create();
5442 size_t i, j;
5443 int ret;
5444 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005445
5446 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005447 if (reply) {
5448 str_parms_destroy(reply);
5449 }
5450 if (query) {
5451 str_parms_destroy(query);
5452 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005453 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
5454 return NULL;
5455 }
5456
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005457 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005458 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
5459 if (ret >= 0) {
5460 value[0] = '\0';
5461 i = 0;
5462 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005463 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5464 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005465 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005466 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005467 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005468 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005469 first = false;
5470 break;
5471 }
5472 }
5473 i++;
5474 }
5475 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5476 str = str_parms_to_str(reply);
5477 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005478 voice_extn_out_get_parameters(out, query, reply);
5479 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005480 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005481
Alexy Joseph62142aa2015-11-16 15:10:34 -08005482
5483 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
5484 if (ret >= 0) {
5485 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05305486 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
5487 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08005488 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305489 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005490 } else {
5491 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05305492 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005493 }
5494 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005495 if (str)
5496 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08005497 str = str_parms_to_str(reply);
5498 }
5499
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005500 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
5501 if (ret >= 0) {
5502 value[0] = '\0';
5503 i = 0;
5504 first = true;
5505 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005506 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5507 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005508 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005509 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005510 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005511 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005512 first = false;
5513 break;
5514 }
5515 }
5516 i++;
5517 }
5518 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005519 if (str)
5520 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005521 str = str_parms_to_str(reply);
5522 }
Mingming Yin3a941d42016-02-17 18:08:05 -08005523
5524 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
5525 if (ret >= 0) {
5526 value[0] = '\0';
5527 i = 0;
5528 first = true;
5529 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005530 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
5531 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005532 if (!first) {
5533 strlcat(value, "|", sizeof(value));
5534 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005535 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08005536 first = false;
5537 break;
5538 }
5539 }
5540 i++;
5541 }
5542 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
5543 if (str)
5544 free(str);
5545 str = str_parms_to_str(reply);
5546 }
5547
Alexy Joseph98988832017-01-13 14:56:59 -08005548 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
5549 //only low latency track supports suspend_resume
5550 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005551 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08005552 if (str)
5553 free(str);
5554 str = str_parms_to_str(reply);
5555 }
5556
5557
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005558 str_parms_destroy(query);
5559 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07005560 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005561 return str;
5562}
5563
5564static uint32_t out_get_latency(const struct audio_stream_out *stream)
5565{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005566 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005567 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08005568 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005569
Alexy Josephaa54c872014-12-03 02:46:47 -08005570 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05305571 lock_output_stream(out);
5572 latency = audio_extn_utils_compress_get_dsp_latency(out);
5573 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005574 } else if ((out->realtime) ||
5575 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005576 // since the buffer won't be filled up faster than realtime,
5577 // return a smaller number
5578 if (out->config.rate)
5579 period_ms = (out->af_period_multiplier * out->config.period_size *
5580 1000) / (out->config.rate);
5581 else
5582 period_ms = 0;
George Gao9ba8a142020-07-23 14:30:03 -07005583 latency = period_ms + platform_render_latency(out) / 1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005584 } else {
5585 latency = (out->config.period_count * out->config.period_size * 1000) /
Mingshu Pangf69a88d2021-04-30 16:14:39 +08005586 (out->config.rate);
5587 if (out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER)
5588 latency += platform_render_latency(out)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005589 }
5590
Zhou Songd2537a02020-06-11 22:04:46 +08005591 if (!out->standby && is_a2dp_out_device_type(&out->device_list))
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08005592 latency += audio_extn_a2dp_get_encoder_latency();
5593
Anish Kumar50ebcbf2014-12-09 04:01:39 +05305594 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08005595 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005596}
5597
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305598static float AmpToDb(float amplification)
5599{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305600 float db = DSD_VOLUME_MIN_DB;
5601 if (amplification > 0) {
5602 db = 20 * log10(amplification);
5603 if(db < DSD_VOLUME_MIN_DB)
5604 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305605 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305606 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305607}
5608
Arun Mirpuri5d170872019-03-26 13:21:31 -07005609static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
5610 float right)
5611{
5612 struct stream_out *out = (struct stream_out *)stream;
5613 long volume = 0;
5614 char mixer_ctl_name[128] = "";
5615 struct audio_device *adev = out->dev;
5616 struct mixer_ctl *ctl = NULL;
5617 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5618 PCM_PLAYBACK);
5619
5620 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5621 "Playback %d Volume", pcm_device_id);
5622 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5623 if (!ctl) {
5624 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5625 __func__, mixer_ctl_name);
5626 return -EINVAL;
5627 }
5628 if (left != right)
5629 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
5630 __func__, left, right);
5631 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
5632 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
5633 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
5634 __func__, mixer_ctl_name, volume);
5635 return -EINVAL;
5636 }
5637 return 0;
5638}
5639
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305640static int out_set_compr_volume(struct audio_stream_out *stream, float left,
5641 float right)
5642{
5643 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305644 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305645 char mixer_ctl_name[128];
5646 struct audio_device *adev = out->dev;
5647 struct mixer_ctl *ctl;
5648 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5649 PCM_PLAYBACK);
5650
5651 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5652 "Compress Playback %d Volume", pcm_device_id);
5653 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5654 if (!ctl) {
5655 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5656 __func__, mixer_ctl_name);
5657 return -EINVAL;
5658 }
5659 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
5660 __func__, mixer_ctl_name, left, right);
5661 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
5662 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
5663 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5664
5665 return 0;
5666}
5667
Zhou Song2b8f28f2017-09-11 10:51:38 +08005668static int out_set_voip_volume(struct audio_stream_out *stream, float left,
5669 float right)
5670{
5671 struct stream_out *out = (struct stream_out *)stream;
5672 char mixer_ctl_name[] = "App Type Gain";
5673 struct audio_device *adev = out->dev;
5674 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305675 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08005676
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07005677 if (!is_valid_volume(left, right)) {
5678 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
5679 __func__, left, right);
5680 return -EINVAL;
5681 }
5682
Zhou Song2b8f28f2017-09-11 10:51:38 +08005683 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5684 if (!ctl) {
5685 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5686 __func__, mixer_ctl_name);
5687 return -EINVAL;
5688 }
5689
5690 set_values[0] = 0; //0: Rx Session 1:Tx Session
5691 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305692 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
5693 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005694
5695 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
5696 return 0;
5697}
5698
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305699static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
5700 float right)
5701{
5702 struct stream_out *out = (struct stream_out *)stream;
5703 /* Volume control for pcm playback */
5704 if (left != right) {
5705 return -EINVAL;
5706 } else {
5707 char mixer_ctl_name[128];
5708 struct audio_device *adev = out->dev;
5709 struct mixer_ctl *ctl;
5710 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5711 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
5712 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5713 if (!ctl) {
5714 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5715 return -EINVAL;
5716 }
5717
5718 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
5719 int ret = mixer_ctl_set_value(ctl, 0, volume);
5720 if (ret < 0) {
5721 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
5722 return -EINVAL;
5723 }
5724
5725 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
5726
5727 return 0;
5728 }
5729}
5730
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005731static int out_set_volume(struct audio_stream_out *stream, float left,
5732 float right)
5733{
Eric Laurenta9024de2013-04-04 09:19:12 -07005734 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005735 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305736 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005737
Arun Mirpuri5d170872019-03-26 13:21:31 -07005738 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07005739 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
5740 /* only take left channel into account: the API is for stereo anyway */
5741 out->muted = (left == 0.0f);
5742 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005743 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305744 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005745 /*
5746 * Set mute or umute on HDMI passthrough stream.
5747 * Only take left channel into account.
5748 * Mute is 0 and unmute 1
5749 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305750 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305751 } else if (out->format == AUDIO_FORMAT_DSD){
5752 char mixer_ctl_name[128] = "DSD Volume";
5753 struct audio_device *adev = out->dev;
5754 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5755
5756 if (!ctl) {
5757 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5758 __func__, mixer_ctl_name);
5759 return -EINVAL;
5760 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05305761 volume[0] = (long)(AmpToDb(left));
5762 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305763 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5764 return 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005765 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS) &&
Derek Chendf05eea2019-08-01 13:57:49 -07005766 (out->car_audio_stream == CAR_AUDIO_STREAM_MEDIA)) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005767 ALOGD("%s: Overriding offload set volume for media bus stream", __func__);
5768 struct listnode *node = NULL;
5769 list_for_each(node, &adev->active_outputs_list) {
5770 streams_output_ctxt_t *out_ctxt = node_to_item(node,
5771 streams_output_ctxt_t,
5772 list);
5773 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
5774 out->volume_l = out_ctxt->output->volume_l;
5775 out->volume_r = out_ctxt->output->volume_r;
5776 }
5777 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08005778 pthread_mutex_lock(&out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +08005779 if (!out->a2dp_muted) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005780 ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5781 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08005782 pthread_mutex_unlock(&out->latch_lock);
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005783 return ret;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005784 } else {
Weiyin Jiang280ea742020-09-08 20:28:22 +08005785 pthread_mutex_lock(&out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +08005786 ALOGV("%s: compress mute %d", __func__, out->a2dp_muted);
5787 if (!out->a2dp_muted)
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305788 ret = out_set_compr_volume(stream, left, right);
5789 out->volume_l = left;
5790 out->volume_r = right;
Weiyin Jiang280ea742020-09-08 20:28:22 +08005791 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305792 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005793 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005794 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005795 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
5796 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Songbaddf9f2020-11-20 13:57:39 +08005797 pthread_mutex_lock(&out->latch_lock);
Aalique Grahame22e49102018-12-18 14:23:57 -08005798 if (!out->standby) {
5799 audio_extn_utils_send_app_type_gain(out->dev,
5800 out->app_type_cfg.app_type,
5801 &out->app_type_cfg.gain[0]);
Zhou Songbaddf9f2020-11-20 13:57:39 +08005802 if (!out->a2dp_muted)
5803 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08005804 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08005805 out->volume_l = left;
5806 out->volume_r = right;
Zhou Songbaddf9f2020-11-20 13:57:39 +08005807 pthread_mutex_unlock(&out->latch_lock);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005808 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005809 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5810 ALOGV("%s: MMAP set volume called", __func__);
5811 if (!out->standby)
5812 ret = out_set_mmap_volume(stream, left, right);
5813 out->volume_l = left;
5814 out->volume_r = right;
5815 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305816 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05305817 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5818 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Zhou Songbaddf9f2020-11-20 13:57:39 +08005819 pthread_mutex_lock(&out->latch_lock);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305820 /* Volume control for pcm playback */
Zhou Songbaddf9f2020-11-20 13:57:39 +08005821 if (!out->standby && !out->a2dp_muted)
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305822 ret = out_set_pcm_volume(stream, left, right);
5823 else
5824 out->apply_volume = true;
5825
5826 out->volume_l = left;
5827 out->volume_r = right;
Zhou Songbaddf9f2020-11-20 13:57:39 +08005828 pthread_mutex_unlock(&out->latch_lock);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305829 return ret;
Derek Chenf13dd492018-11-13 14:53:51 -08005830 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
5831 ALOGV("%s: bus device set volume called", __func__);
Zhou Songbaddf9f2020-11-20 13:57:39 +08005832 pthread_mutex_lock(&out->latch_lock);
5833 if (!out->standby && !out->a2dp_muted)
Derek Chenf13dd492018-11-13 14:53:51 -08005834 ret = out_set_pcm_volume(stream, left, right);
5835 out->volume_l = left;
5836 out->volume_r = right;
Zhou Songbaddf9f2020-11-20 13:57:39 +08005837 pthread_mutex_unlock(&out->latch_lock);
Derek Chenf13dd492018-11-13 14:53:51 -08005838 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07005839 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005840
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005841 return -ENOSYS;
5842}
5843
Zhou Songc9672822017-08-16 16:01:39 +08005844static void update_frames_written(struct stream_out *out, size_t bytes)
5845{
5846 size_t bpf = 0;
5847
5848 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
5849 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
5850 bpf = 1;
5851 else if (!is_offload_usecase(out->usecase))
5852 bpf = audio_bytes_per_sample(out->format) *
5853 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08005854
5855 pthread_mutex_lock(&out->position_query_lock);
5856 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08005857 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08005858 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
5859 }
5860 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08005861}
5862
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005863int split_and_write_audio_haptic_data(struct stream_out *out,
5864 const void *buffer, size_t bytes_to_write)
5865{
5866 struct audio_device *adev = out->dev;
5867
5868 int ret = 0;
5869 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5870 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
5871 size_t frame_size = channel_count * bytes_per_sample;
5872 size_t frame_count = bytes_to_write / frame_size;
5873
5874 bool force_haptic_path =
5875 property_get_bool("vendor.audio.test_haptic", false);
5876
5877 // extract Haptics data from Audio buffer
5878 bool alloc_haptic_buffer = false;
5879 int haptic_channel_count = adev->haptics_config.channels;
5880 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
5881 size_t audio_frame_size = frame_size - haptic_frame_size;
5882 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
5883
5884 if (adev->haptic_buffer == NULL) {
5885 alloc_haptic_buffer = true;
5886 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
5887 free(adev->haptic_buffer);
5888 adev->haptic_buffer_size = 0;
5889 alloc_haptic_buffer = true;
5890 }
5891
5892 if (alloc_haptic_buffer) {
5893 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08005894 if(adev->haptic_buffer == NULL) {
5895 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
5896 return -ENOMEM;
5897 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005898 adev->haptic_buffer_size = total_haptic_buffer_size;
5899 }
5900
5901 size_t src_index = 0, aud_index = 0, hap_index = 0;
5902 uint8_t *audio_buffer = (uint8_t *)buffer;
5903 uint8_t *haptic_buffer = adev->haptic_buffer;
5904
5905 // This is required for testing only. This works for stereo data only.
5906 // One channel is fed to audio stream and other to haptic stream for testing.
5907 if (force_haptic_path)
5908 audio_frame_size = haptic_frame_size = bytes_per_sample;
5909
5910 for (size_t i = 0; i < frame_count; i++) {
5911 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
5912 audio_frame_size);
5913 aud_index += audio_frame_size;
5914 src_index += audio_frame_size;
5915
5916 if (adev->haptic_pcm)
5917 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
5918 haptic_frame_size);
5919 hap_index += haptic_frame_size;
5920 src_index += haptic_frame_size;
5921
5922 // This is required for testing only.
5923 // Discard haptic channel data.
5924 if (force_haptic_path)
5925 src_index += haptic_frame_size;
5926 }
5927
5928 // write to audio pipeline
5929 ret = pcm_write(out->pcm, (void *)audio_buffer,
5930 frame_count * audio_frame_size);
5931
5932 // write to haptics pipeline
5933 if (adev->haptic_pcm)
5934 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
5935 frame_count * haptic_frame_size);
5936
5937 return ret;
5938}
5939
Aalique Grahame22e49102018-12-18 14:23:57 -08005940#ifdef NO_AUDIO_OUT
5941static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
5942 const void *buffer __unused, size_t bytes)
5943{
5944 struct stream_out *out = (struct stream_out *)stream;
5945
5946 /* No Output device supported other than BT for playback.
5947 * Sleep for the amount of buffer duration
5948 */
5949 lock_output_stream(out);
5950 usleep(bytes * 1000000 / audio_stream_out_frame_size(
5951 (const struct audio_stream_out *)&out->stream) /
5952 out_get_sample_rate(&out->stream.common));
5953 pthread_mutex_unlock(&out->lock);
5954 return bytes;
5955}
5956#endif
5957
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005958static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
5959 size_t bytes)
5960{
5961 struct stream_out *out = (struct stream_out *)stream;
5962 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07005963 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305964 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005965 const size_t frame_size = audio_stream_out_frame_size(stream);
5966 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305967 struct audio_usecase *usecase = NULL;
Meng Wang4c32fb42020-01-16 17:57:11 +08005968 uint32_t compr_passthr = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005969
Haynes Mathew George380745d2017-10-04 15:27:45 -07005970 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005971 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305972
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305973 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08005974
Dhananjay Kumarac341582017-02-23 23:42:25 +05305975 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305976 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05305977 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
5978 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005979 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305980 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05305981 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05305982 ALOGD(" %s: sound card is not active/SSR state", __func__);
5983 ret= -EIO;
5984 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305985 }
5986 }
5987
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305988 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305989 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305990 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305991 goto exit;
5992 }
5993
Haynes Mathew George16081042017-05-31 17:16:49 -07005994 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5995 ret = -EINVAL;
5996 goto exit;
5997 }
5998
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005999 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306000 !out->is_iec61937_info_available) {
6001
6002 if (!audio_extn_passthru_is_passthrough_stream(out)) {
6003 out->is_iec61937_info_available = true;
6004 } else if (audio_extn_passthru_is_enabled()) {
6005 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05306006 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05306007
6008 if((out->format == AUDIO_FORMAT_DTS) ||
6009 (out->format == AUDIO_FORMAT_DTS_HD)) {
6010 ret = audio_extn_passthru_update_dts_stream_configuration(out,
6011 buffer, bytes);
6012 if (ret) {
6013 if (ret != -ENOSYS) {
6014 out->is_iec61937_info_available = false;
6015 ALOGD("iec61937 transmission info not yet updated retry");
6016 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306017 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05306018 /* if stream has started and after that there is
6019 * stream config change (iec transmission config)
6020 * then trigger select_device to update backend configuration.
6021 */
6022 out->stream_config_changed = true;
6023 pthread_mutex_lock(&adev->lock);
6024 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306025 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08006026 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306027 ret = -EINVAL;
6028 goto exit;
6029 }
Manish Dewangan671a4202017-08-18 17:30:46 +05306030 pthread_mutex_unlock(&adev->lock);
6031 out->stream_config_changed = false;
6032 out->is_iec61937_info_available = true;
6033 }
6034 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05306035
Meng Wang4c32fb42020-01-16 17:57:11 +08006036#ifdef AUDIO_GKI_ENABLED
6037 /* out->compr_config.codec->reserved[0] is for compr_passthr */
6038 compr_passthr = out->compr_config.codec->reserved[0];
6039#else
6040 compr_passthr = out->compr_config.codec->compr_passthr;
6041#endif
6042
Garmond Leung317cbf12017-09-13 16:20:50 -07006043 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Meng Wang4c32fb42020-01-16 17:57:11 +08006044 (compr_passthr == PASSTHROUGH) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05306045 (out->is_iec61937_info_available == true)) {
6046 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
6047 ret = -EINVAL;
6048 goto exit;
6049 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05306050 }
6051 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306052
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006053 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02006054 (audio_extn_a2dp_source_is_suspended())) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006055 if (!(compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER) ||
6056 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Zhou Songd01e7a22020-09-23 22:49:01 +08006057 if (!is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306058 ret = -EIO;
6059 goto exit;
6060 }
6061 }
6062 }
6063
Weiyin Jiangabedea32020-12-09 12:49:19 +08006064 if (is_usb_out_device_type(&out->device_list) &&
6065 !audio_extn_usb_connected(NULL)) {
6066 ret = -EIO;
6067 goto exit;
6068 }
6069
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006070 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07006071 out->standby = false;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006072 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
6073
Eric Laurent150dbfe2013-02-27 14:31:02 -08006074 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006075 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
6076 ret = voice_extn_compress_voip_start_output_stream(out);
6077 else
6078 ret = start_output_stream(out);
Daniel Hillenbrand17873952013-05-23 10:10:00 +05306079
6080 if (ret == 0)
6081 amplifier_output_stream_start(stream,
6082 is_offload_usecase(out->usecase));
6083
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006084 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006085 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07006086 out->standby = true;
Weiyin Jiangac2bae82020-07-29 17:23:53 +08006087 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006088 goto exit;
6089 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306090 out->started = 1;
Andy Hunga1f48fa2019-07-01 18:14:53 -07006091 out->last_fifo_valid = false; // we're coming out of standby, last_fifo isn't valid.
Weiyin Jiangac2bae82020-07-29 17:23:53 +08006092
6093 if ((last_known_cal_step != -1) && (adev->platform != NULL)) {
vivek mehtab72d08d2016-04-29 03:16:47 -07006094 ALOGD("%s: retry previous failed cal level set", __func__);
Weiyin Jiangac2bae82020-07-29 17:23:53 +08006095 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05306096 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07006097 }
Weiyin Jiangac2bae82020-07-29 17:23:53 +08006098 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306099
6100 if ((out->is_iec61937_info_available == true) &&
6101 (audio_extn_passthru_is_passthrough_stream(out))&&
6102 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
6103 ret = -EINVAL;
6104 goto exit;
6105 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05306106 if (out->set_dual_mono)
6107 audio_extn_send_dual_mono_mixing_coefficients(out);
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006108
Dechen Chai22768452021-07-30 09:29:16 +05306109#ifndef LINUX_ENABLED
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006110 // log startup time in ms.
6111 simple_stats_log(
6112 &out->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Dechen Chai22768452021-07-30 09:29:16 +05306113#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006114 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006115
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006116 if (adev->is_channel_status_set == false &&
6117 compare_device_type(&out->device_list,
6118 AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Alexy Josephb1379942016-01-29 15:49:38 -08006119 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05306120 adev->is_channel_status_set = true;
6121 }
6122
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05306123 if ((adev->use_old_pspd_mix_ctrl == true) &&
6124 (out->pspd_coeff_sent == false)) {
6125 /*
6126 * Need to resend pspd coefficients after stream started for
6127 * older kernel version as it does not save the coefficients
6128 * and also stream has to be started for coeff to apply.
6129 */
6130 usecase = get_usecase_from_list(adev, out->usecase);
6131 if (usecase != NULL) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05306132 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05306133 out->pspd_coeff_sent = true;
6134 }
6135 }
6136
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006137 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08006138 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006139 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006140 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006141 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
6142 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05306143 if (out->send_next_track_params && out->is_compr_metadata_avail) {
6144 ALOGD("copl(%p):send next track params in gapless", out);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08006145 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05306146 out->send_next_track_params = false;
6147 out->is_compr_metadata_avail = false;
6148 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006149 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05306150 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306151 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006152
Ashish Jain83a6cc22016-06-28 14:34:17 +05306153 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05306154 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05306155 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05306156 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006157 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05306158 return -EINVAL;
6159 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05306160 audio_format_t dst_format = out->hal_op_format;
6161 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306162
Dieter Luecking5d57def2018-09-07 14:23:37 +02006163 /* prevent division-by-zero */
6164 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
6165 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
6166 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
6167 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05306168 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006169 ATRACE_END();
6170 return -EINVAL;
6171 }
6172
Ashish Jainf1eaa582016-05-23 20:54:24 +05306173 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
6174 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
6175
Ashish Jain83a6cc22016-06-28 14:34:17 +05306176 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05306177 dst_format,
6178 buffer,
6179 src_format,
6180 frames);
6181
Ashish Jain83a6cc22016-06-28 14:34:17 +05306182 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05306183 bytes_to_write);
6184
6185 /*Convert written bytes in audio flinger format*/
6186 if (ret > 0)
6187 ret = ((ret * format_to_bitwidth_table[out->format]) /
6188 format_to_bitwidth_table[dst_format]);
6189 }
6190 } else
6191 ret = compress_write(out->compr, buffer, bytes);
6192
Zhou Songc9672822017-08-16 16:01:39 +08006193 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
6194 update_frames_written(out, bytes);
6195
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306196 if (ret < 0)
6197 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08006198 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05306199 /*msg to cb thread only if non blocking write is enabled*/
6200 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05306201 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006202 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05306203 } else if (-ENETRESET == ret) {
6204 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306205 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05306206 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05306207 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006208 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05306209 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006210 }
Ashish Jain5106d362016-05-11 19:23:33 +05306211
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05306212 /* Call compr start only when non-zero bytes of data is there to be rendered */
6213 if (!out->playback_started && ret > 0) {
6214 int status = compress_start(out->compr);
6215 if (status < 0) {
6216 ret = status;
6217 ALOGE("%s: compr start failed with err %d", __func__, errno);
6218 goto exit;
6219 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07006220 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006221 out->playback_started = 1;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006222 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006223 out->offload_state = OFFLOAD_STATE_PLAYING;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006224 pthread_mutex_unlock(&out->latch_lock);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006225
6226 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6227 popcount(out->channel_mask),
6228 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006229 }
6230 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006231 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006232 return ret;
6233 } else {
6234 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006235 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006236 if (out->muted)
6237 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006238 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
6239 __func__, frames, frame_size, bytes_to_write);
6240
Aalique Grahame22e49102018-12-18 14:23:57 -08006241 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07006242 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
6243 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
6244 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006245 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
6246 int16_t *src = (int16_t *)buffer;
6247 int16_t *dst = (int16_t *)buffer;
6248
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006249 LOG_ALWAYS_FATAL_IF(channel_count > 2 ||
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006250 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08006251 "out_write called for %s use case with wrong properties",
6252 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006253
6254 /*
6255 * FIXME: this can be removed once audio flinger mixer supports
6256 * mono output
6257 */
6258
6259 /*
6260 * Code below goes over each frame in the buffer and adds both
6261 * L and R samples and then divides by 2 to convert to mono
6262 */
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006263 if (channel_count == 2) {
6264 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
6265 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
6266 }
6267 bytes_to_write /= 2;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006268 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006269 }
Andy Hunga1f48fa2019-07-01 18:14:53 -07006270
6271 // Note: since out_get_presentation_position() is called alternating with out_write()
6272 // by AudioFlinger, we can check underruns using the prior timestamp read.
6273 // (Alternately we could check if the buffer is empty using pcm_get_htimestamp().
6274 if (out->last_fifo_valid) {
6275 // compute drain to see if there is an underrun.
6276 const int64_t current_ns = systemTime(SYSTEM_TIME_MONOTONIC); // sys call
Dhananjay Kumara4429632020-07-11 02:53:37 +05306277 int64_t time_diff_ns = current_ns - out->last_fifo_time_ns;
6278 int64_t frames_by_time =
6279 ((time_diff_ns > 0) && (time_diff_ns < (INT64_MAX / out->config.rate))) ?
6280 (time_diff_ns * out->config.rate / NANOS_PER_SECOND) : 0;
Andy Hunga1f48fa2019-07-01 18:14:53 -07006281 const int64_t underrun = frames_by_time - out->last_fifo_frames_remaining;
6282
6283 if (underrun > 0) {
Dechen Chai22768452021-07-30 09:29:16 +05306284#ifndef LINUX_ENABLED
Andy Hunga1f48fa2019-07-01 18:14:53 -07006285 simple_stats_log(&out->fifo_underruns, underrun);
Dechen Chai22768452021-07-30 09:29:16 +05306286#endif
Andy Hunga1f48fa2019-07-01 18:14:53 -07006287
6288 ALOGW("%s: underrun(%lld) "
6289 "frames_by_time(%lld) > out->last_fifo_frames_remaining(%lld)",
6290 __func__,
6291 (long long)out->fifo_underruns.n,
6292 (long long)frames_by_time,
6293 (long long)out->last_fifo_frames_remaining);
6294 }
6295 out->last_fifo_valid = false; // we're writing below, mark fifo info as stale.
6296 }
6297
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306298 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006299
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006300 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006301
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006302 if (out->config.rate)
6303 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
6304 out->config.rate;
6305
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006306 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006307 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
6308
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006309 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006310 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006311 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306312 out->convert_buffer != NULL) {
6313
6314 memcpy_by_audio_format(out->convert_buffer,
6315 out->hal_op_format,
6316 buffer,
6317 out->hal_ip_format,
6318 out->config.period_size * out->config.channels);
6319
6320 ret = pcm_write(out->pcm, out->convert_buffer,
6321 (out->config.period_size *
6322 out->config.channels *
6323 format_to_bitwidth_table[out->hal_op_format]));
6324 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05306325 /*
6326 * To avoid underrun in DSP when the application is not pumping
6327 * data at required rate, check for the no. of bytes and ignore
6328 * pcm_write if it is less than actual buffer size.
6329 * It is a work around to a change in compress VOIP driver.
6330 */
6331 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
6332 bytes < (out->config.period_size * out->config.channels *
6333 audio_bytes_per_sample(out->format))) {
6334 size_t voip_buf_size =
6335 out->config.period_size * out->config.channels *
6336 audio_bytes_per_sample(out->format);
6337 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
6338 __func__, bytes, voip_buf_size);
6339 usleep(((uint64_t)voip_buf_size - bytes) *
6340 1000000 / audio_stream_out_frame_size(stream) /
6341 out_get_sample_rate(&out->stream.common));
6342 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006343 } else {
6344 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
6345 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
6346 else
6347 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
6348 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306349 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006350
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006351 release_out_focus(out);
6352
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306353 if (ret < 0)
6354 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08006355 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05306356 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006357 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006358 }
6359
6360exit:
Zhou Songc9672822017-08-16 16:01:39 +08006361 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306362 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306363 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306364 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006365 pthread_mutex_unlock(&out->lock);
6366
6367 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006368 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08006369 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306370 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306371 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306372 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306373 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306374 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306375 out->standby = true;
6376 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306377 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006378 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
6379 /* prevent division-by-zero */
6380 uint32_t stream_size = audio_stream_out_frame_size(stream);
6381 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006382
Dieter Luecking5d57def2018-09-07 14:23:37 +02006383 if ((stream_size == 0) || (srate == 0)) {
6384 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
6385 ATRACE_END();
6386 return -EINVAL;
6387 }
6388 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
6389 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006390 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05306391 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006392 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006393 return ret;
6394 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006395 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07006396 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006397 return bytes;
6398}
6399
6400static int out_get_render_position(const struct audio_stream_out *stream,
6401 uint32_t *dsp_frames)
6402{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006403 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08006404
6405 if (dsp_frames == NULL)
6406 return -EINVAL;
6407
6408 *dsp_frames = 0;
6409 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08006410 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05306411
6412 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
6413 * this operation and adev_close_output_stream(where out gets reset).
6414 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05306415 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006416 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05306417 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006418 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05306419 return 0;
6420 }
6421
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006422 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05306423 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306424 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006425 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306426 if (ret < 0)
6427 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006428 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05306429 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006430 }
Naresh Tanniru80659832014-06-04 18:17:56 +05306431 if (-ENETRESET == ret) {
6432 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306433 out->card_status = CARD_STATUS_OFFLINE;
6434 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306435 } else if(ret < 0) {
6436 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306437 ret = -EINVAL;
6438 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05306439 /*
6440 * Handle corner case where compress session is closed during SSR
6441 * and timestamp is queried
6442 */
6443 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306444 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306445 } else if (out->prev_card_status_offline) {
6446 ALOGE("ERROR: previously sound card was offline,return error");
6447 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306448 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306449 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006450 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05306451 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306452 pthread_mutex_unlock(&out->lock);
6453 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08006454 } else if (audio_is_linear_pcm(out->format)) {
6455 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006456 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08006457 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006458 } else
6459 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006460}
6461
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006462static int out_add_audio_effect(const struct audio_stream *stream __unused,
6463 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006464{
6465 return 0;
6466}
6467
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006468static int out_remove_audio_effect(const struct audio_stream *stream __unused,
6469 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006470{
6471 return 0;
6472}
6473
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006474static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
6475 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006476{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05306477 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006478}
6479
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006480static int out_get_presentation_position(const struct audio_stream_out *stream,
6481 uint64_t *frames, struct timespec *timestamp)
6482{
6483 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05306484 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07006485 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006486
Ashish Jain5106d362016-05-11 19:23:33 +05306487 /* below piece of code is not guarded against any lock because audioFliner serializes
6488 * this operation and adev_close_output_stream( where out gets reset).
6489 */
6490 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05306491 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006492 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05306493 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
6494 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
6495 return 0;
6496 }
6497
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006498 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006499
Ashish Jain5106d362016-05-11 19:23:33 +05306500 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
6501 ret = compress_get_tstamp(out->compr, &dsp_frames,
6502 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08006503 // Adjustment accounts for A2dp encoder latency with offload usecases
6504 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006505 if (is_a2dp_out_device_type(&out->device_list)) {
yidongh0515e042017-07-06 15:00:34 +08006506 unsigned long offset =
6507 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
6508 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
6509 }
Ashish Jain5106d362016-05-11 19:23:33 +05306510 ALOGVV("%s rendered frames %ld sample_rate %d",
6511 __func__, dsp_frames, out->sample_rate);
6512 *frames = dsp_frames;
6513 if (ret < 0)
6514 ret = -errno;
6515 if (-ENETRESET == ret) {
6516 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306517 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05306518 ret = -EINVAL;
6519 } else
6520 ret = 0;
6521 /* this is the best we can do */
6522 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07006523 } else {
6524 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08006525 unsigned int avail;
6526 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
George Gao62ebc722019-07-29 16:29:44 -07006527 uint64_t signed_frames = 0;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006528 uint64_t frames_temp = 0;
George Gao62ebc722019-07-29 16:29:44 -07006529
Andy Hunga1f48fa2019-07-01 18:14:53 -07006530 if (out->kernel_buffer_size > avail) {
6531 frames_temp = out->last_fifo_frames_remaining = out->kernel_buffer_size - avail;
6532 } else {
6533 ALOGW("%s: avail:%u > kernel_buffer_size:%zu clamping!",
6534 __func__, avail, out->kernel_buffer_size);
6535 avail = out->kernel_buffer_size;
6536 frames_temp = out->last_fifo_frames_remaining = 0;
6537 }
6538 out->last_fifo_valid = true;
6539 out->last_fifo_time_ns = audio_utils_ns_from_timespec(timestamp);
6540
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006541 if (out->written >= frames_temp)
6542 signed_frames = out->written - frames_temp;
George Gao62ebc722019-07-29 16:29:44 -07006543
Andy Hunga1f48fa2019-07-01 18:14:53 -07006544 ALOGVV("%s: frames:%lld avail:%u kernel_buffer_size:%zu",
6545 __func__, (long long)signed_frames, avail, out->kernel_buffer_size);
6546
Weiyin Jiangd4633762018-03-16 12:05:03 +08006547 // This adjustment accounts for buffering after app processor.
6548 // It is based on estimated DSP latency per use case, rather than exact.
George Gao9ba8a142020-07-23 14:30:03 -07006549 frames_temp = platform_render_latency(out) *
Robert Lee58215542019-07-15 20:55:12 +08006550 out->sample_rate / 1000000LL;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006551 if (signed_frames >= frames_temp)
6552 signed_frames -= frames_temp;
Aniket Kumar Lataff613152017-07-18 18:19:21 -07006553
Weiyin Jiangd4633762018-03-16 12:05:03 +08006554 // Adjustment accounts for A2dp encoder latency with non offload usecases
6555 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006556 if (is_a2dp_out_device_type(&out->device_list)) {
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006557 frames_temp = audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000;
6558 if (signed_frames >= frames_temp)
6559 signed_frames -= frames_temp;
Weiyin Jiangd4633762018-03-16 12:05:03 +08006560 }
6561
6562 // It would be unusual for this value to be negative, but check just in case ...
George Gao62ebc722019-07-29 16:29:44 -07006563 *frames = signed_frames;
6564 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006565 }
Eric Laurenta7a33042019-07-10 16:20:22 -07006566 } else if (out->card_status == CARD_STATUS_OFFLINE ||
6567 // audioflinger still needs position updates when A2DP is suspended
Jasmine Cha5c2517f2019-09-09 11:07:28 +08006568 (is_a2dp_out_device_type(&out->device_list) && audio_extn_a2dp_source_is_suspended())) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306569 *frames = out->written;
6570 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306571 if (is_offload_usecase(out->usecase))
6572 ret = -EINVAL;
6573 else
6574 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006575 }
6576 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006577 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006578 return ret;
6579}
6580
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006581static int out_set_callback(struct audio_stream_out *stream,
6582 stream_callback_t callback, void *cookie)
6583{
6584 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006585 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006586
6587 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006588 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006589 out->client_callback = callback;
6590 out->client_cookie = cookie;
6591 if (out->adsp_hdlr_stream_handle) {
6592 ret = audio_extn_adsp_hdlr_stream_set_callback(
6593 out->adsp_hdlr_stream_handle,
6594 callback,
6595 cookie);
6596 if (ret)
6597 ALOGW("%s:adsp hdlr callback registration failed %d",
6598 __func__, ret);
6599 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006600 pthread_mutex_unlock(&out->lock);
6601 return 0;
6602}
6603
6604static int out_pause(struct audio_stream_out* stream)
6605{
6606 struct stream_out *out = (struct stream_out *)stream;
6607 int status = -ENOSYS;
6608 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006609 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006610 ALOGD("copl(%p):pause compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306611 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006612 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006613 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006614 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306615 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05306616 status = compress_pause(out->compr);
6617
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006618 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006619
Mingming Yin21854652016-04-13 11:54:02 -07006620 if (audio_extn_passthru_is_active()) {
6621 ALOGV("offload use case, pause passthru");
6622 audio_extn_passthru_on_pause(out);
6623 }
6624
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306625 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006626 audio_extn_dts_notify_playback_state(out->usecase, 0,
6627 out->sample_rate, popcount(out->channel_mask),
6628 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006629 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08006630 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006631 pthread_mutex_unlock(&out->lock);
6632 }
6633 return status;
6634}
6635
6636static int out_resume(struct audio_stream_out* stream)
6637{
6638 struct stream_out *out = (struct stream_out *)stream;
6639 int status = -ENOSYS;
6640 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006641 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006642 ALOGD("copl(%p):resume compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306643 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006644 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006645 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006646 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306647 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306648 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07006649 }
6650 if (!status) {
6651 out->offload_state = OFFLOAD_STATE_PLAYING;
6652 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306653 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006654 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6655 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006656 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08006657 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006658 pthread_mutex_unlock(&out->lock);
6659 }
6660 return status;
6661}
6662
6663static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
6664{
6665 struct stream_out *out = (struct stream_out *)stream;
6666 int status = -ENOSYS;
6667 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006668 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006669 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006670 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
6671 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
6672 else
6673 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
6674 pthread_mutex_unlock(&out->lock);
6675 }
6676 return status;
6677}
6678
6679static int out_flush(struct audio_stream_out* stream)
6680{
6681 struct stream_out *out = (struct stream_out *)stream;
6682 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006683 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006684 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006685 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006686 pthread_mutex_lock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006687 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
Gautam Manam14c198b2020-12-24 14:08:04 +05306688 pthread_mutex_unlock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006689 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006690 } else {
6691 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
Gautam Manam14c198b2020-12-24 14:08:04 +05306692 pthread_mutex_unlock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006693 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08006694 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006695 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006696 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006697 return 0;
6698 }
6699 return -ENOSYS;
6700}
6701
Haynes Mathew George16081042017-05-31 17:16:49 -07006702static int out_stop(const struct audio_stream_out* stream)
6703{
6704 struct stream_out *out = (struct stream_out *)stream;
6705 struct audio_device *adev = out->dev;
6706 int ret = -ENOSYS;
6707
6708 ALOGV("%s", __func__);
6709 pthread_mutex_lock(&adev->lock);
6710 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6711 out->playback_started && out->pcm != NULL) {
6712 pcm_stop(out->pcm);
6713 ret = stop_output_stream(out);
6714 out->playback_started = false;
6715 }
6716 pthread_mutex_unlock(&adev->lock);
6717 return ret;
6718}
6719
6720static int out_start(const struct audio_stream_out* stream)
6721{
6722 struct stream_out *out = (struct stream_out *)stream;
6723 struct audio_device *adev = out->dev;
6724 int ret = -ENOSYS;
6725
6726 ALOGV("%s", __func__);
6727 pthread_mutex_lock(&adev->lock);
6728 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6729 !out->playback_started && out->pcm != NULL) {
6730 ret = start_output_stream(out);
6731 if (ret == 0) {
6732 out->playback_started = true;
6733 }
6734 }
6735 pthread_mutex_unlock(&adev->lock);
6736 return ret;
6737}
6738
6739/*
6740 * Modify config->period_count based on min_size_frames
6741 */
6742static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
6743{
6744 int periodCountRequested = (min_size_frames + config->period_size - 1)
6745 / config->period_size;
6746 int periodCount = MMAP_PERIOD_COUNT_MIN;
6747
6748 ALOGV("%s original config.period_size = %d config.period_count = %d",
6749 __func__, config->period_size, config->period_count);
6750
6751 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
6752 periodCount *= 2;
6753 }
6754 config->period_count = periodCount;
6755
6756 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
6757}
6758
Phil Burkfe17efd2019-03-25 10:23:35 -07006759// Read offset for the positional timestamp from a persistent vendor property.
6760// This is to workaround apparent inaccuracies in the timing information that
6761// is used by the AAudio timing model. The inaccuracies can cause glitches.
6762static int64_t get_mmap_out_time_offset() {
6763 const int32_t kDefaultOffsetMicros = 0;
6764 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006765 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07006766 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
6767 return mmap_time_offset_micros * (int64_t)1000;
6768}
6769
Haynes Mathew George16081042017-05-31 17:16:49 -07006770static int out_create_mmap_buffer(const struct audio_stream_out *stream,
6771 int32_t min_size_frames,
6772 struct audio_mmap_buffer_info *info)
6773{
6774 struct stream_out *out = (struct stream_out *)stream;
6775 struct audio_device *adev = out->dev;
6776 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07006777 unsigned int offset1 = 0;
6778 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006779 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006780 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006781 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07006782
Arun Mirpuri5d170872019-03-26 13:21:31 -07006783 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306784 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07006785 pthread_mutex_lock(&adev->lock);
6786
Sharad Sanglec6f32552018-05-04 16:15:38 +05306787 if (CARD_STATUS_OFFLINE == out->card_status ||
6788 CARD_STATUS_OFFLINE == adev->card_status) {
6789 ALOGW("out->card_status or adev->card_status offline, try again");
6790 ret = -EIO;
6791 goto exit;
6792 }
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306793 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07006794 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
6795 ret = -EINVAL;
6796 goto exit;
6797 }
6798 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
6799 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
6800 ret = -ENOSYS;
6801 goto exit;
6802 }
6803 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
6804 if (out->pcm_device_id < 0) {
6805 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6806 __func__, out->pcm_device_id, out->usecase);
6807 ret = -EINVAL;
6808 goto exit;
6809 }
6810
6811 adjust_mmap_period_count(&out->config, min_size_frames);
6812
Arun Mirpuri5d170872019-03-26 13:21:31 -07006813 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006814 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
6815 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
6816 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306817 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306818 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6819 out->card_status = CARD_STATUS_OFFLINE;
6820 adev->card_status = CARD_STATUS_OFFLINE;
6821 ret = -EIO;
6822 goto exit;
6823 }
6824
Haynes Mathew George16081042017-05-31 17:16:49 -07006825 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
6826 step = "open";
6827 ret = -ENODEV;
6828 goto exit;
6829 }
6830 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
6831 if (ret < 0) {
6832 step = "begin";
6833 goto exit;
6834 }
juyuchen626833d2019-06-04 16:48:02 +08006835
6836 info->flags = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006837 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07006838 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07006839 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006840 ret = platform_get_mmap_data_fd(adev->platform,
6841 out->pcm_device_id, 0 /*playback*/,
6842 &info->shared_memory_fd,
6843 &mmap_size);
6844 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07006845 // Fall back to non exclusive mode
6846 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
6847 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07006848 out->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
6849 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, out->mmap_shared_memory_fd);
6850
Arun Mirpuri5d170872019-03-26 13:21:31 -07006851 if (mmap_size < buffer_size) {
6852 step = "mmap";
6853 goto exit;
6854 }
juyuchen626833d2019-06-04 16:48:02 +08006855 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006856 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006857 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006858 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07006859
6860 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
6861 if (ret < 0) {
6862 step = "commit";
6863 goto exit;
6864 }
6865
Phil Burkfe17efd2019-03-25 10:23:35 -07006866 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
6867
Haynes Mathew George16081042017-05-31 17:16:49 -07006868 out->standby = false;
6869 ret = 0;
6870
Arun Mirpuri5d170872019-03-26 13:21:31 -07006871 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006872 __func__, info->shared_memory_address, info->buffer_size_frames);
6873
6874exit:
6875 if (ret != 0) {
6876 if (out->pcm == NULL) {
6877 ALOGE("%s: %s - %d", __func__, step, ret);
6878 } else {
6879 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
6880 pcm_close(out->pcm);
6881 out->pcm = NULL;
6882 }
6883 }
6884 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306885 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07006886 return ret;
6887}
6888
6889static int out_get_mmap_position(const struct audio_stream_out *stream,
6890 struct audio_mmap_position *position)
6891{
6892 struct stream_out *out = (struct stream_out *)stream;
6893 ALOGVV("%s", __func__);
6894 if (position == NULL) {
6895 return -EINVAL;
6896 }
6897 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08006898 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006899 return -ENOSYS;
6900 }
6901 if (out->pcm == NULL) {
6902 return -ENOSYS;
6903 }
6904
6905 struct timespec ts = { 0, 0 };
6906 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
6907 if (ret < 0) {
6908 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
6909 return ret;
6910 }
Phil Burkfe17efd2019-03-25 10:23:35 -07006911 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
6912 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07006913 return 0;
6914}
6915
6916
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006917/** audio_stream_in implementation **/
6918static uint32_t in_get_sample_rate(const struct audio_stream *stream)
6919{
6920 struct stream_in *in = (struct stream_in *)stream;
6921
6922 return in->config.rate;
6923}
6924
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006925static int in_set_sample_rate(struct audio_stream *stream __unused,
6926 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006927{
6928 return -ENOSYS;
6929}
6930
6931static size_t in_get_buffer_size(const struct audio_stream *stream)
6932{
6933 struct stream_in *in = (struct stream_in *)stream;
6934
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006935 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
6936 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07006937 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
6938 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306939 else if(audio_extn_cin_attached_usecase(in))
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306940 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006941
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006942 return in->config.period_size * in->af_period_multiplier *
6943 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006944}
6945
6946static uint32_t in_get_channels(const struct audio_stream *stream)
6947{
6948 struct stream_in *in = (struct stream_in *)stream;
6949
6950 return in->channel_mask;
6951}
6952
6953static audio_format_t in_get_format(const struct audio_stream *stream)
6954{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006955 struct stream_in *in = (struct stream_in *)stream;
6956
6957 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006958}
6959
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006960static int in_set_format(struct audio_stream *stream __unused,
6961 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006962{
6963 return -ENOSYS;
6964}
6965
6966static int in_standby(struct audio_stream *stream)
6967{
6968 struct stream_in *in = (struct stream_in *)stream;
6969 struct audio_device *adev = in->dev;
6970 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306971 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
6972 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006973 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306974
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006975 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006976 if (!in->standby && in->is_st_session) {
6977 ALOGD("%s: sound trigger pcm stop lab", __func__);
6978 audio_extn_sound_trigger_stop_lab(in);
George Gao3018ede2019-10-23 13:23:00 -07006979 if (adev->num_va_sessions > 0)
6980 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006981 in->standby = 1;
6982 }
6983
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006984 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006985 if (adev->adm_deregister_stream)
6986 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
6987
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08006988 pthread_mutex_lock(&adev->lock);
Daniel Hillenbrand17873952013-05-23 10:10:00 +05306989 amplifier_input_stream_standby((struct audio_stream_in *) stream);
6990
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006991 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08006992 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08006993 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08006994 voice_extn_compress_voip_close_input_stream(stream);
6995 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07006996 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6997 do_stop = in->capture_started;
6998 in->capture_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07006999 if (in->mmap_shared_memory_fd >= 0) {
7000 ALOGV("%s: closing mmap_shared_memory_fd = %d",
7001 __func__, in->mmap_shared_memory_fd);
7002 close(in->mmap_shared_memory_fd);
7003 in->mmap_shared_memory_fd = -1;
7004 }
Zhou Songa8895042016-07-05 17:54:22 +08007005 } else {
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307006 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05307007 audio_extn_cin_close_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08007008 }
7009
Arun Mirpuri5d170872019-03-26 13:21:31 -07007010 if (in->pcm) {
7011 ATRACE_BEGIN("pcm_in_close");
7012 pcm_close(in->pcm);
7013 ATRACE_END();
7014 in->pcm = NULL;
7015 }
7016
Carter Hsu2e429db2019-05-14 18:50:52 +08007017 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08007018 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08007019
George Gao3018ede2019-10-23 13:23:00 -07007020 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
7021 if (adev->num_va_sessions > 0)
7022 adev->num_va_sessions--;
7023 }
Quinn Malef6050362019-01-30 15:55:40 -08007024
Eric Laurent150dbfe2013-02-27 14:31:02 -08007025 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007026 }
7027 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07007028 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007029 return status;
7030}
7031
Aalique Grahame22e49102018-12-18 14:23:57 -08007032static int in_dump(const struct audio_stream *stream,
7033 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007034{
Aalique Grahame22e49102018-12-18 14:23:57 -08007035 struct stream_in *in = (struct stream_in *)stream;
7036
7037 // We try to get the lock for consistency,
7038 // but it isn't necessary for these variables.
7039 // If we're not in standby, we may be blocked on a read.
7040 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
7041 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
7042 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
7043 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
Dechen Chai22768452021-07-30 09:29:16 +05307044#ifndef LINUX_ENABLED
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007045 char buffer[256]; // for statistics formatting
7046 if (in->start_latency_ms.n > 0) {
7047 simple_stats_to_string(&in->start_latency_ms, buffer, sizeof(buffer));
7048 dprintf(fd, " Start latency ms: %s\n", buffer);
7049 }
Dechen Chai22768452021-07-30 09:29:16 +05307050#endif
Aalique Grahame22e49102018-12-18 14:23:57 -08007051 if (locked) {
7052 pthread_mutex_unlock(&in->lock);
7053 }
Dechen Chai22768452021-07-30 09:29:16 +05307054#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -08007055 // dump error info
7056 (void)error_log_dump(
7057 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Dechen Chai22768452021-07-30 09:29:16 +05307058#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007059 return 0;
7060}
7061
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307062static void in_snd_mon_cb(void * stream, struct str_parms * parms)
7063{
7064 if (!stream || !parms)
7065 return;
7066
7067 struct stream_in *in = (struct stream_in *)stream;
7068 struct audio_device *adev = in->dev;
7069
7070 card_status_t status;
7071 int card;
7072 if (parse_snd_card_status(parms, &card, &status) < 0)
7073 return;
7074
7075 pthread_mutex_lock(&adev->lock);
7076 bool valid_cb = (card == adev->snd_card);
7077 pthread_mutex_unlock(&adev->lock);
7078
7079 if (!valid_cb)
7080 return;
7081
7082 lock_input_stream(in);
7083 if (in->card_status != status)
7084 in->card_status = status;
7085 pthread_mutex_unlock(&in->lock);
7086
7087 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
7088 use_case_table[in->usecase],
7089 status == CARD_STATUS_OFFLINE ? "offline" : "online");
7090
7091 // a better solution would be to report error back to AF and let
7092 // it put the stream to standby
7093 if (status == CARD_STATUS_OFFLINE)
7094 in_standby(&in->stream.common);
7095
7096 return;
7097}
7098
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007099int route_input_stream(struct stream_in *in,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007100 struct listnode *devices,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007101 audio_source_t source)
7102{
7103 struct audio_device *adev = in->dev;
7104 int ret = 0;
7105
7106 lock_input_stream(in);
7107 pthread_mutex_lock(&adev->lock);
7108
7109 /* no audio source uses val == 0 */
7110 if ((in->source != source) && (source != AUDIO_SOURCE_DEFAULT)) {
7111 in->source = source;
7112 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
7113 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
7114 (voice_extn_compress_voip_is_format_supported(in->format)) &&
7115 (in->config.rate == 8000 || in->config.rate == 16000 ||
7116 in->config.rate == 32000 || in->config.rate == 48000 ) &&
7117 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
7118 ret = voice_extn_compress_voip_open_input_stream(in);
7119 if (ret != 0) {
7120 ALOGE("%s: Compress voip input cannot be opened, error:%d",
7121 __func__, ret);
7122 }
7123 }
7124 }
7125
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007126 if (!compare_devices(&in->device_list, devices) && !list_empty(devices) &&
7127 is_audio_in_device_type(devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007128 // Workaround: If routing to an non existing usb device, fail gracefully
7129 // The routing request will otherwise block during 10 second
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007130 struct str_parms *usb_addr =
7131 str_parms_create_str(get_usb_device_address(devices));
7132 if (is_usb_in_device_type(devices) && usb_addr &&
Weiyin Jiangabedea32020-12-09 12:49:19 +08007133 !audio_extn_usb_connected(NULL)) {
7134 ALOGW("%s: ignoring rerouting to non existing USB", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007135 ret = -ENOSYS;
7136 } else {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007137 /* If recording is in progress, change the tx device to new device */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007138 assign_devices(&in->device_list, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007139 if (!in->standby && !in->is_st_session) {
7140 ALOGV("update input routing change");
7141 // inform adm before actual routing to prevent glitches.
7142 if (adev->adm_on_routing_change) {
7143 adev->adm_on_routing_change(adev->adm_data,
7144 in->capture_handle);
7145 ret = select_devices(adev, in->usecase);
7146 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7147 adev->adm_routing_changed = true;
7148 }
7149 }
7150 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007151 if (usb_addr)
7152 str_parms_destroy(usb_addr);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007153 }
7154 pthread_mutex_unlock(&adev->lock);
7155 pthread_mutex_unlock(&in->lock);
7156
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07007157 ALOGV("%s: exit: status(%d)", __func__, ret);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007158 return ret;
7159}
7160
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007161static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
7162{
7163 struct stream_in *in = (struct stream_in *)stream;
7164 struct audio_device *adev = in->dev;
7165 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007166 char value[32];
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307167 int err = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007168
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307169 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007170 parms = str_parms_create_str(kvpairs);
7171
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307172 if (!parms)
7173 goto error;
Daniel Hillenbrand17873952013-05-23 10:10:00 +05307174
7175 amplifier_in_set_parameters(parms);
7176
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007177 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08007178 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007179
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307180 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
7181 if (err >= 0) {
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307182 strlcpy(in->profile, value, sizeof(in->profile));
7183 ALOGV("updating stream profile with value '%s'", in->profile);
7184 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
7185 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007186 &in->device_list, in->flags, in->format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307187 in->sample_rate, in->bit_width,
7188 in->profile, &in->app_type_cfg);
7189 }
7190
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007191 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08007192 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007193
7194 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307195error:
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307196 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007197}
7198
7199static char* in_get_parameters(const struct audio_stream *stream,
7200 const char *keys)
7201{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007202 struct stream_in *in = (struct stream_in *)stream;
7203 struct str_parms *query = str_parms_create_str(keys);
7204 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007205 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007206
7207 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08007208 if (reply) {
7209 str_parms_destroy(reply);
7210 }
7211 if (query) {
7212 str_parms_destroy(query);
7213 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007214 ALOGE("in_get_parameters: failed to create query or reply");
7215 return NULL;
7216 }
7217
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007218 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007219
7220 voice_extn_in_get_parameters(in, query, reply);
7221
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007222 stream_get_parameter_channels(query, reply,
7223 &in->supported_channel_masks[0]);
7224 stream_get_parameter_formats(query, reply,
7225 &in->supported_formats[0]);
7226 stream_get_parameter_rates(query, reply,
7227 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007228 str = str_parms_to_str(reply);
7229 str_parms_destroy(query);
7230 str_parms_destroy(reply);
7231
7232 ALOGV("%s: exit: returns - %s", __func__, str);
7233 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007234}
7235
Aalique Grahame22e49102018-12-18 14:23:57 -08007236static int in_set_gain(struct audio_stream_in *stream,
7237 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007238{
Aalique Grahame22e49102018-12-18 14:23:57 -08007239 struct stream_in *in = (struct stream_in *)stream;
7240 char mixer_ctl_name[128];
7241 struct mixer_ctl *ctl;
7242 int ctl_value;
7243
7244 ALOGV("%s: gain %f", __func__, gain);
7245
7246 if (stream == NULL)
7247 return -EINVAL;
7248
7249 /* in_set_gain() only used to silence MMAP capture for now */
7250 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
7251 return -ENOSYS;
7252
7253 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
7254
7255 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
7256 if (!ctl) {
7257 ALOGW("%s: Could not get ctl for mixer cmd - %s",
7258 __func__, mixer_ctl_name);
7259 return -ENOSYS;
7260 }
7261
7262 if (gain < RECORD_GAIN_MIN)
7263 gain = RECORD_GAIN_MIN;
7264 else if (gain > RECORD_GAIN_MAX)
7265 gain = RECORD_GAIN_MAX;
7266 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
7267
7268 mixer_ctl_set_value(ctl, 0, ctl_value);
7269
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007270 return 0;
7271}
7272
7273static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
7274 size_t bytes)
7275{
7276 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05307277
7278 if (in == NULL) {
7279 ALOGE("%s: stream_in ptr is NULL", __func__);
7280 return -EINVAL;
7281 }
7282
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007283 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05307284 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307285 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007286
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007287 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05307288
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007289 if (in->is_st_session) {
7290 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
7291 /* Read from sound trigger HAL */
7292 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08007293 if (in->standby) {
George Gao3018ede2019-10-23 13:23:00 -07007294 if (adev->num_va_sessions < UINT_MAX)
7295 adev->num_va_sessions++;
Quinn Malef6050362019-01-30 15:55:40 -08007296 in->standby = 0;
7297 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007298 pthread_mutex_unlock(&in->lock);
7299 return bytes;
7300 }
7301
Haynes Mathew George16081042017-05-31 17:16:49 -07007302 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
7303 ret = -ENOSYS;
7304 goto exit;
7305 }
7306
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007307 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
7308 !in->standby && adev->adm_routing_changed) {
7309 ret = -ENOSYS;
7310 goto exit;
7311 }
7312
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007313 if (in->standby) {
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007314 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
7315
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007316 pthread_mutex_lock(&adev->lock);
7317 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
7318 ret = voice_extn_compress_voip_start_input_stream(in);
7319 else
7320 ret = start_input_stream(in);
George Gao3018ede2019-10-23 13:23:00 -07007321 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
7322 if (adev->num_va_sessions < UINT_MAX)
7323 adev->num_va_sessions++;
7324 }
Daniel Hillenbrand17873952013-05-23 10:10:00 +05307325
7326 if (ret == 0)
7327 amplifier_input_stream_start(stream);
7328
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007329 pthread_mutex_unlock(&adev->lock);
7330 if (ret != 0) {
7331 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007332 }
7333 in->standby = 0;
Dechen Chai22768452021-07-30 09:29:16 +05307334#ifndef LINUX_ENABLED
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007335 // log startup time in ms.
7336 simple_stats_log(
7337 &in->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Dechen Chai22768452021-07-30 09:29:16 +05307338#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007339 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007340
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05307341 /* Avoid read if capture_stopped is set */
7342 if (android_atomic_acquire_load(&(in->capture_stopped)) > 0) {
7343 ALOGD("%s: force stopped catpure session, ignoring read request", __func__);
7344 ret = -EINVAL;
7345 goto exit;
7346 }
7347
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007348 // what's the duration requested by the client?
7349 long ns = 0;
7350
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307351 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007352 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
7353 in->config.rate;
7354
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007355 ret = request_in_focus(in, ns);
7356 if (ret != 0)
7357 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007358 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007359
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307360 if (audio_extn_cin_attached_usecase(in)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307361 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
7362 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307363 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007364 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307365 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07007366 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007367 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007368 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07007369 } else if (audio_extn_ffv_get_stream() == in) {
7370 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307371 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007372 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307373 /* data from DSP comes in 24_8 format, convert it to 8_24 */
7374 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
7375 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
7376 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307377 ret = -EINVAL;
7378 goto exit;
7379 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307380 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307381 ret = -errno;
7382 }
7383 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307384 /* bytes read is always set to bytes for non compress usecases */
7385 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007386 }
7387
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007388 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007389
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007390 /*
Quinn Malef6050362019-01-30 15:55:40 -08007391 * Instead of writing zeroes here, we could trust the hardware to always
7392 * provide zeroes when muted. This is also muted with voice recognition
7393 * usecases so that other clients do not have access to voice recognition
7394 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007395 */
Quinn Malef6050362019-01-30 15:55:40 -08007396 if ((ret == 0 && voice_get_mic_mute(adev) &&
7397 !voice_is_in_call_rec_stream(in) &&
Zhou Song62ea0282020-03-22 19:53:01 +08007398 (in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY &&
7399 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY2)) ||
Quinn Malef6050362019-01-30 15:55:40 -08007400 (adev->num_va_sessions &&
7401 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
7402 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
7403 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007404 memset(buffer, 0, bytes);
7405
7406exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307407 frame_size = audio_stream_in_frame_size(stream);
7408 if (frame_size > 0)
7409 in->frames_read += bytes_read/frame_size;
7410
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007411 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307412 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007413 pthread_mutex_unlock(&in->lock);
7414
7415 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307416 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307417 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307418 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307419 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307420 in->standby = true;
7421 }
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307422 if (!audio_extn_cin_attached_usecase(in)) {
Sharad Sangled17c9122017-03-20 15:58:52 +05307423 bytes_read = bytes;
7424 memset(buffer, 0, bytes);
7425 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007426 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007427 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7428 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007429 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05307430 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05307431 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007432 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307433 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007434}
7435
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007436static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007437{
7438 return 0;
7439}
7440
Aalique Grahame22e49102018-12-18 14:23:57 -08007441static int in_get_capture_position(const struct audio_stream_in *stream,
7442 int64_t *frames, int64_t *time)
7443{
7444 if (stream == NULL || frames == NULL || time == NULL) {
7445 return -EINVAL;
7446 }
7447 struct stream_in *in = (struct stream_in *)stream;
7448 int ret = -ENOSYS;
7449
7450 lock_input_stream(in);
7451 // note: ST sessions do not close the alsa pcm driver synchronously
7452 // on standby. Therefore, we may return an error even though the
7453 // pcm stream is still opened.
7454 if (in->standby) {
7455 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
7456 "%s stream in standby but pcm not NULL for non ST session", __func__);
7457 goto exit;
7458 }
7459 if (in->pcm) {
7460 struct timespec timestamp;
7461 unsigned int avail;
7462 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
7463 *frames = in->frames_read + avail;
Robert Lee58215542019-07-15 20:55:12 +08007464 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec
George Gao9ba8a142020-07-23 14:30:03 -07007465 - platform_capture_latency(in) * 1000LL;
Kakanaboina Ramanjaneyulu8cedb092021-03-15 15:55:29 +05307466 //Adjustment accounts for A2dp decoder latency for recording usecase
7467 // Note: decoder latency is returned in ms, while platform_capture_latency in ns.
7468 if (is_a2dp_in_device_type(&in->device_list))
7469 *time -= audio_extn_a2dp_get_decoder_latency() * 1000000LL;
Aalique Grahame22e49102018-12-18 14:23:57 -08007470 ret = 0;
7471 }
7472 }
7473exit:
7474 pthread_mutex_unlock(&in->lock);
7475 return ret;
7476}
7477
Carter Hsu2e429db2019-05-14 18:50:52 +08007478static int in_update_effect_list(bool add, effect_handle_t effect,
7479 struct listnode *head)
7480{
7481 struct listnode *node;
7482 struct in_effect_list *elist = NULL;
7483 struct in_effect_list *target = NULL;
7484 int ret = 0;
7485
7486 if (!head)
7487 return ret;
7488
7489 list_for_each(node, head) {
7490 elist = node_to_item(node, struct in_effect_list, list);
7491 if (elist->handle == effect) {
7492 target = elist;
7493 break;
7494 }
7495 }
7496
7497 if (add) {
7498 if (target) {
7499 ALOGD("effect %p already exist", effect);
7500 return ret;
7501 }
7502
7503 target = (struct in_effect_list *)
7504 calloc(1, sizeof(struct in_effect_list));
7505
7506 if (!target) {
7507 ALOGE("%s:fail to allocate memory", __func__);
7508 return -ENOMEM;
7509 }
7510
7511 target->handle = effect;
7512 list_add_tail(head, &target->list);
7513 } else {
7514 if (target) {
7515 list_remove(&target->list);
7516 free(target);
7517 }
7518 }
7519
7520 return ret;
7521}
7522
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007523static int add_remove_audio_effect(const struct audio_stream *stream,
7524 effect_handle_t effect,
7525 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007526{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007527 struct stream_in *in = (struct stream_in *)stream;
7528 int status = 0;
7529 effect_descriptor_t desc;
7530
7531 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007532 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
7533
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007534 if (status != 0)
7535 return status;
7536
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007537 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007538 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08007539 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08007540 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
7541 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007542 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08007543
7544 in_update_effect_list(enable, effect, &in->aec_list);
7545 enable = !list_empty(&in->aec_list);
7546 if (enable == in->enable_aec)
7547 goto exit;
7548
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007549 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007550 ALOGD("AEC enable %d", enable);
7551
Aalique Grahame22e49102018-12-18 14:23:57 -08007552 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7553 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
7554 in->dev->enable_voicerx = enable;
7555 struct audio_usecase *usecase;
7556 struct listnode *node;
7557 list_for_each(node, &in->dev->usecase_list) {
7558 usecase = node_to_item(node, struct audio_usecase, list);
7559 if (usecase->type == PCM_PLAYBACK)
7560 select_devices(in->dev, usecase->id);
7561 }
7562 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007563 if (!in->standby) {
7564 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
7565 select_devices(in->dev, in->usecase);
7566 }
7567
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007568 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007569 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
7570
7571 in_update_effect_list(enable, effect, &in->ns_list);
7572 enable = !list_empty(&in->ns_list);
7573 if (enable == in->enable_ns)
7574 goto exit;
7575
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007576 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007577 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007578 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08007579 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7580 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007581 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
7582 select_devices(in->dev, in->usecase);
7583 } else
7584 select_devices(in->dev, in->usecase);
7585 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007586 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007587exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007588 pthread_mutex_unlock(&in->dev->lock);
7589 pthread_mutex_unlock(&in->lock);
7590
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007591 return 0;
7592}
7593
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007594static int in_add_audio_effect(const struct audio_stream *stream,
7595 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007596{
Eric Laurent994a6932013-07-17 11:51:42 -07007597 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007598 return add_remove_audio_effect(stream, effect, true);
7599}
7600
7601static int in_remove_audio_effect(const struct audio_stream *stream,
7602 effect_handle_t effect)
7603{
Eric Laurent994a6932013-07-17 11:51:42 -07007604 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007605 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007606}
7607
Haynes Mathew George16081042017-05-31 17:16:49 -07007608static int in_stop(const struct audio_stream_in* stream)
7609{
7610 struct stream_in *in = (struct stream_in *)stream;
7611 struct audio_device *adev = in->dev;
7612
7613 int ret = -ENOSYS;
7614 ALOGV("%s", __func__);
7615 pthread_mutex_lock(&adev->lock);
7616 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7617 in->capture_started && in->pcm != NULL) {
7618 pcm_stop(in->pcm);
7619 ret = stop_input_stream(in);
7620 in->capture_started = false;
7621 }
7622 pthread_mutex_unlock(&adev->lock);
7623 return ret;
7624}
7625
7626static int in_start(const struct audio_stream_in* stream)
7627{
7628 struct stream_in *in = (struct stream_in *)stream;
7629 struct audio_device *adev = in->dev;
7630 int ret = -ENOSYS;
7631
7632 ALOGV("%s in %p", __func__, in);
7633 pthread_mutex_lock(&adev->lock);
7634 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7635 !in->capture_started && in->pcm != NULL) {
7636 if (!in->capture_started) {
7637 ret = start_input_stream(in);
7638 if (ret == 0) {
7639 in->capture_started = true;
7640 }
7641 }
7642 }
7643 pthread_mutex_unlock(&adev->lock);
7644 return ret;
7645}
7646
Phil Burke0a86d12019-02-16 22:28:11 -08007647// Read offset for the positional timestamp from a persistent vendor property.
7648// This is to workaround apparent inaccuracies in the timing information that
7649// is used by the AAudio timing model. The inaccuracies can cause glitches.
7650static int64_t in_get_mmap_time_offset() {
7651 const int32_t kDefaultOffsetMicros = 0;
7652 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08007653 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08007654 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
7655 return mmap_time_offset_micros * (int64_t)1000;
7656}
7657
Haynes Mathew George16081042017-05-31 17:16:49 -07007658static int in_create_mmap_buffer(const struct audio_stream_in *stream,
7659 int32_t min_size_frames,
7660 struct audio_mmap_buffer_info *info)
7661{
7662 struct stream_in *in = (struct stream_in *)stream;
7663 struct audio_device *adev = in->dev;
7664 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07007665 unsigned int offset1 = 0;
7666 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007667 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07007668 uint32_t mmap_size = 0;
7669 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007670
7671 pthread_mutex_lock(&adev->lock);
7672 ALOGV("%s in %p", __func__, in);
7673
Sharad Sanglec6f32552018-05-04 16:15:38 +05307674 if (CARD_STATUS_OFFLINE == in->card_status||
7675 CARD_STATUS_OFFLINE == adev->card_status) {
7676 ALOGW("in->card_status or adev->card_status offline, try again");
7677 ret = -EIO;
7678 goto exit;
7679 }
7680
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307681 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07007682 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
7683 ret = -EINVAL;
7684 goto exit;
7685 }
7686 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
7687 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
7688 ALOGV("%s in %p", __func__, in);
7689 ret = -ENOSYS;
7690 goto exit;
7691 }
7692 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
7693 if (in->pcm_device_id < 0) {
7694 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
7695 __func__, in->pcm_device_id, in->usecase);
7696 ret = -EINVAL;
7697 goto exit;
7698 }
7699
7700 adjust_mmap_period_count(&in->config, min_size_frames);
7701
7702 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
7703 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
7704 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
7705 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307706 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307707 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7708 in->card_status = CARD_STATUS_OFFLINE;
7709 adev->card_status = CARD_STATUS_OFFLINE;
7710 ret = -EIO;
7711 goto exit;
7712 }
7713
Haynes Mathew George16081042017-05-31 17:16:49 -07007714 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
7715 step = "open";
7716 ret = -ENODEV;
7717 goto exit;
7718 }
7719
7720 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
7721 if (ret < 0) {
7722 step = "begin";
7723 goto exit;
7724 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007725
juyuchen626833d2019-06-04 16:48:02 +08007726 info->flags = 0;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007727 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
7728 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
7729 info->burst_size_frames = in->config.period_size;
7730 ret = platform_get_mmap_data_fd(adev->platform,
7731 in->pcm_device_id, 1 /*capture*/,
7732 &info->shared_memory_fd,
7733 &mmap_size);
7734 if (ret < 0) {
7735 // Fall back to non exclusive mode
7736 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
7737 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07007738 in->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
7739 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, in->mmap_shared_memory_fd);
7740
Arun Mirpuri5d170872019-03-26 13:21:31 -07007741 if (mmap_size < buffer_size) {
7742 step = "mmap";
7743 goto exit;
7744 }
juyuchen626833d2019-06-04 16:48:02 +08007745 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007746 }
7747
7748 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07007749
7750 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
7751 if (ret < 0) {
7752 step = "commit";
7753 goto exit;
7754 }
7755
Phil Burke0a86d12019-02-16 22:28:11 -08007756 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
7757
Haynes Mathew George16081042017-05-31 17:16:49 -07007758 in->standby = false;
7759 ret = 0;
7760
7761 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
7762 __func__, info->shared_memory_address, info->buffer_size_frames);
7763
7764exit:
7765 if (ret != 0) {
7766 if (in->pcm == NULL) {
7767 ALOGE("%s: %s - %d", __func__, step, ret);
7768 } else {
7769 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
7770 pcm_close(in->pcm);
7771 in->pcm = NULL;
7772 }
7773 }
7774 pthread_mutex_unlock(&adev->lock);
7775 return ret;
7776}
7777
7778static int in_get_mmap_position(const struct audio_stream_in *stream,
7779 struct audio_mmap_position *position)
7780{
7781 struct stream_in *in = (struct stream_in *)stream;
7782 ALOGVV("%s", __func__);
7783 if (position == NULL) {
7784 return -EINVAL;
7785 }
Gautam Manam34d1f542021-01-05 20:24:37 +05307786 lock_input_stream(in);
Haynes Mathew George16081042017-05-31 17:16:49 -07007787 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
Gautam Manam34d1f542021-01-05 20:24:37 +05307788 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07007789 return -ENOSYS;
7790 }
7791 if (in->pcm == NULL) {
Gautam Manam34d1f542021-01-05 20:24:37 +05307792 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07007793 return -ENOSYS;
7794 }
7795 struct timespec ts = { 0, 0 };
7796 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
7797 if (ret < 0) {
7798 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
Gautam Manam34d1f542021-01-05 20:24:37 +05307799 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07007800 return ret;
7801 }
Phil Burke0a86d12019-02-16 22:28:11 -08007802 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7803 + in->mmap_time_offset_nanos;
Gautam Manam34d1f542021-01-05 20:24:37 +05307804 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07007805 return 0;
7806}
7807
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307808static int in_get_active_microphones(const struct audio_stream_in *stream,
7809 struct audio_microphone_characteristic_t *mic_array,
7810 size_t *mic_count) {
7811 struct stream_in *in = (struct stream_in *)stream;
7812 struct audio_device *adev = in->dev;
7813 ALOGVV("%s", __func__);
7814
7815 lock_input_stream(in);
7816 pthread_mutex_lock(&adev->lock);
7817 int ret = platform_get_active_microphones(adev->platform,
7818 audio_channel_count_from_in_mask(in->channel_mask),
7819 in->usecase, mic_array, mic_count);
7820 pthread_mutex_unlock(&adev->lock);
7821 pthread_mutex_unlock(&in->lock);
7822
7823 return ret;
7824}
7825
7826static int adev_get_microphones(const struct audio_hw_device *dev,
7827 struct audio_microphone_characteristic_t *mic_array,
7828 size_t *mic_count) {
7829 struct audio_device *adev = (struct audio_device *)dev;
7830 ALOGVV("%s", __func__);
7831
7832 pthread_mutex_lock(&adev->lock);
7833 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
7834 pthread_mutex_unlock(&adev->lock);
7835
7836 return ret;
7837}
juyuchendb308c22019-01-21 11:57:17 -07007838
7839static void in_update_sink_metadata(struct audio_stream_in *stream,
7840 const struct sink_metadata *sink_metadata) {
7841
7842 if (stream == NULL
7843 || sink_metadata == NULL
7844 || sink_metadata->tracks == NULL) {
7845 return;
7846 }
7847
7848 int error = 0;
7849 struct stream_in *in = (struct stream_in *)stream;
7850 struct audio_device *adev = in->dev;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007851 struct listnode devices;
7852
7853 list_init(&devices);
juyuchendb308c22019-01-21 11:57:17 -07007854
7855 if (sink_metadata->track_count != 0)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007856 reassign_device_list(&devices, sink_metadata->tracks->dest_device, "");
juyuchendb308c22019-01-21 11:57:17 -07007857
7858 lock_input_stream(in);
7859 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007860 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, get_device_types(&devices));
juyuchendb308c22019-01-21 11:57:17 -07007861
Zhou Song503196b2021-07-23 17:31:05 +08007862 if ((in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY ||
7863 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2) &&
7864 !list_empty(&devices) &&
7865 adev->voice_tx_output != NULL) {
juyuchendb308c22019-01-21 11:57:17 -07007866 /* Use the rx device from afe-proxy record to route voice call because
7867 there is no routing if tx device is on primary hal and rx device
7868 is on other hal during voice call. */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007869 assign_devices(&adev->voice_tx_output->device_list, &devices);
juyuchendb308c22019-01-21 11:57:17 -07007870
7871 if (!voice_is_call_state_active(adev)) {
7872 if (adev->mode == AUDIO_MODE_IN_CALL) {
7873 adev->current_call_output = adev->voice_tx_output;
7874 error = voice_start_call(adev);
7875 if (error != 0)
7876 ALOGE("%s: start voice call failed %d", __func__, error);
7877 }
7878 } else {
7879 adev->current_call_output = adev->voice_tx_output;
7880 voice_update_devices_for_all_voice_usecases(adev);
7881 }
7882 }
7883
7884 pthread_mutex_unlock(&adev->lock);
7885 pthread_mutex_unlock(&in->lock);
7886}
7887
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307888int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07007889 audio_io_handle_t handle,
7890 audio_devices_t devices,
7891 audio_output_flags_t flags,
7892 struct audio_config *config,
7893 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04007894 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007895{
7896 struct audio_device *adev = (struct audio_device *)dev;
7897 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05307898 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007899 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007900 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05307901 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007902 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
7903 bool is_usb_dev = audio_is_usb_out_device(devices) &&
7904 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
7905 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007906 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07007907 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
7908 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007909 bool force_haptic_path =
7910 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007911 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08007912#ifdef AUDIO_GKI_ENABLED
7913 __s32 *generic_dec;
7914#endif
Weiyin Jiang906db3c2021-03-02 13:17:04 +08007915 pthread_mutexattr_t latch_attr;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007916
kunleizdff872d2018-08-20 14:40:33 +08007917 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007918 is_usb_dev = false;
7919 devices = AUDIO_DEVICE_OUT_SPEAKER;
7920 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
7921 __func__, devices);
Mingshu Pangdbd20562019-11-25 18:04:39 +08007922 if (config->format == AUDIO_FORMAT_DEFAULT)
7923 config->format = AUDIO_FORMAT_PCM_16_BIT;
7924 if (config->sample_rate == 0)
7925 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7926 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7927 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
kunleizd6a9e0c2018-07-30 15:38:52 +08007928 }
7929
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007930 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05307931
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007932 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
7933
Mingming Yin3a941d42016-02-17 18:08:05 -08007934 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04007935 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
7936 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307937
7938
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007939 if (!out) {
7940 return -ENOMEM;
7941 }
7942
Haynes Mathew George204045b2015-02-25 20:32:03 -08007943 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007944 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Weiyin Jiang906db3c2021-03-02 13:17:04 +08007945 pthread_mutexattr_init(&latch_attr);
7946 pthread_mutexattr_settype(&latch_attr, PTHREAD_MUTEX_RECURSIVE);
7947 pthread_mutex_init(&out->latch_lock, &latch_attr);
7948 pthread_mutexattr_destroy(&latch_attr);
Zhou Song48453a02018-01-10 17:50:59 +08007949 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08007950 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
7951
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007952 if (devices == AUDIO_DEVICE_NONE)
7953 devices = AUDIO_DEVICE_OUT_SPEAKER;
7954
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007955 out->flags = flags;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007956 list_init(&out->device_list);
7957 update_device_list(&out->device_list, devices, address, true /* add devices */);
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07007958 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07007959 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007960 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05307961 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05307962 if (out->channel_mask == AUDIO_CHANNEL_NONE)
7963 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
7964 else
7965 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07007966 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007967 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08007968 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307969 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307970 out->started = 0;
Zhou Songbaddf9f2020-11-20 13:57:39 +08007971 out->a2dp_muted = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007972 out->hal_output_suspend_supported = 0;
7973 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05307974 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05307975 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05307976 out->pspd_coeff_sent = false;
Phil Burkd898ba62019-06-20 12:49:01 -07007977 out->mmap_shared_memory_fd = -1; // not open
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007978
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05307979 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05307980 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07007981 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
7982
Aalique Grahame22e49102018-12-18 14:23:57 -08007983 if (direct_dev &&
7984 (audio_is_linear_pcm(out->format) ||
7985 config->format == AUDIO_FORMAT_DEFAULT) &&
7986 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
7987 audio_format_t req_format = config->format;
7988 audio_channel_mask_t req_channel_mask = config->channel_mask;
7989 uint32_t req_sample_rate = config->sample_rate;
7990
7991 pthread_mutex_lock(&adev->lock);
7992 if (is_hdmi) {
7993 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
7994 ret = read_hdmi_sink_caps(out);
7995 if (config->sample_rate == 0)
7996 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7997 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7998 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
7999 if (config->format == AUDIO_FORMAT_DEFAULT)
8000 config->format = AUDIO_FORMAT_PCM_16_BIT;
8001 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008002 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
8003 &config->format,
8004 &out->supported_formats[0],
8005 MAX_SUPPORTED_FORMATS,
8006 &config->channel_mask,
8007 &out->supported_channel_masks[0],
8008 MAX_SUPPORTED_CHANNEL_MASKS,
8009 &config->sample_rate,
8010 &out->supported_sample_rates[0],
8011 MAX_SUPPORTED_SAMPLE_RATES);
8012 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008013 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008014
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008015 pthread_mutex_unlock(&adev->lock);
8016 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08008017 if (ret == -ENOSYS) {
8018 /* ignore and go with default */
8019 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08008020 }
8021 // For MMAP NO IRQ, allow conversions in ADSP
8022 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
8023 goto error_open;
8024 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008025 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08008026 goto error_open;
8027 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008028
8029 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
8030 config->sample_rate = req_sample_rate;
8031 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
8032 config->channel_mask = req_channel_mask;
8033 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
8034 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08008035 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008036
8037 out->sample_rate = config->sample_rate;
8038 out->channel_mask = config->channel_mask;
8039 out->format = config->format;
8040 if (is_hdmi) {
8041 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
8042 out->config = pcm_config_hdmi_multi;
8043 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8044 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8045 out->config = pcm_config_mmap_playback;
8046 out->stream.start = out_start;
8047 out->stream.stop = out_stop;
8048 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8049 out->stream.get_mmap_position = out_get_mmap_position;
8050 } else {
8051 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
8052 out->config = pcm_config_hifi;
8053 }
8054
8055 out->config.rate = out->sample_rate;
8056 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
8057 if (is_hdmi) {
8058 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
8059 audio_bytes_per_sample(out->format));
8060 }
8061 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08008062 }
8063
Derek Chenf6318be2017-06-12 17:16:24 -04008064 /* validate bus device address */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008065 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008066 /* extract car audio stream index */
8067 out->car_audio_stream =
8068 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
8069 if (out->car_audio_stream < 0) {
8070 ALOGE("%s: invalid car audio stream %x",
8071 __func__, out->car_audio_stream);
8072 ret = -EINVAL;
8073 goto error_open;
8074 }
Derek Chen5f67a942020-02-24 23:08:13 -08008075 ALOGV("%s: car_audio_stream %x", __func__, out->car_audio_stream);
Derek Chenf6318be2017-06-12 17:16:24 -04008076 }
8077
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008078 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07008079 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008080 if (!voice_extn_is_compress_voip_supported()) {
8081 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
8082 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07008083 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
Lakshman Chaluvarajue7fc9482020-05-30 14:29:29 +05308084 config->channel_mask : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008085 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
8086 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07008087 out->volume_l = INVALID_OUT_VOLUME;
8088 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07008089
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008090 out->config = default_pcm_config_voip_copp;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008091 out->config.rate = out->sample_rate;
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07008092 uint32_t channel_count =
8093 audio_channel_count_from_out_mask(out->channel_mask);
Ramjee Singh968858a2020-08-06 16:30:48 +05308094 out->config.channels = channel_count;
8095
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07008096 uint32_t buffer_size = get_stream_buffer_size(DEFAULT_VOIP_BUF_DURATION_MS,
8097 out->sample_rate, out->format,
8098 channel_count, false);
8099 uint32_t frame_size = audio_bytes_per_sample(out->format) * channel_count;
8100 if (frame_size != 0)
8101 out->config.period_size = buffer_size / frame_size;
8102 else
8103 ALOGW("%s: frame size is 0 for format %#x", __func__, out->format);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008104 }
8105 } else {
8106 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
8107 voice_extn_compress_voip_is_active(out->dev)) &&
8108 (voice_extn_compress_voip_is_config_supported(config))) {
8109 ret = voice_extn_compress_voip_open_output_stream(out);
8110 if (ret != 0) {
8111 ALOGE("%s: Compress voip output cannot be opened, error:%d",
8112 __func__, ret);
8113 goto error_open;
8114 }
Sujin Panicker19027262019-09-16 18:28:06 +05308115 } else {
8116 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8117 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008118 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008119 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008120 } else if (audio_is_linear_pcm(out->format) &&
8121 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
8122 out->channel_mask = config->channel_mask;
8123 out->sample_rate = config->sample_rate;
8124 out->format = config->format;
8125 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
8126 // does this change?
8127 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
8128 out->config.rate = config->sample_rate;
8129 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
8130 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
8131 audio_bytes_per_sample(config->format));
8132 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07008133 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308134 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308135 pthread_mutex_lock(&adev->lock);
8136 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
8137 pthread_mutex_unlock(&adev->lock);
8138
8139 // reject offload during card offline to allow
8140 // fallback to s/w paths
8141 if (offline) {
8142 ret = -ENODEV;
8143 goto error_open;
8144 }
vivek mehta0ea887a2015-08-26 14:01:20 -07008145
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008146 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
8147 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
8148 ALOGE("%s: Unsupported Offload information", __func__);
8149 ret = -EINVAL;
8150 goto error_open;
8151 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008152
Atul Khare3fa6e542017-08-09 00:56:17 +05308153 if (config->offload_info.format == 0)
8154 config->offload_info.format = config->format;
8155 if (config->offload_info.sample_rate == 0)
8156 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008157
Mingming Yin90310102013-11-13 16:57:00 -08008158 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308159 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07008160 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008161 ret = -EINVAL;
8162 goto error_open;
8163 }
8164
Ben Romberger0f8c87b2017-05-24 17:41:11 -07008165 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
8166 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
8167 (audio_extn_passthru_is_passthrough_stream(out)) &&
8168 !((config->sample_rate == 48000) ||
8169 (config->sample_rate == 96000) ||
8170 (config->sample_rate == 192000))) {
8171 ALOGE("%s: Unsupported sample rate %d for audio format %x",
8172 __func__, config->sample_rate, config->offload_info.format);
8173 ret = -EINVAL;
8174 goto error_open;
8175 }
8176
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008177 out->compr_config.codec = (struct snd_codec *)
8178 calloc(1, sizeof(struct snd_codec));
8179
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008180 if (!out->compr_config.codec) {
8181 ret = -ENOMEM;
8182 goto error_open;
8183 }
8184
Dhananjay Kumarac341582017-02-23 23:42:25 +05308185 out->stream.pause = out_pause;
8186 out->stream.resume = out_resume;
8187 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05308188 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05308189 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07008190 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05308191 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07008192 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05308193 } else {
8194 out->usecase = get_offload_usecase(adev, false /* is_compress */);
8195 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07008196 }
vivek mehta446c3962015-09-14 10:57:35 -07008197
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308198 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8199 ALOGD("%s: Setting latency mode to true", __func__);
Meng Wang4c32fb42020-01-16 17:57:11 +08008200#ifdef AUDIO_GKI_ENABLED
8201 /* out->compr_config.codec->reserved[1] is for flags */
8202 out->compr_config.codec->reserved[1] |= audio_extn_utils_get_perf_mode_flag();
8203#else
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308204 out->compr_config.codec->flags |= audio_extn_utils_get_perf_mode_flag();
Meng Wang4c32fb42020-01-16 17:57:11 +08008205#endif
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308206 }
8207
vivek mehta446c3962015-09-14 10:57:35 -07008208 if (out->usecase == USECASE_INVALID) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008209 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Mingming Yin3a941d42016-02-17 18:08:05 -08008210 config->format == 0 && config->sample_rate == 0 &&
8211 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07008212 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08008213 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
8214 } else {
8215 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
8216 ret = -EEXIST;
8217 goto error_open;
8218 }
vivek mehta446c3962015-09-14 10:57:35 -07008219 }
8220
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008221 if (config->offload_info.channel_mask)
8222 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008223 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008224 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008225 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008226 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05308227 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008228 ret = -EINVAL;
8229 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008230 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008231
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008232 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008233 out->sample_rate = config->offload_info.sample_rate;
8234
Mingming Yin3ee55c62014-08-04 14:23:35 -07008235 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008236
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308237 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05308238 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308239 audio_extn_dolby_send_ddp_endp_params(adev);
8240 audio_extn_dolby_set_dmid(adev);
8241 }
vivek mehta0ea887a2015-08-26 14:01:20 -07008242
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008243 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08008244 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008245 out->compr_config.codec->bit_rate =
8246 config->offload_info.bit_rate;
8247 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05308248 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008249 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05308250 /* Update bit width only for non passthrough usecases.
8251 * For passthrough usecases, the output will always be opened @16 bit
8252 */
8253 if (!audio_extn_passthru_is_passthrough_stream(out))
8254 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308255
8256 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
Meng Wang4c32fb42020-01-16 17:57:11 +08008257#ifdef AUDIO_GKI_ENABLED
8258 /* out->compr_config.codec->reserved[1] is for flags */
8259 out->compr_config.codec->reserved[1] |= COMPRESSED_TIMESTAMP_FLAG;
8260 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->reserved[1]);
8261#else
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308262 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
8263 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
Meng Wang4c32fb42020-01-16 17:57:11 +08008264#endif
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308265
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008266 /*TODO: Do we need to change it for passthrough */
8267 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008268
Manish Dewangana6fc5442015-08-24 20:30:31 +05308269 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
8270 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308271 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05308272 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308273 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
8274 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308275
8276 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
8277 AUDIO_FORMAT_PCM) {
8278
8279 /*Based on platform support, configure appropriate alsa format for corresponding
8280 *hal input format.
8281 */
8282 out->compr_config.codec->format = hal_format_to_alsa(
8283 config->offload_info.format);
8284
Ashish Jain83a6cc22016-06-28 14:34:17 +05308285 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05308286 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308287 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308288
Dhananjay Kumarac341582017-02-23 23:42:25 +05308289 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05308290 *hal input format and alsa format might differ based on platform support.
8291 */
8292 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05308293 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308294
8295 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
8296
Deeraj Soman93155a62019-09-30 19:00:37 +05308297 if (property_get_bool("vendor.audio.offload.buffer.duration.enabled", false)) {
8298 if ((config->offload_info.duration_us >= MIN_OFFLOAD_BUFFER_DURATION_MS * 1000) &&
8299 (config->offload_info.duration_us <= MAX_OFFLOAD_BUFFER_DURATION_MS * 1000))
8300 out->info.duration_us = (int64_t)config->offload_info.duration_us;
8301 }
Deeraj Soman65358ab2019-02-07 15:40:49 +05308302
Ashish Jainf1eaa582016-05-23 20:54:24 +05308303 /* Check if alsa session is configured with the same format as HAL input format,
8304 * if not then derive correct fragment size needed to accomodate the
8305 * conversion of HAL input format to alsa format.
8306 */
8307 audio_extn_utils_update_direct_pcm_fragment_size(out);
8308
8309 /*if hal input and output fragment size is different this indicates HAL input format is
8310 *not same as the alsa format
8311 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308312 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05308313 /*Allocate a buffer to convert input data to the alsa configured format.
8314 *size of convert buffer is equal to the size required to hold one fragment size
8315 *worth of pcm data, this is because flinger does not write more than fragment_size
8316 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308317 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
8318 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05308319 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
8320 ret = -ENOMEM;
8321 goto error_open;
8322 }
8323 }
8324 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
8325 out->compr_config.fragment_size =
8326 audio_extn_passthru_get_buffer_size(&config->offload_info);
8327 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8328 } else {
8329 out->compr_config.fragment_size =
8330 platform_get_compress_offload_buffer_size(&config->offload_info);
8331 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8332 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008333
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308334 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8335 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
8336 }
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008337 if (config->offload_info.format == AUDIO_FORMAT_FLAC) {
8338#ifdef AUDIO_GKI_ENABLED
8339 generic_dec =
8340 &(out->compr_config.codec->options.generic.reserved[1]);
8341 ((struct snd_generic_dec_flac *)generic_dec)->sample_size =
8342 AUDIO_OUTPUT_BIT_WIDTH;
8343#else
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05308344 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008345#endif
8346 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008347
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05308348 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
8349 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
8350 }
8351
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008352 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
8353 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008354
Manish Dewangan69426c82017-01-30 17:35:36 +05308355 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
8356 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
8357 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
8358 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8359 out->render_mode = RENDER_MODE_AUDIO_MASTER;
8360 } else {
8361 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
8362 }
Alexy Josephaa54c872014-12-03 02:46:47 -08008363
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05308364 memset(&out->channel_map_param, 0,
8365 sizeof(struct audio_out_channel_map_param));
8366
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008367 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05308368 out->send_next_track_params = false;
8369 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008370 out->offload_state = OFFLOAD_STATE_IDLE;
8371 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08008372 out->writeAt.tv_sec = 0;
8373 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008374
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008375 audio_extn_dts_create_state_notifier_node(out->usecase);
8376
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008377 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
8378 __func__, config->offload_info.version,
8379 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05308380
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308381 /* Check if DSD audio format is supported in codec
8382 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308383 */
8384
8385 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308386 (!platform_check_codec_dsd_support(adev->platform) ||
8387 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308388 ret = -EINVAL;
8389 goto error_open;
8390 }
8391
Ashish Jain5106d362016-05-11 19:23:33 +05308392 /* Disable gapless if any of the following is true
8393 * passthrough playback
8394 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05308395 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05308396 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308397 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308398 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07008399 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308400 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308401 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05308402 check_and_set_gapless_mode(adev, false);
8403 } else
8404 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07008405
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308406 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07008407 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
8408 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308409 if (config->format == AUDIO_FORMAT_DSD) {
8410 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
Meng Wang4c32fb42020-01-16 17:57:11 +08008411#ifdef AUDIO_GKI_ENABLED
8412 /* out->compr_config.codec->reserved[0] is for compr_passthr */
8413 out->compr_config.codec->reserved[0] = PASSTHROUGH_DSD;
8414#else
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308415 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
Meng Wang4c32fb42020-01-16 17:57:11 +08008416#endif
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308417 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07008418
8419 create_offload_callback_thread(out);
8420
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008421 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008422 switch (config->sample_rate) {
8423 case 0:
8424 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8425 break;
8426 case 8000:
8427 case 16000:
8428 case 48000:
8429 out->sample_rate = config->sample_rate;
8430 break;
8431 default:
8432 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
8433 config->sample_rate);
8434 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8435 ret = -EINVAL;
8436 goto error_open;
8437 }
8438 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8439 switch (config->channel_mask) {
8440 case AUDIO_CHANNEL_NONE:
8441 case AUDIO_CHANNEL_OUT_STEREO:
8442 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8443 break;
8444 default:
8445 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
8446 config->channel_mask);
8447 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8448 ret = -EINVAL;
8449 goto error_open;
8450 }
8451 switch (config->format) {
8452 case AUDIO_FORMAT_DEFAULT:
8453 case AUDIO_FORMAT_PCM_16_BIT:
8454 out->format = AUDIO_FORMAT_PCM_16_BIT;
8455 break;
8456 default:
8457 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
8458 config->format);
8459 config->format = AUDIO_FORMAT_PCM_16_BIT;
8460 ret = -EINVAL;
8461 goto error_open;
8462 }
8463
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05308464 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008465 if (ret != 0) {
8466 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008467 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008468 goto error_open;
8469 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008470 } else if (is_single_device_type_equal(&out->device_list,
8471 AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08008472 switch (config->sample_rate) {
8473 case 0:
8474 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
8475 break;
8476 case 8000:
8477 case 16000:
8478 case 48000:
8479 out->sample_rate = config->sample_rate;
8480 break;
8481 default:
8482 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
8483 config->sample_rate);
8484 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8485 ret = -EINVAL;
8486 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008487 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008488 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8489 switch (config->channel_mask) {
8490 case AUDIO_CHANNEL_NONE:
8491 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8492 break;
8493 case AUDIO_CHANNEL_OUT_STEREO:
8494 out->channel_mask = config->channel_mask;
8495 break;
8496 default:
8497 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
8498 config->channel_mask);
8499 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8500 ret = -EINVAL;
8501 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008502 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008503 switch (config->format) {
8504 case AUDIO_FORMAT_DEFAULT:
8505 out->format = AUDIO_FORMAT_PCM_16_BIT;
8506 break;
8507 case AUDIO_FORMAT_PCM_16_BIT:
8508 out->format = config->format;
8509 break;
8510 default:
8511 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
8512 config->format);
8513 config->format = AUDIO_FORMAT_PCM_16_BIT;
8514 ret = -EINVAL;
8515 break;
8516 }
8517 if (ret != 0)
8518 goto error_open;
8519
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008520 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
8521 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08008522 out->config.rate = out->sample_rate;
8523 out->config.channels =
8524 audio_channel_count_from_out_mask(out->channel_mask);
8525 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008526 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008527 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05308528 unsigned int channels = 0;
8529 /*Update config params to default if not set by the caller*/
8530 if (config->sample_rate == 0)
8531 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8532 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8533 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8534 if (config->format == AUDIO_FORMAT_DEFAULT)
8535 config->format = AUDIO_FORMAT_PCM_16_BIT;
8536
8537 channels = audio_channel_count_from_out_mask(out->channel_mask);
8538
Varun Balaraje49253e2017-07-06 19:48:56 +05308539 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
8540 out->usecase = get_interactive_usecase(adev);
8541 out->config = pcm_config_low_latency;
8542 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05308543 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008544 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
8545 out->flags);
8546 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07008547 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8548 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8549 out->config = pcm_config_mmap_playback;
8550 out->stream.start = out_start;
8551 out->stream.stop = out_stop;
8552 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8553 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308554 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8555 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008556 out->hal_output_suspend_supported =
8557 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
8558 out->dynamic_pm_qos_config_supported =
8559 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
8560 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08008561 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
8562 } else {
8563 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
8564 //the mixer path will be a string similar to "low-latency-playback resume"
8565 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
8566 strlcat(out->pm_qos_mixer_path,
8567 " resume", MAX_MIXER_PATH_LEN);
8568 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
8569 out->pm_qos_mixer_path);
8570 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308571 out->config = pcm_config_low_latency;
8572 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
8573 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
8574 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05308575 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
8576 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
8577 if (out->config.period_size <= 0) {
8578 ALOGE("Invalid configuration period size is not valid");
8579 ret = -EINVAL;
8580 goto error_open;
8581 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008582 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
8583 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
8584 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008585 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
8586 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
8587 out->config = pcm_config_haptics_audio;
8588 if (force_haptic_path)
8589 adev->haptics_config = pcm_config_haptics_audio;
8590 else
8591 adev->haptics_config = pcm_config_haptics;
8592
Meng Wangd08ce322020-04-02 08:59:20 +08008593 channels =
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008594 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
8595
8596 if (force_haptic_path) {
8597 out->config.channels = 1;
8598 adev->haptics_config.channels = 1;
8599 } else
8600 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 -08008601 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008602 ret = audio_extn_auto_hal_open_output_stream(out);
8603 if (ret) {
8604 ALOGE("%s: Failed to open output stream for bus device", __func__);
8605 ret = -EINVAL;
8606 goto error_open;
8607 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308608 } else {
8609 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008610 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8611 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308612 }
8613 out->hal_ip_format = format = out->format;
8614 out->config.format = hal_format_to_pcm(out->hal_ip_format);
8615 out->hal_op_format = pcm_format_to_hal(out->config.format);
8616 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
8617 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008618 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05308619 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308620 if (out->hal_ip_format != out->hal_op_format) {
8621 uint32_t buffer_size = out->config.period_size *
8622 format_to_bitwidth_table[out->hal_op_format] *
8623 out->config.channels;
8624 out->convert_buffer = calloc(1, buffer_size);
8625 if (out->convert_buffer == NULL){
8626 ALOGE("Allocation failed for convert buffer for size %d",
8627 out->compr_config.fragment_size);
8628 ret = -ENOMEM;
8629 goto error_open;
8630 }
8631 ALOGD("Convert buffer allocated of size %d", buffer_size);
8632 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008633 }
8634
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008635 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
8636 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308637
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008638 /* TODO remove this hardcoding and check why width is zero*/
8639 if (out->bit_width == 0)
8640 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308641 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008642 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008643 &out->device_list, out->flags,
8644 out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05308645 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05308646 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08008647 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08008648 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
8649 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008650 if(adev->primary_output == NULL)
8651 adev->primary_output = out;
8652 else {
8653 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008654 ret = -EEXIST;
8655 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008656 }
8657 }
8658
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008659 /* Check if this usecase is already existing */
8660 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07008661 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
8662 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008663 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008664 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008665 ret = -EEXIST;
8666 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008667 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008668
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008669 pthread_mutex_unlock(&adev->lock);
8670
8671 out->stream.common.get_sample_rate = out_get_sample_rate;
8672 out->stream.common.set_sample_rate = out_set_sample_rate;
8673 out->stream.common.get_buffer_size = out_get_buffer_size;
8674 out->stream.common.get_channels = out_get_channels;
8675 out->stream.common.get_format = out_get_format;
8676 out->stream.common.set_format = out_set_format;
8677 out->stream.common.standby = out_standby;
8678 out->stream.common.dump = out_dump;
8679 out->stream.common.set_parameters = out_set_parameters;
8680 out->stream.common.get_parameters = out_get_parameters;
8681 out->stream.common.add_audio_effect = out_add_audio_effect;
8682 out->stream.common.remove_audio_effect = out_remove_audio_effect;
8683 out->stream.get_latency = out_get_latency;
8684 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08008685#ifdef NO_AUDIO_OUT
8686 out->stream.write = out_write_for_no_output;
8687#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008688 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08008689#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008690 out->stream.get_render_position = out_get_render_position;
8691 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008692 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008693
Haynes Mathew George16081042017-05-31 17:16:49 -07008694 if (out->realtime)
8695 out->af_period_multiplier = af_period_multiplier;
8696 else
8697 out->af_period_multiplier = 1;
8698
Andy Hunga1f48fa2019-07-01 18:14:53 -07008699 out->kernel_buffer_size = out->config.period_size * out->config.period_count;
8700
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008701 out->standby = 1;
Zhou Songbaddf9f2020-11-20 13:57:39 +08008702 out->volume_l = PLAYBACK_GAIN_MAX;
8703 out->volume_r = PLAYBACK_GAIN_MAX;
Eric Laurenta9024de2013-04-04 09:19:12 -07008704 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008705 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008706
8707 config->format = out->stream.common.get_format(&out->stream.common);
8708 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
8709 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308710 register_format(out->format, out->supported_formats);
8711 register_channel_mask(out->channel_mask, out->supported_channel_masks);
8712 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008713
Dechen Chai22768452021-07-30 09:29:16 +05308714#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -08008715 out->error_log = error_log_create(
8716 ERROR_LOG_ENTRIES,
8717 1000000000 /* aggregate consecutive identical errors within one second in ns */);
Dechen Chai22768452021-07-30 09:29:16 +05308718#endif
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308719 /*
8720 By locking output stream before registering, we allow the callback
8721 to update stream's state only after stream's initial state is set to
8722 adev state.
8723 */
8724 lock_output_stream(out);
8725 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
8726 pthread_mutex_lock(&adev->lock);
8727 out->card_status = adev->card_status;
8728 pthread_mutex_unlock(&adev->lock);
8729 pthread_mutex_unlock(&out->lock);
8730
Aalique Grahame22e49102018-12-18 14:23:57 -08008731 stream_app_type_cfg_init(&out->app_type_cfg);
8732
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008733 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308734 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07008735 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008736
8737 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
8738 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
8739 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008740 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05308741 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008742 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07008743 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05308744 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
8745 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008746 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
8747 out->usecase, PCM_PLAYBACK);
8748 hdlr_stream_cfg.flags = out->flags;
8749 hdlr_stream_cfg.type = PCM_PLAYBACK;
8750 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
8751 &hdlr_stream_cfg);
8752 if (ret) {
8753 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
8754 out->adsp_hdlr_stream_handle = NULL;
8755 }
8756 }
Gangadhar Sb0210342019-02-22 17:39:41 +05308757 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
8758 is_direct_passthough, false);
8759 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
8760 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07008761 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07008762 if (ret < 0) {
8763 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
8764 out->ip_hdlr_handle = NULL;
8765 }
8766 }
Derek Chenf939fb72018-11-13 13:34:41 -08008767
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008768 ret = io_streams_map_insert(adev, &out->stream.common,
8769 out->handle, AUDIO_PATCH_HANDLE_NONE);
8770 if (ret != 0)
8771 goto error_open;
8772
Susan Wang6dd13092021-01-25 10:27:11 -05008773 out->out_ctxt.output = out;
Derek Chenf939fb72018-11-13 13:34:41 -08008774
8775 pthread_mutex_lock(&adev->lock);
Susan Wang6dd13092021-01-25 10:27:11 -05008776 list_add_tail(&adev->active_outputs_list, &out->out_ctxt.list);
Derek Chenf939fb72018-11-13 13:34:41 -08008777 pthread_mutex_unlock(&adev->lock);
8778
Eric Laurent994a6932013-07-17 11:51:42 -07008779 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008780 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008781
8782error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05308783 if (out->convert_buffer)
8784 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008785 free(out);
8786 *stream_out = NULL;
8787 ALOGD("%s: exit: ret %d", __func__, ret);
8788 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008789}
8790
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308791void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008792 struct audio_stream_out *stream)
8793{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008794 struct stream_out *out = (struct stream_out *)stream;
8795 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008796 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008797
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008798 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308799
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008800 io_streams_map_remove(adev, out->handle);
8801
Susan Wang6dd13092021-01-25 10:27:11 -05008802 // remove out_ctxt early to prevent the stream
8803 // being opened in a race condition
8804 pthread_mutex_lock(&adev->lock);
8805 list_remove(&out->out_ctxt.list);
8806 pthread_mutex_unlock(&adev->lock);
8807
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308808 // must deregister from sndmonitor first to prevent races
8809 // between the callback and close_stream
8810 audio_extn_snd_mon_unregister_listener(out);
8811
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008812 /* close adsp hdrl session before standby */
8813 if (out->adsp_hdlr_stream_handle) {
8814 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
8815 if (ret)
8816 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
8817 out->adsp_hdlr_stream_handle = NULL;
8818 }
8819
Manish Dewangan21a850a2017-08-14 12:03:55 +05308820 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07008821 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
8822 out->ip_hdlr_handle = NULL;
8823 }
8824
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008825 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308826 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008827 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308828 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308829 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008830 if(ret != 0)
8831 ALOGE("%s: Compress voip output cannot be closed, error:%d",
8832 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008833 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008834 out_standby(&stream->common);
8835
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008836 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008837 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008838 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008839 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008840 if (out->compr_config.codec != NULL)
8841 free(out->compr_config.codec);
8842 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008843
Zhou Songbaddf9f2020-11-20 13:57:39 +08008844 out->a2dp_muted = false;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05308845
Varun Balaraje49253e2017-07-06 19:48:56 +05308846 if (is_interactive_usecase(out->usecase))
8847 free_interactive_usecase(adev, out->usecase);
8848
Ashish Jain83a6cc22016-06-28 14:34:17 +05308849 if (out->convert_buffer != NULL) {
8850 free(out->convert_buffer);
8851 out->convert_buffer = NULL;
8852 }
8853
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008854 if (adev->voice_tx_output == out)
8855 adev->voice_tx_output = NULL;
8856
Dechen Chai22768452021-07-30 09:29:16 +05308857#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -08008858 error_log_destroy(out->error_log);
8859 out->error_log = NULL;
Dechen Chai22768452021-07-30 09:29:16 +05308860#endif
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05308861 if (adev->primary_output == out)
8862 adev->primary_output = NULL;
8863
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008864 pthread_cond_destroy(&out->cond);
8865 pthread_mutex_destroy(&out->lock);
Weiyin Jiang280ea742020-09-08 20:28:22 +08008866 pthread_mutex_destroy(&out->pre_lock);
8867 pthread_mutex_destroy(&out->latch_lock);
8868 pthread_mutex_destroy(&out->position_query_lock);
Derek Chenf939fb72018-11-13 13:34:41 -08008869
8870 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008871 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08008872 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07008873 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008874}
8875
8876static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
8877{
8878 struct audio_device *adev = (struct audio_device *)dev;
8879 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008880 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008881 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008882 int ret;
8883 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08008884 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008885 struct listnode *node;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008886 int controller = -1, stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008887
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008888 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008889 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008890
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308891 if (!parms)
8892 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05308893
Derek Chen6f293672019-04-01 01:40:24 -07008894 /* notify adev and input/output streams on the snd card status */
8895 adev_snd_mon_cb((void *)adev, parms);
8896
Weiyin Jiang24f55292020-12-22 14:35:46 +08008897 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
8898 if (ret >= 0) {
8899 list_for_each(node, &adev->active_outputs_list) {
8900 streams_output_ctxt_t *out_ctxt = node_to_item(node,
8901 streams_output_ctxt_t,
8902 list);
8903 out_snd_mon_cb((void *)out_ctxt->output, parms);
8904 }
Derek Chen6f293672019-04-01 01:40:24 -07008905
Weiyin Jiang24f55292020-12-22 14:35:46 +08008906 list_for_each(node, &adev->active_inputs_list) {
8907 streams_input_ctxt_t *in_ctxt = node_to_item(node,
8908 streams_input_ctxt_t,
8909 list);
8910 in_snd_mon_cb((void *)in_ctxt->input, parms);
8911 }
Derek Chen6f293672019-04-01 01:40:24 -07008912 }
8913
Zhou Songd6d71752019-05-21 18:08:51 +08008914 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308915 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
8916 if (ret >= 0) {
8917 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08008918 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308919 adev->bt_sco_on = true;
Shalini Manjunatha3a2e06e2021-02-01 12:23:49 +05308920 /*
8921 * When ever BT_SCO=ON arrives, make sure to route
8922 * all use cases to SCO device, otherwise due to delay in
8923 * BT_SCO=ON and lack of synchronization with create audio patch
8924 * request for SCO device, some times use case not routed properly to
8925 * SCO device
8926 */
8927 struct audio_usecase *usecase;
8928 struct listnode *node;
8929 list_for_each(node, &adev->usecase_list) {
8930 usecase = node_to_item(node, struct audio_usecase, list);
Anver sadhiquef0efca32021-09-03 15:25:44 +05308931 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
Anver sadhique93f3c912021-08-11 11:19:45 +05308932 (!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 +05308933 ALOGD("BT_SCO ON, switch all in use case to it");
8934 select_devices(adev, usecase->id);
8935 }
Mingshu Pangef517202021-04-22 10:35:00 +08008936 if (usecase->stream.out && (usecase->type == PCM_PLAYBACK ||
8937 usecase->type == VOICE_CALL) &&
Anver sadhique93f3c912021-08-11 11:19:45 +05308938 (!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 +05308939 ALOGD("BT_SCO ON, switch all out use case to it");
8940 select_devices(adev, usecase->id);
8941 }
8942 }
8943 }
8944 else {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308945 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008946 audio_extn_sco_reset_configuration();
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008947 }
8948 }
8949
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008950 status = voice_set_parameters(adev, parms);
8951 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008952 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008953
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008954 status = platform_set_parameters(adev->platform, parms);
8955 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008956 goto done;
8957
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008958 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
8959 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07008960 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008961 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8962 adev->bluetooth_nrec = true;
8963 else
8964 adev->bluetooth_nrec = false;
8965 }
8966
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008967 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
8968 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008969 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8970 adev->screen_off = false;
8971 else
8972 adev->screen_off = true;
Quinn Male70f20f32019-06-26 16:50:26 -07008973 audio_extn_sound_trigger_update_screen_status(adev->screen_off);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008974 }
8975
Eric Laurent4b084132018-10-19 17:33:43 -07008976 ret = str_parms_get_int(parms, "rotation", &val);
8977 if (ret >= 0) {
8978 bool reverse_speakers = false;
8979 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8980 switch (val) {
8981 // FIXME: note that the code below assumes that the speakers are in the correct placement
8982 // relative to the user when the device is rotated 90deg from its default rotation. This
8983 // assumption is device-specific, not platform-specific like this code.
8984 case 270:
8985 reverse_speakers = true;
8986 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
8987 break;
8988 case 0:
8989 case 180:
8990 camera_rotation = CAMERA_ROTATION_PORTRAIT;
8991 break;
8992 case 90:
8993 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8994 break;
8995 default:
8996 ALOGE("%s: unexpected rotation of %d", __func__, val);
8997 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008998 }
Eric Laurent4b084132018-10-19 17:33:43 -07008999 if (status == 0) {
9000 // check and set swap
9001 // - check if orientation changed and speaker active
9002 // - set rotation and cache the rotation value
9003 adev->camera_orientation =
9004 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
9005 if (!audio_extn_is_maxx_audio_enabled())
9006 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
9007 }
9008 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07009009
Mingming Yin514a8bc2014-07-29 15:22:21 -07009010 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
9011 if (ret >= 0) {
9012 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
9013 adev->bt_wb_speech_enabled = true;
9014 else
9015 adev->bt_wb_speech_enabled = false;
9016 }
9017
Zhou Song12c29502019-03-16 10:37:18 +08009018 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
9019 if (ret >= 0) {
9020 val = atoi(value);
9021 adev->swb_speech_mode = val;
9022 }
9023
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07009024 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
9025 if (ret >= 0) {
9026 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309027 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08009028 if (audio_is_output_device(val) &&
9029 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07009030 ALOGV("cache new ext disp type and edid");
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07009031 platform_get_controller_stream_from_params(parms, &controller, &stream);
9032 platform_set_ext_display_device_v2(adev->platform, controller, stream);
9033 ret = platform_get_ext_disp_type_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07009034 if (ret < 0) {
9035 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05309036 } else {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07009037 platform_cache_edid_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07009038 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309039 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07009040 /*
9041 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
9042 * Per AudioPolicyManager, USB device is higher priority than WFD.
9043 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
9044 * If WFD use case occupies AFE proxy, it may result unintended behavior while
9045 * starting voice call on USB
9046 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08009047 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309048 if (ret >= 0)
9049 audio_extn_usb_add_device(device, atoi(value));
9050
Zhou Song6f862822017-11-06 17:27:57 +08009051 if (!audio_extn_usb_is_tunnel_supported()) {
9052 ALOGV("detected USB connect .. disable proxy");
9053 adev->allow_afe_proxy_usage = false;
9054 }
Zhou Song503196b2021-07-23 17:31:05 +08009055 } else if (audio_is_hearing_aid_out_device(device) &&
9056 property_get_bool("persist.vendor.audio.ha_proxy.enabled", false)) {
9057 adev->ha_proxy_enable = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07009058 }
9059 }
9060
9061 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
9062 if (ret >= 0) {
9063 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309064 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07009065 /*
9066 * The HDMI / Displayport disconnect handling has been moved to
9067 * audio extension to ensure that its parameters are not
9068 * invalidated prior to updating sysfs of the disconnect event
9069 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
9070 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309071 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08009072 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309073 if (ret >= 0)
9074 audio_extn_usb_remove_device(device, atoi(value));
9075
Zhou Song6f862822017-11-06 17:27:57 +08009076 if (!audio_extn_usb_is_tunnel_supported()) {
9077 ALOGV("detected USB disconnect .. enable proxy");
9078 adev->allow_afe_proxy_usage = true;
9079 }
Zhou Song503196b2021-07-23 17:31:05 +08009080 } else if (audio_is_hearing_aid_out_device(device)) {
9081 adev->ha_proxy_enable = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07009082 }
9083 }
9084
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009085 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08009086
9087 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08009088 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309089 struct audio_usecase *usecase;
9090 struct listnode *node;
9091 list_for_each(node, &adev->usecase_list) {
9092 usecase = node_to_item(node, struct audio_usecase, list);
Weiyin Jiangff56ff32020-05-08 14:32:21 +08009093 if ((usecase->stream.out == NULL) || (usecase->type != PCM_PLAYBACK))
9094 continue;
9095
9096 if (is_a2dp_out_device_type(&usecase->device_list)) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309097 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05309098 audio_extn_a2dp_set_handoff_mode(true);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05309099 ALOGD("Switching to speaker and muting the stream before select_devices");
9100 check_a2dp_restore_l(adev, usecase->stream.out, false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309101 //force device switch to re configure encoder
9102 select_devices(adev, usecase->id);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05309103 ALOGD("Unmuting the stream after select_devices");
Zhou Songbaddf9f2020-11-20 13:57:39 +08009104 check_a2dp_restore_l(adev, usecase->stream.out, true);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05309105 audio_extn_a2dp_set_handoff_mode(false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309106 break;
Zhou Songd01e7a22020-09-23 22:49:01 +08009107 } else if (is_offload_usecase(usecase->stream.out->usecase)) {
Weiyin Jiang280ea742020-09-08 20:28:22 +08009108 pthread_mutex_lock(&usecase->stream.out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +08009109 if (usecase->stream.out->a2dp_muted) {
Weiyin Jiang280ea742020-09-08 20:28:22 +08009110 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
9111 reassign_device_list(&usecase->stream.out->device_list,
9112 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, "");
9113 check_a2dp_restore_l(adev, usecase->stream.out, true);
9114 break;
9115 }
9116 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309117 }
9118 }
9119 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009120
9121 //handle vr audio setparam
9122 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9123 value, sizeof(value));
9124 if (ret >= 0) {
9125 ALOGI("Setting vr mode to be %s", value);
9126 if (!strncmp(value, "true", 4)) {
9127 adev->vr_audio_mode_enabled = true;
9128 ALOGI("Setting vr mode to true");
9129 } else if (!strncmp(value, "false", 5)) {
9130 adev->vr_audio_mode_enabled = false;
9131 ALOGI("Setting vr mode to false");
9132 } else {
9133 ALOGI("wrong vr mode set");
9134 }
9135 }
9136
Eric Laurent4b084132018-10-19 17:33:43 -07009137 //FIXME: to be replaced by proper video capture properties API
9138 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
9139 if (ret >= 0) {
9140 int camera_facing = CAMERA_FACING_BACK;
9141 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
9142 camera_facing = CAMERA_FACING_FRONT;
9143 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
9144 camera_facing = CAMERA_FACING_BACK;
9145 else {
9146 ALOGW("%s: invalid camera facing value: %s", __func__, value);
9147 goto done;
9148 }
9149 adev->camera_orientation =
9150 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
9151 struct audio_usecase *usecase;
9152 struct listnode *node;
9153 list_for_each(node, &adev->usecase_list) {
9154 usecase = node_to_item(node, struct audio_usecase, list);
9155 struct stream_in *in = usecase->stream.in;
9156 if (usecase->type == PCM_CAPTURE && in != NULL &&
9157 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
9158 select_devices(adev, in->usecase);
9159 }
9160 }
9161 }
9162
Daniel Hillenbrand17873952013-05-23 10:10:00 +05309163 amplifier_set_parameters(parms);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05309164 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08009165done:
9166 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009167 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05309168error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009169 ALOGV("%s: exit with code(%d)", __func__, status);
9170 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009171}
9172
9173static char* adev_get_parameters(const struct audio_hw_device *dev,
9174 const char *keys)
9175{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05309176 ALOGD("%s:%s", __func__, keys);
9177
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009178 struct audio_device *adev = (struct audio_device *)dev;
9179 struct str_parms *reply = str_parms_create();
9180 struct str_parms *query = str_parms_create_str(keys);
9181 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05309182 char value[256] = {0};
9183 int ret = 0;
9184
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009185 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08009186 if (reply) {
9187 str_parms_destroy(reply);
9188 }
9189 if (query) {
9190 str_parms_destroy(query);
9191 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009192 ALOGE("adev_get_parameters: failed to create query or reply");
9193 return NULL;
9194 }
9195
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009196 //handle vr audio getparam
9197
9198 ret = str_parms_get_str(query,
9199 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9200 value, sizeof(value));
9201
9202 if (ret >= 0) {
9203 bool vr_audio_enabled = false;
9204 pthread_mutex_lock(&adev->lock);
9205 vr_audio_enabled = adev->vr_audio_mode_enabled;
9206 pthread_mutex_unlock(&adev->lock);
9207
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07009208 ALOGV("getting vr mode to %d", vr_audio_enabled);
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009209
9210 if (vr_audio_enabled) {
9211 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9212 "true");
9213 goto exit;
9214 } else {
9215 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9216 "false");
9217 goto exit;
9218 }
9219 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009220
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009221 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009222 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08009223 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08009224 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009225 platform_get_parameters(adev->platform, query, reply);
justinwengd5395152019-11-04 12:23:09 +08009226 audio_extn_ma_get_parameters(adev, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05309227 pthread_mutex_unlock(&adev->lock);
9228
Naresh Tannirud7205b62014-06-20 02:54:48 +05309229exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009230 str = str_parms_to_str(reply);
9231 str_parms_destroy(query);
9232 str_parms_destroy(reply);
9233
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07009234 ALOGV("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009235 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009236}
9237
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009238static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009239{
9240 return 0;
9241}
9242
9243static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
9244{
Haynes Mathew George5191a852013-09-11 14:19:36 -07009245 int ret;
9246 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08009247
9248 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
9249
Haynes Mathew George5191a852013-09-11 14:19:36 -07009250 pthread_mutex_lock(&adev->lock);
9251 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07009252 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07009253 pthread_mutex_unlock(&adev->lock);
9254 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009255}
9256
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009257static int adev_set_master_volume(struct audio_hw_device *dev __unused,
9258 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009259{
9260 return -ENOSYS;
9261}
9262
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009263static int adev_get_master_volume(struct audio_hw_device *dev __unused,
9264 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009265{
9266 return -ENOSYS;
9267}
9268
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009269static int adev_set_master_mute(struct audio_hw_device *dev __unused,
9270 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009271{
9272 return -ENOSYS;
9273}
9274
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009275static int adev_get_master_mute(struct audio_hw_device *dev __unused,
9276 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009277{
9278 return -ENOSYS;
9279}
9280
9281static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
9282{
9283 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07009284 struct listnode *node;
9285 struct audio_usecase *usecase = NULL;
9286 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08009287
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009288 pthread_mutex_lock(&adev->lock);
9289 if (adev->mode != mode) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309290 ALOGD("%s: mode %d , prev_mode %d \n", __func__, mode , adev->mode);
9291 adev->prev_mode = adev->mode; /* prev_mode is kept to handle voip concurrency*/
Daniel Hillenbrand17873952013-05-23 10:10:00 +05309292 if (amplifier_set_mode(mode) != 0)
9293 ALOGE("Failed setting amplifier mode");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009294 adev->mode = mode;
Weiyin Jiang96b96f72020-09-22 16:48:19 +08009295 if (mode == AUDIO_MODE_CALL_SCREEN) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309296 adev->current_call_output = adev->primary_output;
9297 voice_start_call(adev);
9298 } else if (voice_is_in_call_or_call_screen(adev) &&
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08009299 (mode == AUDIO_MODE_NORMAL ||
9300 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07009301 list_for_each(node, &adev->usecase_list) {
9302 usecase = node_to_item(node, struct audio_usecase, list);
9303 if (usecase->type == VOICE_CALL)
9304 break;
9305 }
9306 if (usecase &&
9307 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
9308 ret = audio_extn_usb_check_and_set_svc_int(usecase,
9309 true);
9310 if (ret != 0) {
9311 /* default service interval was successfully updated,
9312 reopen USB backend with new service interval */
9313 check_usecases_codec_backend(adev,
9314 usecase,
9315 usecase->out_snd_device);
9316 }
9317 }
9318
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009319 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07009320 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009321 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08009322 // restore device for other active usecases after stop call
9323 list_for_each(node, &adev->usecase_list) {
9324 usecase = node_to_item(node, struct audio_usecase, list);
9325 select_devices(adev, usecase->id);
9326 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009327 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009328 }
9329 pthread_mutex_unlock(&adev->lock);
9330 return 0;
9331}
9332
9333static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
9334{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009335 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08009336 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009337
9338 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08009339 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009340 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009341
Derek Chend2530072014-11-24 12:39:14 -08009342 if (adev->ext_hw_plugin)
9343 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009344
9345 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009346 pthread_mutex_unlock(&adev->lock);
9347
9348 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009349}
9350
9351static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
9352{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009353 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009354 return 0;
9355}
9356
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009357static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009358 const struct audio_config *config)
9359{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009360 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009361
Aalique Grahame22e49102018-12-18 14:23:57 -08009362 /* Don't know if USB HIFI in this context so use true to be conservative */
9363 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9364 true /*is_usb_hifi */) != 0)
9365 return 0;
9366
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009367 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
9368 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009369}
9370
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009371static bool adev_input_allow_hifi_record(struct audio_device *adev,
9372 audio_devices_t devices,
9373 audio_input_flags_t flags,
9374 audio_source_t source) {
9375 const bool allowed = true;
9376
9377 if (!audio_is_usb_in_device(devices))
9378 return !allowed;
9379
9380 switch (flags) {
9381 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009382 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07009383 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
9384 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009385 default:
9386 return !allowed;
9387 }
9388
9389 switch (source) {
9390 case AUDIO_SOURCE_DEFAULT:
9391 case AUDIO_SOURCE_MIC:
9392 case AUDIO_SOURCE_UNPROCESSED:
9393 break;
9394 default:
9395 return !allowed;
9396 }
9397
9398 switch (adev->mode) {
9399 case 0:
9400 break;
9401 default:
9402 return !allowed;
9403 }
9404
9405 return allowed;
9406}
9407
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009408static int adev_update_voice_comm_input_stream(struct stream_in *in,
9409 struct audio_config *config)
9410{
9411 bool valid_rate = (config->sample_rate == 8000 ||
9412 config->sample_rate == 16000 ||
9413 config->sample_rate == 32000 ||
9414 config->sample_rate == 48000);
9415 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
9416
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009417 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08009418 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009419 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9420 in->config = default_pcm_config_voip_copp;
9421 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
9422 DEFAULT_VOIP_BUF_DURATION_MS,
9423 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009424 } else {
9425 ALOGW("%s No valid input in voip, use defaults"
9426 "sample rate %u, channel mask 0x%X",
9427 __func__, config->sample_rate, in->channel_mask);
9428 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009429 in->config.rate = config->sample_rate;
9430 in->sample_rate = config->sample_rate;
9431 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009432 //XXX needed for voice_extn_compress_voip_open_input_stream
9433 in->config.rate = config->sample_rate;
9434 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
Shalini Manjunathaa763cc42019-08-23 15:13:46 +05309435 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009436 voice_extn_compress_voip_is_active(in->dev)) &&
9437 (voice_extn_compress_voip_is_format_supported(in->format)) &&
9438 valid_rate && valid_ch) {
9439 voice_extn_compress_voip_open_input_stream(in);
9440 // update rate entries to match config from AF
9441 in->config.rate = config->sample_rate;
9442 in->sample_rate = config->sample_rate;
9443 } else {
9444 ALOGW("%s compress voip not active, use defaults", __func__);
9445 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009446 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009447 return 0;
9448}
9449
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009450static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07009451 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009452 audio_devices_t devices,
9453 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009454 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309455 audio_input_flags_t flags,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009456 const char *address,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009457 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009458{
9459 struct audio_device *adev = (struct audio_device *)dev;
9460 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009461 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009462 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009463 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05309464 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009465 bool is_usb_dev = audio_is_usb_in_device(devices);
9466 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
9467 devices,
9468 flags,
9469 source);
Andy Hung94320602018-10-29 18:31:12 -07009470 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
9471 " sample_rate %u, channel_mask %#x, format %#x",
9472 __func__, flags, is_usb_dev, may_use_hifi_record,
9473 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309474
kunleizdff872d2018-08-20 14:40:33 +08009475 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08009476 is_usb_dev = false;
9477 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
9478 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
9479 __func__, devices);
9480 }
9481
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009482 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009483
9484 if (!(is_usb_dev && may_use_hifi_record)) {
9485 if (config->sample_rate == 0)
9486 config->sample_rate = 48000;
9487 if (config->channel_mask == AUDIO_CHANNEL_NONE)
9488 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9489 if (config->format == AUDIO_FORMAT_DEFAULT)
9490 config->format = AUDIO_FORMAT_PCM_16_BIT;
9491
9492 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
9493
Aalique Grahame22e49102018-12-18 14:23:57 -08009494 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9495 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009496 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05309497 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009498
9499 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009500
9501 if (!in) {
9502 ALOGE("failed to allocate input stream");
9503 return -ENOMEM;
9504 }
9505
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309506 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05309507 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
9508 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009509 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07009510 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009511
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009512 in->stream.common.get_sample_rate = in_get_sample_rate;
9513 in->stream.common.set_sample_rate = in_set_sample_rate;
9514 in->stream.common.get_buffer_size = in_get_buffer_size;
9515 in->stream.common.get_channels = in_get_channels;
9516 in->stream.common.get_format = in_get_format;
9517 in->stream.common.set_format = in_set_format;
9518 in->stream.common.standby = in_standby;
9519 in->stream.common.dump = in_dump;
9520 in->stream.common.set_parameters = in_set_parameters;
9521 in->stream.common.get_parameters = in_get_parameters;
9522 in->stream.common.add_audio_effect = in_add_audio_effect;
9523 in->stream.common.remove_audio_effect = in_remove_audio_effect;
9524 in->stream.set_gain = in_set_gain;
9525 in->stream.read = in_read;
9526 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08009527 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309528 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07009529 in->stream.set_microphone_direction = in_set_microphone_direction;
9530 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07009531 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009532
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009533 list_init(&in->device_list);
9534 update_device_list(&in->device_list, devices, address, true);
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009535 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009536 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009537 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009538 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009539 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07009540 in->bit_width = 16;
9541 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07009542 in->direction = MIC_DIRECTION_UNSPECIFIED;
9543 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08009544 list_init(&in->aec_list);
9545 list_init(&in->ns_list);
Phil Burkd898ba62019-06-20 12:49:01 -07009546 in->mmap_shared_memory_fd = -1; // not open
Haynes Mathew George46740472017-10-27 18:40:12 -07009547
Andy Hung94320602018-10-29 18:31:12 -07009548 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08009549 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
9550 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
9551 /* Force channel config requested to mono if incall
9552 record is being requested for only uplink/downlink */
9553 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
9554 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9555 ret = -EINVAL;
9556 goto err_open;
9557 }
9558 }
9559
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009560 if (is_usb_dev && may_use_hifi_record) {
9561 /* HiFi record selects an appropriate format, channel, rate combo
9562 depending on sink capabilities*/
9563 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
9564 &config->format,
9565 &in->supported_formats[0],
9566 MAX_SUPPORTED_FORMATS,
9567 &config->channel_mask,
9568 &in->supported_channel_masks[0],
9569 MAX_SUPPORTED_CHANNEL_MASKS,
9570 &config->sample_rate,
9571 &in->supported_sample_rates[0],
9572 MAX_SUPPORTED_SAMPLE_RATES);
9573 if (ret != 0) {
9574 ret = -EINVAL;
9575 goto err_open;
9576 }
9577 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009578 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309579 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05309580 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
9581 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
9582 in->config.format = PCM_FORMAT_S32_LE;
9583 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309584 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
9585 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
9586 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
9587 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
9588 bool ret_error = false;
9589 in->bit_width = 24;
9590 /* 24 bit is restricted to UNPROCESSED source only,also format supported
9591 from HAL is 24_packed and 8_24
9592 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
9593 24_packed return error indicating supported format is 24_packed
9594 *> In case of any other source requesting 24 bit or float return error
9595 indicating format supported is 16 bit only.
9596
9597 on error flinger will retry with supported format passed
9598 */
9599 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
9600 (source != AUDIO_SOURCE_CAMCORDER)) {
9601 config->format = AUDIO_FORMAT_PCM_16_BIT;
9602 if (config->sample_rate > 48000)
9603 config->sample_rate = 48000;
9604 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07009605 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
9606 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309607 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
9608 ret_error = true;
9609 }
9610
9611 if (ret_error) {
9612 ret = -EINVAL;
9613 goto err_open;
9614 }
9615 }
9616
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009617 in->channel_mask = config->channel_mask;
9618 in->format = config->format;
9619
9620 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309621
Huicheng Liu1404ba12020-09-11 01:03:25 -04009622 /* validate bus device address */
9623 if (compare_device_type(&in->device_list, AUDIO_DEVICE_IN_BUS)) {
9624 /* extract car audio stream index */
9625 in->car_audio_stream =
9626 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
9627 if (in->car_audio_stream < 0) {
9628 ALOGE("%s: invalid car audio stream %x",
9629 __func__, in->car_audio_stream);
9630 ret = -EINVAL;
9631 goto err_open;
9632 }
9633 ALOGV("%s: car_audio_stream 0x%x", __func__, in->car_audio_stream);
Huicheng Liuea4fd422021-01-12 18:34:50 -05009634 ret = audio_extn_auto_hal_open_input_stream(in);
9635 if (ret) {
9636 ALOGE("%s: Failed to open input stream for bus device", __func__);
9637 ret = -EINVAL;
9638 goto err_open;
9639 }
Huicheng Liu1404ba12020-09-11 01:03:25 -04009640 }
9641
Susan Wange3959562021-03-11 11:50:26 -05009642 /* reassign use case for echo reference stream on automotive platforms */
9643 if (in->source == AUDIO_SOURCE_ECHO_REFERENCE) {
9644 ret = audio_extn_auto_hal_open_echo_reference_stream(in);
9645 }
9646
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309647 if (in->source == AUDIO_SOURCE_FM_TUNER) {
9648 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
9649 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
9650 else {
9651 ret = -EINVAL;
9652 goto err_open;
9653 }
9654 }
9655
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009656 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Deeraj Somanfa377bf2019-02-06 12:57:59 +05309657 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
9658 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009659 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
9660 is_low_latency = true;
9661#if LOW_LATENCY_CAPTURE_USE_CASE
Revathi Uddarajud9f23d92020-07-27 10:55:06 +05309662 if ((flags & AUDIO_INPUT_FLAG_VOIP_TX) != 0)
9663 in->usecase = USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY;
9664 else
9665 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009666#endif
9667 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08009668 if (!in->realtime) {
9669 in->config = pcm_config_audio_capture;
9670 frame_size = audio_stream_in_frame_size(&in->stream);
9671 buffer_size = get_input_buffer_size(config->sample_rate,
9672 config->format,
9673 channel_count,
9674 is_low_latency);
9675 in->config.period_size = buffer_size / frame_size;
9676 in->config.rate = config->sample_rate;
9677 in->af_period_multiplier = 1;
9678 } else {
9679 // period size is left untouched for rt mode playback
9680 in->config = pcm_config_audio_capture_rt;
9681 in->af_period_multiplier = af_period_multiplier;
9682 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009683 }
9684
Susan Wangb803cb52021-10-14 12:03:36 -04009685 /* Additional sample rates added below must also be present
9686 in audio_policy_configuration.xml for mmap_no_irq_in */
9687 bool valid_mmap_record_rate = (config->sample_rate == 8000 ||
9688 config->sample_rate == 16000 ||
Susan Wang89da9042021-10-14 12:03:36 -04009689 config->sample_rate == 24000 ||
Susan Wangb803cb52021-10-14 12:03:36 -04009690 config->sample_rate == 32000 ||
9691 config->sample_rate == 48000);
9692 if (valid_mmap_record_rate &&
9693 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009694 in->realtime = 0;
9695 in->usecase = USECASE_AUDIO_RECORD_MMAP;
9696 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07009697 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009698 in->stream.start = in_start;
9699 in->stream.stop = in_stop;
9700 in->stream.create_mmap_buffer = in_create_mmap_buffer;
9701 in->stream.get_mmap_position = in_get_mmap_position;
Ramjee Singhbcb3b6c2021-11-17 13:19:16 +05309702 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009703 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
Haynes Mathew George46740472017-10-27 18:40:12 -07009704 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009705 in->usecase = USECASE_AUDIO_RECORD_HIFI;
9706 in->config = pcm_config_audio_capture;
9707 frame_size = audio_stream_in_frame_size(&in->stream);
9708 buffer_size = get_input_buffer_size(config->sample_rate,
9709 config->format,
9710 channel_count,
9711 false /*is_low_latency*/);
9712 in->config.period_size = buffer_size / frame_size;
9713 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009714 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07009715 switch (config->format) {
9716 case AUDIO_FORMAT_PCM_32_BIT:
9717 in->bit_width = 32;
9718 break;
9719 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
9720 case AUDIO_FORMAT_PCM_8_24_BIT:
9721 in->bit_width = 24;
9722 break;
9723 default:
9724 in->bit_width = 16;
9725 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009726 } else if (is_single_device_type_equal(&in->device_list,
9727 AUDIO_DEVICE_IN_TELEPHONY_RX) ||
9728 is_single_device_type_equal(&in->device_list,
9729 AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009730 if (config->sample_rate == 0)
9731 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9732 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
9733 config->sample_rate != 8000) {
9734 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9735 ret = -EINVAL;
9736 goto err_open;
9737 }
9738 if (config->format == AUDIO_FORMAT_DEFAULT)
9739 config->format = AUDIO_FORMAT_PCM_16_BIT;
9740 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
9741 config->format = AUDIO_FORMAT_PCM_16_BIT;
9742 ret = -EINVAL;
9743 goto err_open;
9744 }
9745
9746 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
Zhou Song62ea0282020-03-22 19:53:01 +08009747 if (adev->ha_proxy_enable &&
9748 is_single_device_type_equal(&in->device_list,
9749 AUDIO_DEVICE_IN_TELEPHONY_RX))
9750 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY2;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009751 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009752 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08009753 in->af_period_multiplier = 1;
9754 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
Shalini Manjunathaac412b32020-01-03 15:00:14 +05309755 (!voice_extn_is_compress_voip_supported()) &&
Aalique Grahame22e49102018-12-18 14:23:57 -08009756 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
9757 (config->sample_rate == 8000 ||
9758 config->sample_rate == 16000 ||
9759 config->sample_rate == 32000 ||
9760 config->sample_rate == 48000) &&
9761 channel_count == 1) {
9762 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9763 in->config = pcm_config_audio_capture;
9764 frame_size = audio_stream_in_frame_size(&in->stream);
9765 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
9766 config->sample_rate,
9767 config->format,
9768 channel_count, false /*is_low_latency*/);
9769 in->config.period_size = buffer_size / frame_size;
9770 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
9771 in->config.rate = config->sample_rate;
9772 in->af_period_multiplier = 1;
Mingshu Pangc2d65042021-01-14 16:19:10 +08009773 } else if (in->realtime) {
9774 in->config = pcm_config_audio_capture_rt;
9775 in->config.format = pcm_format_from_audio_format(config->format);
9776 in->af_period_multiplier = af_period_multiplier;
Haynes Mathew George46740472017-10-27 18:40:12 -07009777 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05309778 int ret_val;
9779 pthread_mutex_lock(&adev->lock);
9780 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
9781 in, config, &channel_mask_updated);
9782 pthread_mutex_unlock(&adev->lock);
9783
9784 if (!ret_val) {
9785 if (channel_mask_updated == true) {
9786 ALOGD("%s: return error to retry with updated channel mask (%#x)",
9787 __func__, config->channel_mask);
9788 ret = -EINVAL;
9789 goto err_open;
9790 }
9791 ALOGD("%s: created multi-channel session succesfully",__func__);
9792 } else if (audio_extn_compr_cap_enabled() &&
9793 audio_extn_compr_cap_format_supported(config->format) &&
9794 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
9795 audio_extn_compr_cap_init(in);
9796 } else if (audio_extn_cin_applicable_stream(in)) {
Deeraj Soman14230922019-01-30 16:39:30 +05309797 ret = audio_extn_cin_configure_input_stream(in, config);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309798 if (ret)
9799 goto err_open;
9800 } else {
9801 in->config = pcm_config_audio_capture;
9802 in->config.rate = config->sample_rate;
9803 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309804 in->format = config->format;
9805 frame_size = audio_stream_in_frame_size(&in->stream);
9806 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07009807 config->format,
9808 channel_count,
9809 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02009810 /* prevent division-by-zero */
9811 if (frame_size == 0) {
9812 ALOGE("%s: Error frame_size==0", __func__);
9813 ret = -EINVAL;
9814 goto err_open;
9815 }
9816
Revathi Uddarajud2634032017-12-07 14:42:34 +05309817 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08009818 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009819
Revathi Uddarajud2634032017-12-07 14:42:34 +05309820 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9821 /* optionally use VOIP usecase depending on config(s) */
9822 ret = adev_update_voice_comm_input_stream(in, config);
9823 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009824
Revathi Uddarajud2634032017-12-07 14:42:34 +05309825 if (ret) {
9826 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
9827 goto err_open;
9828 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009829 }
Jaideep Sharmad305a4a2020-02-27 14:29:04 +05309830
9831 /* assign concurrent capture usecase if record has to caried out from
9832 * actual hardware input source */
9833 if (audio_extn_is_concurrent_capture_enabled() &&
9834 !audio_is_virtual_input_source(in->source)) {
Samyak Jainc37062f2019-04-25 18:41:06 +05309835 /* Acquire lock to avoid two concurrent use cases initialized to
9836 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +08009837
Samyak Jainc37062f2019-04-25 18:41:06 +05309838 if (in->usecase == USECASE_AUDIO_RECORD) {
9839 pthread_mutex_lock(&adev->lock);
9840 if (!(adev->pcm_record_uc_state)) {
9841 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
9842 adev->pcm_record_uc_state = 1;
9843 pthread_mutex_unlock(&adev->lock);
9844 } else {
9845 pthread_mutex_unlock(&adev->lock);
9846 /* Assign compress record use case for second record */
9847 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
9848 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
9849 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
9850 if (audio_extn_cin_applicable_stream(in)) {
9851 in->sample_rate = config->sample_rate;
Deeraj Soman14230922019-01-30 16:39:30 +05309852 ret = audio_extn_cin_configure_input_stream(in, config);
Samyak Jainc37062f2019-04-25 18:41:06 +05309853 if (ret)
9854 goto err_open;
9855 }
9856 }
9857 }
kunleiz28c73e72019-03-27 17:24:04 +08009858 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009859 }
Ramjee Singh82fd0c12019-08-21 16:31:33 +05309860 if (audio_extn_ssr_get_stream() != in)
9861 in->config.channels = channel_count;
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009862
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009863 in->sample_rate = in->config.rate;
9864
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309865 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
9866 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009867 &in->device_list, flags, in->format,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009868 in->sample_rate, in->bit_width,
9869 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05309870 register_format(in->format, in->supported_formats);
9871 register_channel_mask(in->channel_mask, in->supported_channel_masks);
9872 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309873
Dechen Chai22768452021-07-30 09:29:16 +05309874#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -08009875 in->error_log = error_log_create(
9876 ERROR_LOG_ENTRIES,
9877 1000000000 /* aggregate consecutive identical errors within one second */);
Dechen Chai22768452021-07-30 09:29:16 +05309878#endif
Aalique Grahame22e49102018-12-18 14:23:57 -08009879
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009880 /* This stream could be for sound trigger lab,
9881 get sound trigger pcm if present */
9882 audio_extn_sound_trigger_check_and_get_session(in);
9883
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309884 lock_input_stream(in);
9885 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
9886 pthread_mutex_lock(&adev->lock);
9887 in->card_status = adev->card_status;
9888 pthread_mutex_unlock(&adev->lock);
9889 pthread_mutex_unlock(&in->lock);
9890
Aalique Grahame22e49102018-12-18 14:23:57 -08009891 stream_app_type_cfg_init(&in->app_type_cfg);
9892
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009893 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -08009894
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009895 ret = io_streams_map_insert(adev, &in->stream.common,
9896 handle, AUDIO_PATCH_HANDLE_NONE);
9897 if (ret != 0)
9898 goto err_open;
9899
Susan Wang6dd13092021-01-25 10:27:11 -05009900 in->in_ctxt.input = in;
Derek Chenf939fb72018-11-13 13:34:41 -08009901
9902 pthread_mutex_lock(&adev->lock);
Susan Wang6dd13092021-01-25 10:27:11 -05009903 list_add_tail(&adev->active_inputs_list, &in->in_ctxt.list);
Derek Chenf939fb72018-11-13 13:34:41 -08009904 pthread_mutex_unlock(&adev->lock);
9905
Eric Laurent994a6932013-07-17 11:51:42 -07009906 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009907 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009908
9909err_open:
Samyak Jainc37062f2019-04-25 18:41:06 +05309910 if (in->usecase == USECASE_AUDIO_RECORD) {
9911 pthread_mutex_lock(&adev->lock);
9912 adev->pcm_record_uc_state = 0;
9913 pthread_mutex_unlock(&adev->lock);
9914 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009915 free(in);
9916 *stream_in = NULL;
9917 return ret;
9918}
9919
9920static void adev_close_input_stream(struct audio_hw_device *dev,
9921 struct audio_stream_in *stream)
9922{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009923 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009924 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009925 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309926
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309927 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08009928
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009929 if (in == NULL) {
9930 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
9931 return;
9932 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009933 io_streams_map_remove(adev, in->capture_handle);
9934
Susan Wang6dd13092021-01-25 10:27:11 -05009935 // remove out_ctxt early to prevent the stream
9936 // being opened in a race condition
9937 pthread_mutex_lock(&adev->lock);
9938 list_remove(&in->in_ctxt.list);
9939 pthread_mutex_unlock(&adev->lock);
9940
kunleiz70e57612018-12-28 17:50:23 +08009941 /* must deregister from sndmonitor first to prevent races
9942 * between the callback and close_stream
9943 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309944 audio_extn_snd_mon_unregister_listener(stream);
9945
kunleiz70e57612018-12-28 17:50:23 +08009946 /* Disable echo reference if there are no active input, hfp call
9947 * and sound trigger while closing input stream
9948 */
Eric Laurent637e2d42018-11-15 12:24:31 -08009949 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +08009950 !audio_extn_hfp_is_active(adev) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009951 !audio_extn_sound_trigger_check_ec_ref_enable()) {
9952 struct listnode out_devices;
9953 list_init(&out_devices);
9954 platform_set_echo_reference(adev, false, &out_devices);
9955 } else
kunleiz70e57612018-12-28 17:50:23 +08009956 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05309957
Dechen Chai22768452021-07-30 09:29:16 +05309958#ifndef LINUX_ENABLED
Weiyin Jiang2995f662019-04-17 14:25:12 +08009959 error_log_destroy(in->error_log);
9960 in->error_log = NULL;
Dechen Chai22768452021-07-30 09:29:16 +05309961#endif
Pallavid7c7a272018-01-16 11:22:55 +05309962
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009963 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309964 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009965 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309966 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009967 if (ret != 0)
9968 ALOGE("%s: Compress voip input cannot be closed, error:%d",
9969 __func__, ret);
9970 } else
9971 in_standby(&stream->common);
9972
Weiyin Jiang280ea742020-09-08 20:28:22 +08009973 pthread_mutex_destroy(&in->lock);
9974 pthread_mutex_destroy(&in->pre_lock);
9975
Revathi Uddarajud2634032017-12-07 14:42:34 +05309976 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05309977 if (in->usecase == USECASE_AUDIO_RECORD) {
9978 adev->pcm_record_uc_state = 0;
9979 }
9980
Kunlei Zhang5d5d8d92020-02-26 15:00:59 +08009981 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9982 adev->enable_voicerx = false;
9983 }
9984
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07009985 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009986 audio_extn_ssr_deinit();
9987 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009988
Garmond Leunge2433c32017-09-28 21:51:22 -07009989 if (audio_extn_ffv_get_stream() == in) {
9990 audio_extn_ffv_stream_deinit();
9991 }
9992
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309993 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07009994 audio_extn_compr_cap_format_supported(in->config.format))
9995 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05309996
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05309997 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05309998 audio_extn_cin_free_input_stream_resources(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009999
Mingming Yinfd7607b2016-01-22 12:48:44 -080010000 if (in->is_st_session) {
10001 ALOGV("%s: sound trigger pcm stop lab", __func__);
10002 audio_extn_sound_trigger_stop_lab(in);
10003 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010004 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +053010005 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010006 return;
10007}
10008
Aalique Grahame22e49102018-12-18 14:23:57 -080010009/* verifies input and output devices and their capabilities.
10010 *
10011 * This verification is required when enabling extended bit-depth or
10012 * sampling rates, as not all qcom products support it.
10013 *
10014 * Suitable for calling only on initialization such as adev_open().
10015 * It fills the audio_device use_case_table[] array.
10016 *
10017 * Has a side-effect that it needs to configure audio routing / devices
10018 * in order to power up the devices and read the device parameters.
10019 * It does not acquire any hw device lock. Should restore the devices
10020 * back to "normal state" upon completion.
10021 */
10022static int adev_verify_devices(struct audio_device *adev)
10023{
10024 /* enumeration is a bit difficult because one really wants to pull
10025 * the use_case, device id, etc from the hidden pcm_device_table[].
10026 * In this case there are the following use cases and device ids.
10027 *
10028 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
10029 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
10030 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
10031 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
10032 * [USECASE_AUDIO_RECORD] = {0, 0},
10033 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
10034 * [USECASE_VOICE_CALL] = {2, 2},
10035 *
10036 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
10037 * USECASE_VOICE_CALL omitted, but possible for either input or output.
10038 */
10039
10040 /* should be the usecases enabled in adev_open_input_stream() */
10041 static const int test_in_usecases[] = {
10042 USECASE_AUDIO_RECORD,
10043 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
10044 };
10045 /* should be the usecases enabled in adev_open_output_stream()*/
10046 static const int test_out_usecases[] = {
10047 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
10048 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
10049 };
10050 static const usecase_type_t usecase_type_by_dir[] = {
10051 PCM_PLAYBACK,
10052 PCM_CAPTURE,
10053 };
10054 static const unsigned flags_by_dir[] = {
10055 PCM_OUT,
10056 PCM_IN,
10057 };
10058
10059 size_t i;
10060 unsigned dir;
10061 const unsigned card_id = adev->snd_card;
10062
10063 for (dir = 0; dir < 2; ++dir) {
10064 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
10065 const unsigned flags_dir = flags_by_dir[dir];
10066 const size_t testsize =
10067 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
10068 const int *testcases =
10069 dir ? test_in_usecases : test_out_usecases;
10070 const audio_devices_t audio_device =
10071 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
10072
10073 for (i = 0; i < testsize; ++i) {
10074 const audio_usecase_t audio_usecase = testcases[i];
10075 int device_id;
10076 struct pcm_params **pparams;
10077 struct stream_out out;
10078 struct stream_in in;
10079 struct audio_usecase uc_info;
10080 int retval;
10081
10082 pparams = &adev->use_case_table[audio_usecase];
10083 pcm_params_free(*pparams); /* can accept null input */
10084 *pparams = NULL;
10085
10086 /* find the device ID for the use case (signed, for error) */
10087 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
10088 if (device_id < 0)
10089 continue;
10090
10091 /* prepare structures for device probing */
10092 memset(&uc_info, 0, sizeof(uc_info));
10093 uc_info.id = audio_usecase;
10094 uc_info.type = usecase_type;
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010095 list_init(&uc_info.device_list);
Aalique Grahame22e49102018-12-18 14:23:57 -080010096 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -080010097 memset(&in, 0, sizeof(in));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010098 list_init(&in.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010099 update_device_list(&in.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -080010100 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
10101 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -080010102 }
10103 memset(&out, 0, sizeof(out));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010104 list_init(&out.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010105 update_device_list(&out.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -080010106 uc_info.stream.out = &out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010107 update_device_list(&uc_info.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -080010108 uc_info.in_snd_device = SND_DEVICE_NONE;
10109 uc_info.out_snd_device = SND_DEVICE_NONE;
10110 list_add_tail(&adev->usecase_list, &uc_info.list);
10111
10112 /* select device - similar to start_(in/out)put_stream() */
10113 retval = select_devices(adev, audio_usecase);
10114 if (retval >= 0) {
10115 *pparams = pcm_params_get(card_id, device_id, flags_dir);
10116#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -070010117 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -080010118 if (*pparams) {
10119 ALOGV("%s: (%s) card %d device %d", __func__,
10120 dir ? "input" : "output", card_id, device_id);
10121 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
10122 } else {
10123 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
10124 }
10125#endif
10126 }
10127
10128 /* deselect device - similar to stop_(in/out)put_stream() */
10129 /* 1. Get and set stream specific mixer controls */
10130 retval = disable_audio_route(adev, &uc_info);
10131 /* 2. Disable the rx device */
10132 retval = disable_snd_device(adev,
10133 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
10134 list_remove(&uc_info.list);
10135 }
10136 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010137 return 0;
10138}
10139
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010140int update_patch(unsigned int num_sources,
10141 const struct audio_port_config *sources,
10142 unsigned int num_sinks,
10143 const struct audio_port_config *sinks,
10144 audio_patch_handle_t handle,
10145 struct audio_patch_info *p_info,
10146 patch_type_t patch_type, bool new_patch)
10147{
Aniket Kumar Latad13758f2020-08-06 15:11:36 -070010148 ALOGV("%s: enter", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010149
10150 if (p_info == NULL) {
10151 ALOGE("%s: Invalid patch pointer", __func__);
10152 return -EINVAL;
10153 }
10154
10155 if (new_patch) {
10156 p_info->patch = (struct audio_patch *) calloc(1, sizeof(struct audio_patch));
10157 if (p_info->patch == NULL) {
10158 ALOGE("%s: Could not allocate patch", __func__);
10159 return -ENOMEM;
10160 }
10161 }
10162
10163 p_info->patch->id = handle;
10164 p_info->patch->num_sources = num_sources;
10165 p_info->patch->num_sinks = num_sinks;
10166
10167 for (int i = 0; i < num_sources; i++)
10168 p_info->patch->sources[i] = sources[i];
10169 for (int i = 0; i < num_sinks; i++)
10170 p_info->patch->sinks[i] = sinks[i];
10171
10172 p_info->patch_type = patch_type;
10173 return 0;
10174}
10175
10176audio_patch_handle_t generate_patch_handle()
10177{
10178 static audio_patch_handle_t patch_handle = AUDIO_PATCH_HANDLE_NONE;
10179 if (++patch_handle < 0)
10180 patch_handle = AUDIO_PATCH_HANDLE_NONE + 1;
10181 return patch_handle;
10182}
10183
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010184int adev_create_audio_patch(struct audio_hw_device *dev,
10185 unsigned int num_sources,
10186 const struct audio_port_config *sources,
10187 unsigned int num_sinks,
10188 const struct audio_port_config *sinks,
10189 audio_patch_handle_t *handle)
10190{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010191 int ret = 0;
10192 struct audio_device *adev = (struct audio_device *)dev;
10193 struct audio_patch_info *p_info = NULL;
10194 patch_type_t patch_type = PATCH_NONE;
10195 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10196 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
10197 struct audio_stream_info *s_info = NULL;
10198 struct audio_stream *stream = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010199 struct listnode devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010200 audio_devices_t device_type = AUDIO_DEVICE_NONE;
10201 bool new_patch = false;
10202 char addr[AUDIO_DEVICE_MAX_ADDRESS_LEN];
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010203
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010204 ALOGD("%s: enter: num sources %d, num_sinks %d, handle %d", __func__,
10205 num_sources, num_sinks, *handle);
10206
10207 if (num_sources == 0 || num_sources > AUDIO_PATCH_PORTS_MAX ||
10208 num_sinks == 0 || num_sinks > AUDIO_PATCH_PORTS_MAX) {
10209 ALOGE("%s: Invalid patch arguments", __func__);
10210 ret = -EINVAL;
10211 goto done;
10212 }
10213
10214 if (num_sources > 1) {
10215 ALOGE("%s: Multiple sources are not supported", __func__);
10216 ret = -EINVAL;
10217 goto done;
10218 }
10219
10220 if (sources == NULL || sinks == NULL) {
10221 ALOGE("%s: Invalid sources or sinks port config", __func__);
10222 ret = -EINVAL;
10223 goto done;
10224 }
10225
10226 ALOGV("%s: source role %d, source type %d", __func__,
10227 sources[0].type, sources[0].role);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010228 list_init(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010229
10230 // Populate source/sink information and fetch stream info
10231 switch (sources[0].type) {
10232 case AUDIO_PORT_TYPE_DEVICE: // Patch for audio capture or loopback
10233 device_type = sources[0].ext.device.type;
10234 strlcpy(&addr[0], &sources[0].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010235 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010236 if (sinks[0].type == AUDIO_PORT_TYPE_MIX) {
10237 patch_type = PATCH_CAPTURE;
10238 io_handle = sinks[0].ext.mix.handle;
10239 input_source = sinks[0].ext.mix.usecase.source;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010240 ALOGD("%s: Capture patch from device %x to mix %d",
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010241 __func__, device_type, io_handle);
10242 } else {
10243 // Device to device patch is not implemented.
10244 // This space will need changes if audio HAL
10245 // handles device to device patches in the future.
10246 patch_type = PATCH_DEVICE_LOOPBACK;
10247 }
10248 break;
10249 case AUDIO_PORT_TYPE_MIX: // Patch for audio playback
10250 io_handle = sources[0].ext.mix.handle;
10251 for (int i = 0; i < num_sinks; i++) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010252 device_type = sinks[i].ext.device.type;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010253 strlcpy(&addr[0], &sinks[i].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010254 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010255 }
10256 patch_type = PATCH_PLAYBACK;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010257 ALOGD("%s: Playback patch from mix handle %d to device %x",
10258 __func__, io_handle, get_device_types(&devices));
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010259 break;
10260 case AUDIO_PORT_TYPE_SESSION:
10261 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010262 ALOGE("%s: Unsupported source type %d", __func__, sources[0].type);
10263 ret = -EINVAL;
10264 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010265 }
10266
10267 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010268
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010269 // Generate patch info and update patch
10270 if (*handle == AUDIO_PATCH_HANDLE_NONE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010271 *handle = generate_patch_handle();
10272 p_info = (struct audio_patch_info *)
10273 calloc(1, sizeof(struct audio_patch_info));
10274 if (p_info == NULL) {
10275 ALOGE("%s: Failed to allocate memory", __func__);
10276 pthread_mutex_unlock(&adev->lock);
10277 ret = -ENOMEM;
10278 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010279 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010280 new_patch = true;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010281 } else {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010282 p_info = fetch_patch_info_l(adev, *handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010283 if (p_info == NULL) {
10284 ALOGE("%s: Unable to fetch patch for received patch handle %d",
10285 __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010286 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010287 ret = -EINVAL;
10288 goto done;
10289 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010290 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010291 update_patch(num_sources, sources, num_sinks, sinks,
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010292 *handle, p_info, patch_type, new_patch);
10293
10294 // Fetch stream info of associated mix for playback or capture patches
10295 if (p_info->patch_type == PATCH_PLAYBACK ||
10296 p_info->patch_type == PATCH_CAPTURE) {
10297 s_info = hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10298 if (s_info == NULL) {
10299 ALOGE("%s: Failed to obtain stream info", __func__);
10300 if (new_patch)
10301 free(p_info);
10302 pthread_mutex_unlock(&adev->lock);
10303 ret = -EINVAL;
10304 goto done;
10305 }
10306 ALOGV("%s: Fetched stream info with io_handle %d", __func__, io_handle);
10307 s_info->patch_handle = *handle;
10308 stream = s_info->stream;
10309 }
10310 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010311
10312 // Update routing for stream
10313 if (stream != NULL) {
10314 if (p_info->patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010315 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010316 else if (p_info->patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010317 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010318 if (ret < 0) {
10319 pthread_mutex_lock(&adev->lock);
10320 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10321 if (new_patch)
10322 free(p_info);
10323 pthread_mutex_unlock(&adev->lock);
10324 ALOGE("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10325 goto done;
10326 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010327 }
10328
10329 // Add new patch to patch map
10330 if (!ret && new_patch) {
10331 pthread_mutex_lock(&adev->lock);
10332 hashmapPut(adev->patch_map, (void *) (intptr_t) *handle, (void *) p_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010333 ALOGD("%s: Added a new patch with handle %d", __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010334 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010335 }
10336
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010337done:
10338 audio_extn_hw_loopback_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010339 num_sources,
10340 sources,
10341 num_sinks,
10342 sinks,
10343 handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010344 audio_extn_auto_hal_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010345 num_sources,
10346 sources,
10347 num_sinks,
10348 sinks,
10349 handle);
10350 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010351}
10352
10353int adev_release_audio_patch(struct audio_hw_device *dev,
10354 audio_patch_handle_t handle)
10355{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010356 struct audio_device *adev = (struct audio_device *) dev;
10357 int ret = 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010358 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010359 struct audio_stream *stream = NULL;
Derek Chenf939fb72018-11-13 13:34:41 -080010360
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010361 if (handle == AUDIO_PATCH_HANDLE_NONE) {
10362 ALOGE("%s: Invalid patch handle %d", __func__, handle);
10363 ret = -EINVAL;
10364 goto done;
10365 }
10366
10367 ALOGD("%s: Remove patch with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010368 pthread_mutex_lock(&adev->lock);
10369 struct audio_patch_info *p_info = fetch_patch_info_l(adev, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010370 if (p_info == NULL) {
10371 ALOGE("%s: Patch info not found with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010372 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010373 ret = -EINVAL;
10374 goto done;
10375 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010376 struct audio_patch *patch = p_info->patch;
10377 if (patch == NULL) {
10378 ALOGE("%s: Patch not found for handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010379 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010380 ret = -EINVAL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010381 goto done;
10382 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010383 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10384 switch (patch->sources[0].type) {
10385 case AUDIO_PORT_TYPE_MIX:
10386 io_handle = patch->sources[0].ext.mix.handle;
10387 break;
10388 case AUDIO_PORT_TYPE_DEVICE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010389 if (p_info->patch_type == PATCH_CAPTURE)
10390 io_handle = patch->sinks[0].ext.mix.handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010391 break;
10392 case AUDIO_PORT_TYPE_SESSION:
10393 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010394 pthread_mutex_unlock(&adev->lock);
10395 ret = -EINVAL;
10396 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010397 }
10398
10399 // Remove patch and reset patch handle in stream info
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010400 patch_type_t patch_type = p_info->patch_type;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010401 patch_map_remove_l(adev, handle);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010402 if (patch_type == PATCH_PLAYBACK ||
10403 patch_type == PATCH_CAPTURE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010404 struct audio_stream_info *s_info =
10405 hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10406 if (s_info == NULL) {
10407 ALOGE("%s: stream for io_handle %d is not available", __func__, io_handle);
10408 pthread_mutex_unlock(&adev->lock);
10409 goto done;
10410 }
10411 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10412 stream = s_info->stream;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010413 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010414 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010415
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010416 if (stream != NULL) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010417 struct listnode devices;
10418 list_init(&devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010419 if (patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010420 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010421 else if (patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010422 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010423 }
10424
10425 if (ret < 0)
10426 ALOGW("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10427
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010428done:
10429 audio_extn_hw_loopback_release_audio_patch(dev, handle);
10430 audio_extn_auto_hal_release_audio_patch(dev, handle);
10431
10432 ALOGV("%s: Successfully released patch %d", __func__, handle);
Derek Chenf939fb72018-11-13 13:34:41 -080010433 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010434}
10435
10436int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
10437{
Derek Chenf13dd492018-11-13 14:53:51 -080010438 int ret = 0;
10439
10440 ret = audio_extn_hw_loopback_get_audio_port(dev, config);
10441 ret |= audio_extn_auto_hal_get_audio_port(dev, config);
10442 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010443}
10444
10445int adev_set_audio_port_config(struct audio_hw_device *dev,
10446 const struct audio_port_config *config)
10447{
Derek Chenf13dd492018-11-13 14:53:51 -080010448 int ret = 0;
10449
10450 ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
10451 ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
10452 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010453}
10454
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -070010455static int adev_dump(const audio_hw_device_t *device __unused,
10456 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010457{
10458 return 0;
10459}
10460
10461static int adev_close(hw_device_t *device)
10462{
Aalique Grahame22e49102018-12-18 14:23:57 -080010463 size_t i;
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010464 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -070010465
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010466 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -070010467 return 0;
10468
10469 pthread_mutex_lock(&adev_init_lock);
10470
10471 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +053010472 if (audio_extn_spkr_prot_is_enabled())
10473 audio_extn_spkr_prot_deinit();
Daniel Hillenbrand17873952013-05-23 10:10:00 +053010474 if (amplifier_close() != 0)
10475 ALOGE("Amplifier close failed");
Jaideep Sharmaa2b49672019-09-10 20:37:03 +053010476 audio_extn_battery_properties_listener_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010477 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010478 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -080010479 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010480 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -080010481 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010482 audio_extn_utils_release_streams_cfg_lists(
10483 &adev->streams_output_cfg_list,
10484 &adev->streams_input_cfg_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010485 if (audio_extn_qap_is_enabled())
10486 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010487 if (audio_extn_qaf_is_enabled())
10488 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -070010489 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +080010490 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -070010491 free(adev->snd_dev_ref_cnt);
10492 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010493 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
10494 pcm_params_free(adev->use_case_table[i]);
10495 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010496 if (adev->adm_deinit)
10497 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010498 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010499 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010500 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010501 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010502 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010503 if (adev->device_cfg_params) {
10504 free(adev->device_cfg_params);
10505 adev->device_cfg_params = NULL;
10506 }
Derek Chend2530072014-11-24 12:39:14 -080010507 if(adev->ext_hw_plugin)
10508 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -080010509 audio_extn_auto_hal_deinit();
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010510 free_map(adev->patch_map);
10511 free_map(adev->io_streams_map);
Kiran Kandi910e1862013-10-29 13:29:42 -070010512 free(device);
10513 adev = NULL;
10514 }
10515 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +053010516 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010517 return 0;
10518}
10519
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010520/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
10521 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
10522 * just that it _might_ work.
10523 */
10524static int period_size_is_plausible_for_low_latency(int period_size)
10525{
10526 switch (period_size) {
10527 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -070010528 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010529 case 240:
10530 case 320:
10531 case 480:
10532 return 1;
10533 default:
10534 return 0;
10535 }
10536}
10537
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010538static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
10539{
10540 bool is_snd_card_status = false;
10541 bool is_ext_device_status = false;
10542 char value[32];
10543 int card = -1;
10544 card_status_t status;
10545
10546 if (cookie != adev || !parms)
10547 return;
10548
10549 if (!parse_snd_card_status(parms, &card, &status)) {
10550 is_snd_card_status = true;
10551 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
10552 is_ext_device_status = true;
10553 } else {
10554 // not a valid event
10555 return;
10556 }
10557
10558 pthread_mutex_lock(&adev->lock);
10559 if (card == adev->snd_card || is_ext_device_status) {
10560 if (is_snd_card_status && adev->card_status != status) {
Jaideep Sharmacb402512020-09-24 17:51:07 +053010561 ALOGD("%s card_status %d", __func__, status);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010562 adev->card_status = status;
10563 platform_snd_card_update(adev->platform, status);
10564 audio_extn_fm_set_parameters(adev, parms);
Derek Chend6f371d2019-03-01 13:45:58 -080010565 audio_extn_auto_hal_set_parameters(adev, parms);
Zhou Song4f43e352019-07-02 00:32:23 +080010566 if (status == CARD_STATUS_OFFLINE)
10567 audio_extn_sco_reset_configuration();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010568 } else if (is_ext_device_status) {
10569 platform_set_parameters(adev->platform, parms);
10570 }
10571 }
10572 pthread_mutex_unlock(&adev->lock);
10573 return;
10574}
10575
Weiyin Jiang280ea742020-09-08 20:28:22 +080010576/* adev lock held */
10577int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010578{
10579 struct audio_usecase *uc_info;
Zhou Song407e5aa2020-12-27 19:13:04 +080010580 struct audio_usecase *usecase;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010581 struct listnode devices;
Zhou Song407e5aa2020-12-27 19:13:04 +080010582 struct listnode *node;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010583
10584 uc_info = get_usecase_from_list(adev, out->usecase);
10585 if (uc_info == NULL) {
10586 ALOGE("%s: Could not find the usecase (%d) in the list",
10587 __func__, out->usecase);
10588 return -EINVAL;
10589 }
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010590 list_init(&devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010591
Zhou Songbaddf9f2020-11-20 13:57:39 +080010592 ALOGD("%s: enter: usecase(%d: %s), a2dp muted %d", __func__,
10593 out->usecase, use_case_table[out->usecase], out->a2dp_muted);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010594
10595 if (restore) {
Weiyin Jiang280ea742020-09-08 20:28:22 +080010596 pthread_mutex_lock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010597 // restore A2DP device for active usecases and unmute if required
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010598 if (is_a2dp_out_device_type(&out->device_list)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010599 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
Zhou Songe5225132019-09-26 15:33:36 +080010600 if (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)
10601 select_devices(adev, uc_info->id);
Zhou Songbaddf9f2020-11-20 13:57:39 +080010602
10603 if (is_offload_usecase(out->usecase)) {
10604 if (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)
Weiyin Jiang280ea742020-09-08 20:28:22 +080010605 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
Zhou Songbaddf9f2020-11-20 13:57:39 +080010606 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
10607 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
10608 } else {
10609 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010610 }
Zhou Songbaddf9f2020-11-20 13:57:39 +080010611 out->a2dp_muted = false;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010612 }
Weiyin Jiang280ea742020-09-08 20:28:22 +080010613 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010614 } else {
Weiyin Jiang280ea742020-09-08 20:28:22 +080010615 pthread_mutex_lock(&out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +080010616 // mute stream and switch to speaker if suspended
10617 if (!out->a2dp_muted && !out->standby) {
Zhou Songbaddf9f2020-11-20 13:57:39 +080010618 assign_devices(&devices, &out->device_list);
10619 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Zhou Song407e5aa2020-12-27 19:13:04 +080010620 list_for_each(node, &adev->usecase_list) {
10621 usecase = node_to_item(node, struct audio_usecase, list);
Zhou Songe63b6fe2021-04-15 13:54:46 +080010622 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
10623 !is_a2dp_out_device_type(&usecase->stream.out->device_list) &&
Zhou Songcf77af02021-05-14 18:21:14 +080010624 !is_sco_out_device_type(&usecase->stream.out->device_list) &&
Zhou Songe63b6fe2021-04-15 13:54:46 +080010625 platform_check_backends_match(SND_DEVICE_OUT_SPEAKER,
10626 usecase->out_snd_device)) {
Zhou Song407e5aa2020-12-27 19:13:04 +080010627 assign_devices(&out->device_list, &usecase->stream.out->device_list);
10628 break;
10629 }
10630 }
Zhou Songcf77af02021-05-14 18:21:14 +080010631 if ((is_a2dp_out_device_type(&devices) && list_length(&devices) == 1) ||
10632 (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)) {
Zhou Song8edbbdb2021-01-14 16:48:03 +080010633 out->a2dp_muted = true;
10634 if (is_offload_usecase(out->usecase)) {
10635 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10636 compress_pause(out->compr);
10637 out_set_compr_volume(&out->stream, (float)0, (float)0);
Zhou Song8edbbdb2021-01-14 16:48:03 +080010638 } else {
Weiyin Jiang906db3c2021-03-02 13:17:04 +080010639 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
10640 out_set_voip_volume(&out->stream, (float)0, (float)0);
10641 else
10642 out_set_pcm_volume(&out->stream, (float)0, (float)0);
10643
Zhou Song8edbbdb2021-01-14 16:48:03 +080010644 /* wait for stale pcm drained before switching to speaker */
10645 uint32_t latency =
10646 (out->config.period_count * out->config.period_size * 1000) /
10647 (out->config.rate);
10648 usleep(latency * 1000);
10649 }
Zhou Songbaddf9f2020-11-20 13:57:39 +080010650 }
10651 select_devices(adev, out->usecase);
Zhou Song8edbbdb2021-01-14 16:48:03 +080010652 ALOGD("%s: switched to device:%s and stream muted:%d", __func__,
10653 platform_get_snd_device_name(uc_info->out_snd_device), out->a2dp_muted);
Zhou Songbaddf9f2020-11-20 13:57:39 +080010654 if (is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010655 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10656 compress_resume(out->compr);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010657 }
Zhou Songbaddf9f2020-11-20 13:57:39 +080010658 assign_devices(&out->device_list, &devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010659 }
Weiyin Jiang280ea742020-09-08 20:28:22 +080010660 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010661 }
10662 ALOGV("%s: exit", __func__);
10663 return 0;
10664}
10665
Haynes Mathew George01156f92018-04-13 15:29:54 -070010666void adev_on_battery_status_changed(bool charging)
10667{
10668 pthread_mutex_lock(&adev->lock);
10669 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
10670 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +080010671 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -070010672 pthread_mutex_unlock(&adev->lock);
10673}
10674
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010675static int adev_open(const hw_module_t *module, const char *name,
10676 hw_device_t **device)
10677{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010678 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -080010679 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010680 char mixer_ctl_name[128] = {0};
10681 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010682
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080010683 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010684 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
10685
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010686 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -070010687 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010688 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -070010689 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010690 ALOGD("%s: returning existing instance of adev", __func__);
10691 ALOGD("%s: exit", __func__);
10692 pthread_mutex_unlock(&adev_init_lock);
10693 return 0;
10694 }
10695
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010696 adev = calloc(1, sizeof(struct audio_device));
10697
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -070010698 if (!adev) {
10699 pthread_mutex_unlock(&adev_init_lock);
10700 return -ENOMEM;
10701 }
10702
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -070010703 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
10704
Weiyin Jiange6ce6312019-01-28 18:28:22 +080010705 // register audio ext hidl at the earliest
10706 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053010707#ifdef DYNAMIC_LOG_ENABLED
10708 register_for_dynamic_logging("hal");
10709#endif
10710
Derek Chenf939fb72018-11-13 13:34:41 -080010711 /* default audio HAL major version */
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010712 uint32_t maj_version = 3;
Derek Chenf939fb72018-11-13 13:34:41 -080010713 if(property_get("vendor.audio.hal.maj.version", value, NULL))
10714 maj_version = atoi(value);
10715
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010716 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -080010717 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010718 adev->device.common.module = (struct hw_module_t *)module;
10719 adev->device.common.close = adev_close;
10720
10721 adev->device.init_check = adev_init_check;
10722 adev->device.set_voice_volume = adev_set_voice_volume;
10723 adev->device.set_master_volume = adev_set_master_volume;
10724 adev->device.get_master_volume = adev_get_master_volume;
10725 adev->device.set_master_mute = adev_set_master_mute;
10726 adev->device.get_master_mute = adev_get_master_mute;
10727 adev->device.set_mode = adev_set_mode;
10728 adev->device.set_mic_mute = adev_set_mic_mute;
10729 adev->device.get_mic_mute = adev_get_mic_mute;
10730 adev->device.set_parameters = adev_set_parameters;
10731 adev->device.get_parameters = adev_get_parameters;
10732 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
10733 adev->device.open_output_stream = adev_open_output_stream;
10734 adev->device.close_output_stream = adev_close_output_stream;
10735 adev->device.open_input_stream = adev_open_input_stream;
10736 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010737 adev->device.create_audio_patch = adev_create_audio_patch;
10738 adev->device.release_audio_patch = adev_release_audio_patch;
10739 adev->device.get_audio_port = adev_get_audio_port;
10740 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010741 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +053010742 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010743
10744 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010745 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -080010746 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010747 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010748 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -080010749 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -070010750 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +053010751 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -070010752 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -070010753 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -070010754 /* Init audio and voice feature */
10755 audio_extn_feature_init();
10756 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070010757 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -080010758 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -080010759 list_init(&adev->active_inputs_list);
10760 list_init(&adev->active_outputs_list);
Rahul Sharma99770982019-03-06 17:05:26 +053010761 list_init(&adev->audio_patch_record_list);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010762 adev->io_streams_map = hashmapCreate(AUDIO_IO_PORTS_MAX, audio_extn_utils_hash_fn,
10763 audio_extn_utils_hash_eq);
10764 if (!adev->io_streams_map) {
10765 ALOGE("%s: Could not create io streams map", __func__);
10766 ret = -ENOMEM;
10767 goto adev_open_err;
10768 }
10769 adev->patch_map = hashmapCreate(AUDIO_PATCH_PORTS_MAX, audio_extn_utils_hash_fn,
10770 audio_extn_utils_hash_eq);
10771 if (!adev->patch_map) {
10772 ALOGE("%s: Could not create audio patch map", __func__);
10773 ret = -ENOMEM;
10774 goto adev_open_err;
10775 }
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -080010776 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -070010777 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +053010778 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +053010779 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +053010780 adev->perf_lock_opts[0] = 0x101;
10781 adev->perf_lock_opts[1] = 0x20E;
10782 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010783 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -070010784 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010785 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010786 adev->adm_routing_changed = false;
Revathi Uddarajub26e3932020-06-10 14:51:02 +053010787 adev->a2dp_started = false;
Zhou Song503196b2021-07-23 17:31:05 +080010788 adev->ha_proxy_enable = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +053010789
Zhou Song68ebc352019-12-05 17:11:15 +080010790 audio_extn_perf_lock_init();
10791
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010792 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -070010793 adev->platform = platform_init(adev);
10794 if (!adev->platform) {
Eric Laurentb23d5282013-05-14 15:27:20 -070010795 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010796 ret = -EINVAL;
10797 goto adev_open_err;
Eric Laurentb23d5282013-05-14 15:27:20 -070010798 }
Eric Laurentc4aef752013-09-12 17:45:53 -070010799
Aalique Grahame22e49102018-12-18 14:23:57 -080010800 adev->extspk = audio_extn_extspk_init(adev);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010801 if (audio_extn_qap_is_enabled()) {
10802 ret = audio_extn_qap_init(adev);
10803 if (ret < 0) {
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010804 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010805 goto adev_open_err;
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010806 }
10807 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
10808 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
10809 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010810
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010811 if (audio_extn_qaf_is_enabled()) {
10812 ret = audio_extn_qaf_init(adev);
10813 if (ret < 0) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010814 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010815 goto adev_open_err;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010816 }
10817
10818 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
10819 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
10820 }
10821
Derek Chenae7b0342019-02-08 15:17:04 -080010822 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -080010823 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
10824
Eric Laurentc4aef752013-09-12 17:45:53 -070010825 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
10826 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
10827 if (adev->visualizer_lib == NULL) {
10828 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
10829 } else {
10830 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
10831 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010832 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010833 "visualizer_hal_start_output");
10834 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010835 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010836 "visualizer_hal_stop_output");
10837 }
10838 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +053010839 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010840 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -080010841 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +080010842 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010843 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010844 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -070010845
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010846 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
10847 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
10848 if (adev->offload_effects_lib == NULL) {
10849 ALOGE("%s: DLOPEN failed for %s", __func__,
10850 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10851 } else {
10852 ALOGV("%s: DLOPEN successful for %s", __func__,
10853 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10854 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +053010855 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010856 "offload_effects_bundle_hal_start_output");
10857 adev->offload_effects_stop_output =
10858 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
10859 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080010860 adev->offload_effects_set_hpx_state =
10861 (int (*)(bool))dlsym(adev->offload_effects_lib,
10862 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +053010863 adev->offload_effects_get_parameters =
10864 (void (*)(struct str_parms *, struct str_parms *))
10865 dlsym(adev->offload_effects_lib,
10866 "offload_effects_bundle_get_parameters");
10867 adev->offload_effects_set_parameters =
10868 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
10869 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010870 }
10871 }
10872
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010873 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
10874 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
10875 if (adev->adm_lib == NULL) {
10876 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
10877 } else {
10878 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
10879 adev->adm_init = (adm_init_t)
10880 dlsym(adev->adm_lib, "adm_init");
10881 adev->adm_deinit = (adm_deinit_t)
10882 dlsym(adev->adm_lib, "adm_deinit");
10883 adev->adm_register_input_stream = (adm_register_input_stream_t)
10884 dlsym(adev->adm_lib, "adm_register_input_stream");
10885 adev->adm_register_output_stream = (adm_register_output_stream_t)
10886 dlsym(adev->adm_lib, "adm_register_output_stream");
10887 adev->adm_deregister_stream = (adm_deregister_stream_t)
10888 dlsym(adev->adm_lib, "adm_deregister_stream");
10889 adev->adm_request_focus = (adm_request_focus_t)
10890 dlsym(adev->adm_lib, "adm_request_focus");
10891 adev->adm_abandon_focus = (adm_abandon_focus_t)
10892 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010893 adev->adm_set_config = (adm_set_config_t)
10894 dlsym(adev->adm_lib, "adm_set_config");
10895 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
10896 dlsym(adev->adm_lib, "adm_request_focus_v2");
10897 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
10898 dlsym(adev->adm_lib, "adm_is_noirq_avail");
10899 adev->adm_on_routing_change = (adm_on_routing_change_t)
10900 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010901 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
10902 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010903 }
10904 }
10905
Aalique Grahame22e49102018-12-18 14:23:57 -080010906 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010907 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +080010908 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Kunlei Zhanga3c4cb02021-03-05 16:03:54 +080010909 adev->fluence_nn_usecase_id = USECASE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -080010910 //initialize this to false for now,
10911 //this will be set to true through set param
10912 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010913
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -070010914 audio_extn_ds2_enable(adev);
Daniel Hillenbrand17873952013-05-23 10:10:00 +053010915
10916 if (amplifier_open(adev) != 0)
10917 ALOGE("Amplifier initialization failed");
10918
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010919 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -080010920
10921 if (k_enable_extended_precision)
10922 adev_verify_devices(adev);
10923
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010924 adev->dsp_bit_width_enforce_mode =
10925 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010926
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010927 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
10928 &adev->streams_output_cfg_list,
10929 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070010930
Kiran Kandi910e1862013-10-29 13:29:42 -070010931 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010932
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010933 int trial;
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010934 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010935 trial = atoi(value);
10936 if (period_size_is_plausible_for_low_latency(trial)) {
10937 pcm_config_low_latency.period_size = trial;
10938 pcm_config_low_latency.start_threshold = trial / 4;
10939 pcm_config_low_latency.avail_min = trial / 4;
10940 configured_low_latency_capture_period_size = trial;
10941 }
10942 }
ronghuiz93177262021-04-21 19:58:13 +080010943 if (property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010944 trial = atoi(value);
10945 if (period_size_is_plausible_for_low_latency(trial)) {
10946 configured_low_latency_capture_period_size = trial;
10947 }
10948 }
10949
Vignesh Kulothungan7d374312018-02-21 17:12:00 -080010950 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
10951
Eric Laurent4b084132018-10-19 17:33:43 -070010952 adev->camera_orientation = CAMERA_DEFAULT;
10953
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010954 if (property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010955 af_period_multiplier = atoi(value);
10956 if (af_period_multiplier < 0)
10957 af_period_multiplier = 2;
10958 else if (af_period_multiplier > 4)
10959 af_period_multiplier = 4;
10960
10961 ALOGV("new period_multiplier = %d", af_period_multiplier);
10962 }
10963
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010964 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010965
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -070010966 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010967 pthread_mutex_unlock(&adev_init_lock);
10968
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010969 if (adev->adm_init)
10970 adev->adm_data = adev->adm_init();
10971
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010972 qahwi_init(*device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010973 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010974
10975 audio_extn_snd_mon_init();
10976 pthread_mutex_lock(&adev->lock);
10977 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
10978 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -070010979 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
10980 /*
10981 * if the battery state callback happens before charging can be queried,
10982 * it will be guarded with the adev->lock held in the cb function and so
10983 * the callback value will reflect the latest state
10984 */
10985 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010986 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +080010987 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -070010988 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +080010989 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010990 /* Allocate memory for Device config params */
10991 adev->device_cfg_params = (struct audio_device_config_param*)
10992 calloc(platform_get_max_codec_backend(),
10993 sizeof(struct audio_device_config_param));
10994 if (adev->device_cfg_params == NULL)
10995 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010996
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010997 /*
10998 * Check if new PSPD matrix mixer control is supported. If not
10999 * supported, then set flag so that old mixer ctrl is sent while
11000 * sending pspd coefficients on older kernel version. Query mixer
11001 * control for default pcm id and channel value one.
11002 */
11003 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
11004 "AudStr %d ChMixer Weight Ch %d", 0, 1);
11005
11006 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
11007 if (!ctl) {
11008 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
11009 __func__, mixer_ctl_name);
11010 adev->use_old_pspd_mix_ctrl = true;
11011 }
11012
Jaideep Sharma0fa53812020-09-17 09:00:11 +053011013 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011014 return 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011015
11016adev_open_err:
11017 free_map(adev->patch_map);
11018 free_map(adev->io_streams_map);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080011019 free(adev->snd_dev_ref_cnt);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070011020 pthread_mutex_destroy(&adev->lock);
11021 free(adev);
11022 adev = NULL;
11023 *device = NULL;
11024 pthread_mutex_unlock(&adev_init_lock);
11025 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011026}
11027
11028static struct hw_module_methods_t hal_module_methods = {
11029 .open = adev_open,
11030};
11031
11032struct audio_module HAL_MODULE_INFO_SYM = {
11033 .common = {
11034 .tag = HARDWARE_MODULE_TAG,
11035 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
11036 .hal_api_version = HARDWARE_HAL_API_VERSION,
11037 .id = AUDIO_HARDWARE_MODULE_ID,
11038 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -080011039 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011040 .methods = &hal_module_methods,
11041 },
11042};