blob: 9664b7e813c4132dcd38e0815dd280ab2aee29cf [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Ramu Gottipatifa5be522021-12-28 19:18:21 +05302 * Copyright (c) 2013-2022, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070039#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041/*#define VERY_VERY_VERBOSE_LOGGING*/
42#ifdef VERY_VERY_VERBOSE_LOGGING
43#define ALOGVV ALOGV
44#else
45#define ALOGVV(a...) do { } while(0)
46#endif
George Gao3018ede2019-10-23 13:23:00 -070047#include <limits.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080048#include <errno.h>
49#include <pthread.h>
50#include <stdint.h>
51#include <sys/time.h>
52#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070054#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include <sys/resource.h>
56#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
Aalique Grahame22e49102018-12-18 14:23:57 -080058#include <log/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070059#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080060#include <cutils/str_parms.h>
61#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062#include <cutils/atomic.h>
63#include <cutils/sched_policy.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070064#include <hardware/audio_effect.h>
Haynes Mathew George484e8d22017-07-31 18:55:17 -070065#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070066#include <system/thread_defs.h>
Haynes Mathew George16081042017-05-31 17:16:49 -070067#include <tinyalsa/asoundlib.h>
Andy Hunga1f48fa2019-07-01 18:14:53 -070068#include <utils/Timers.h> // systemTime
Eric Laurentb23d5282013-05-14 15:27:20 -070069#include <audio_effects/effect_aec.h>
70#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053071#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080072#include "audio_hw.h"
Wei Wangf7ca6c92017-11-21 14:51:20 -080073#include "audio_perf.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070074#include "platform_api.h"
75#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070076#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080077#include "voice_extn.h"
Ashish Jaind5694242017-09-05 20:09:06 +053078#include "ip_hdlr_intf.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080079
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070080#include "sound/compress_params.h"
Xiaojun Sang782e5b12020-06-29 21:13:06 +080081
82#ifdef AUDIO_GKI_ENABLED
83#include "sound/audio_compressed_formats.h"
84#endif
85
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080086#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080087
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053088#ifdef DYNAMIC_LOG_ENABLED
89#include <log_xml_parser.h>
90#define LOG_MASK HAL_MOD_FILE_AUDIO_HW
91#include <log_utils.h>
92#endif
93
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070094#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053095/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
96#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070097#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Vikram Panduranga93f080e2017-06-07 18:16:14 -070098#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Arun Mirpuri5d170872019-03-26 13:21:31 -070099#define MMAP_PLAYBACK_VOLUME_MAX 0x2000
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530100#define PCM_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530101#define DSD_VOLUME_MIN_DB (-110)
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700102#define INVALID_OUT_VOLUME -1
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700103#define AUDIO_IO_PORTS_MAX 32
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700104
Zhou Songbaddf9f2020-11-20 13:57:39 +0800105#define PLAYBACK_GAIN_MAX 1.0f
Aalique Grahame22e49102018-12-18 14:23:57 -0800106#define RECORD_GAIN_MIN 0.0f
107#define RECORD_GAIN_MAX 1.0f
108#define RECORD_VOLUME_CTL_MAX 0x2000
109
110/* treat as unsigned Q1.13 */
111#define APP_TYPE_GAIN_DEFAULT 0x2000
112
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700113#define PROXY_OPEN_RETRY_COUNT 100
114#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800115
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800116#define GET_USECASE_AUDIO_PLAYBACK_PRIMARY(db) \
117 (db)? USECASE_AUDIO_PLAYBACK_DEEP_BUFFER : \
118 USECASE_AUDIO_PLAYBACK_LOW_LATENCY
119#define GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(db) \
120 (db)? pcm_config_deep_buffer : pcm_config_low_latency
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800121
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700122#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700123#define DEFAULT_VOIP_BUF_DURATION_MS 20
124#define DEFAULT_VOIP_BIT_DEPTH_BYTE sizeof(int16_t)
125#define DEFAULT_VOIP_SAMP_RATE 48000
126
127#define VOIP_IO_BUF_SIZE(SR, DURATION_MS, BIT_DEPTH) (SR)/1000 * DURATION_MS * BIT_DEPTH
128
129struct pcm_config default_pcm_config_voip_copp = {
130 .channels = 1,
131 .rate = DEFAULT_VOIP_SAMP_RATE, /* changed when the stream is opened */
132 .period_size = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
133 .period_count = 2,
134 .format = PCM_FORMAT_S16_LE,
kunleiz95b597a2017-10-23 17:07:33 +0800135 .avail_min = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
136 .stop_threshold = INT_MAX,
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700137};
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700138
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700139#define MIN_CHANNEL_COUNT 1
140#define DEFAULT_CHANNEL_COUNT 2
141#define MAX_HIFI_CHANNEL_COUNT 8
142
Aalique Grahame22e49102018-12-18 14:23:57 -0800143#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
144#define MAX_CHANNEL_COUNT 1
145#else
146#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
147#define XSTR(x) STR(x)
148#define STR(x) #x
149#endif
150
Dechen Chai22768452021-07-30 09:29:16 +0530151#ifdef LINUX_ENABLED
152static inline int64_t audio_utils_ns_from_timespec(const struct timespec *ts)
153{
154 return ts->tv_sec * 1000000000LL + ts->tv_nsec;
155}
156#endif
157
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700158static unsigned int configured_low_latency_capture_period_size =
159 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
160
Haynes Mathew George16081042017-05-31 17:16:49 -0700161#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
162#define MMAP_PERIOD_COUNT_MIN 32
163#define MMAP_PERIOD_COUNT_MAX 512
164#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
165
Aalique Grahame22e49102018-12-18 14:23:57 -0800166/* This constant enables extended precision handling.
167 * TODO The flag is off until more testing is done.
168 */
169static const bool k_enable_extended_precision = false;
Arun Mirpurie008ed22019-03-21 11:21:04 -0700170extern int AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Aalique Grahame22e49102018-12-18 14:23:57 -0800171
Eric Laurentb23d5282013-05-14 15:27:20 -0700172struct pcm_config pcm_config_deep_buffer = {
173 .channels = 2,
174 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
175 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
176 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
177 .format = PCM_FORMAT_S16_LE,
178 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
179 .stop_threshold = INT_MAX,
180 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
181};
182
183struct pcm_config pcm_config_low_latency = {
184 .channels = 2,
185 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
186 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
187 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
188 .format = PCM_FORMAT_S16_LE,
189 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
190 .stop_threshold = INT_MAX,
191 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
192};
193
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800194struct pcm_config pcm_config_haptics_audio = {
195 .channels = 1,
196 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
197 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
198 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
199 .format = PCM_FORMAT_S16_LE,
200 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
201 .stop_threshold = INT_MAX,
202 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
203};
204
205struct pcm_config pcm_config_haptics = {
206 .channels = 1,
207 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
208 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
209 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
210 .format = PCM_FORMAT_S16_LE,
211 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
212 .stop_threshold = INT_MAX,
213 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
214};
215
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700216static int af_period_multiplier = 4;
217struct pcm_config pcm_config_rt = {
218 .channels = 2,
219 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
220 .period_size = ULL_PERIOD_SIZE, //1 ms
221 .period_count = 512, //=> buffer size is 512ms
222 .format = PCM_FORMAT_S16_LE,
223 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
224 .stop_threshold = INT_MAX,
225 .silence_threshold = 0,
226 .silence_size = 0,
227 .avail_min = ULL_PERIOD_SIZE, //1 ms
228};
229
Eric Laurentb23d5282013-05-14 15:27:20 -0700230struct pcm_config pcm_config_hdmi_multi = {
231 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
232 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
233 .period_size = HDMI_MULTI_PERIOD_SIZE,
234 .period_count = HDMI_MULTI_PERIOD_COUNT,
235 .format = PCM_FORMAT_S16_LE,
236 .start_threshold = 0,
237 .stop_threshold = INT_MAX,
238 .avail_min = 0,
239};
240
Haynes Mathew George16081042017-05-31 17:16:49 -0700241struct pcm_config pcm_config_mmap_playback = {
242 .channels = 2,
243 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
244 .period_size = MMAP_PERIOD_SIZE,
245 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
246 .format = PCM_FORMAT_S16_LE,
247 .start_threshold = MMAP_PERIOD_SIZE*8,
248 .stop_threshold = INT32_MAX,
249 .silence_threshold = 0,
250 .silence_size = 0,
251 .avail_min = MMAP_PERIOD_SIZE, //1 ms
252};
253
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700254struct pcm_config pcm_config_hifi = {
255 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
256 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
257 .period_size = HIFI_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
258 .period_count = HIFI_BUFFER_OUTPUT_PERIOD_COUNT,
259 .format = PCM_FORMAT_S24_3LE,
260 .start_threshold = 0,
261 .stop_threshold = INT_MAX,
262 .avail_min = 0,
263};
264
Eric Laurentb23d5282013-05-14 15:27:20 -0700265struct pcm_config pcm_config_audio_capture = {
266 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700267 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
268 .format = PCM_FORMAT_S16_LE,
269};
270
Haynes Mathew George16081042017-05-31 17:16:49 -0700271struct pcm_config pcm_config_mmap_capture = {
272 .channels = 2,
273 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
274 .period_size = MMAP_PERIOD_SIZE,
275 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
276 .format = PCM_FORMAT_S16_LE,
277 .start_threshold = 0,
278 .stop_threshold = INT_MAX,
279 .silence_threshold = 0,
280 .silence_size = 0,
281 .avail_min = MMAP_PERIOD_SIZE, //1 ms
282};
283
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700284#define AFE_PROXY_CHANNEL_COUNT 2
285#define AFE_PROXY_SAMPLING_RATE 48000
286
287#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
288#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
289
290struct pcm_config pcm_config_afe_proxy_playback = {
291 .channels = AFE_PROXY_CHANNEL_COUNT,
292 .rate = AFE_PROXY_SAMPLING_RATE,
293 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
294 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
295 .format = PCM_FORMAT_S16_LE,
296 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
297 .stop_threshold = INT_MAX,
298 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
299};
300
301#define AFE_PROXY_RECORD_PERIOD_SIZE 768
302#define AFE_PROXY_RECORD_PERIOD_COUNT 4
303
Aalique Grahame22e49102018-12-18 14:23:57 -0800304struct pcm_config pcm_config_audio_capture_rt = {
305 .channels = 2,
306 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
307 .period_size = ULL_PERIOD_SIZE,
308 .period_count = 512,
309 .format = PCM_FORMAT_S16_LE,
310 .start_threshold = 0,
311 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
312 .silence_threshold = 0,
313 .silence_size = 0,
314 .avail_min = ULL_PERIOD_SIZE, //1 ms
315};
316
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700317struct pcm_config pcm_config_afe_proxy_record = {
318 .channels = AFE_PROXY_CHANNEL_COUNT,
319 .rate = AFE_PROXY_SAMPLING_RATE,
320 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
321 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
322 .format = PCM_FORMAT_S16_LE,
323 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
324 .stop_threshold = INT_MAX,
325 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
326};
327
Ashish Jainf1eaa582016-05-23 20:54:24 +0530328#define AUDIO_MAX_PCM_FORMATS 7
329
330const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
331 [AUDIO_FORMAT_DEFAULT] = 0,
332 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
333 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
334 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
335 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
336 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
337 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
338};
339
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800340const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700341 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
342 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800343 [USECASE_AUDIO_PLAYBACK_WITH_HAPTICS] = "audio-with-haptics-playback",
Meng Wang51d8c2a2020-04-27 15:23:21 +0800344 [USECASE_AUDIO_PLAYBACK_HAPTICS] = "haptics-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700345 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
346 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700347 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700348 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700349 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
350 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
351 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
352 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
353 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
354 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
355 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
356 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
Haynes Mathew George16081042017-05-31 17:16:49 -0700357 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
358 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700359 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Aalique Grahame22e49102018-12-18 14:23:57 -0800360 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
vivek mehta0ea887a2015-08-26 14:01:20 -0700361
Eric Laurentb23d5282013-05-14 15:27:20 -0700362 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700363 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530364 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
365 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
366 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Dhananjay Kumar376e38b2017-09-28 22:26:23 +0530367 [USECASE_AUDIO_RECORD_COMPRESS5] = "audio-record-compress5",
368 [USECASE_AUDIO_RECORD_COMPRESS6] = "audio-record-compress6",
Eric Laurentb23d5282013-05-14 15:27:20 -0700369 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700370 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700371 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700372 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700373
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800374 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800375 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Derek Chenf7092792017-05-23 12:23:53 -0400376 [USECASE_AUDIO_HFP_SCO_DOWNLINK] = "hfp-sco-downlink",
377 [USECASE_AUDIO_HFP_SCO_WB_DOWNLINK] = "hfp-sco-wb-downlink",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700378
Derek Chenf7092792017-05-23 12:23:53 -0400379 [USECASE_VOICE_CALL] = "voice-call",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700380 [USECASE_VOICE2_CALL] = "voice2-call",
381 [USECASE_VOLTE_CALL] = "volte-call",
382 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800383 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800384 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
385 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800386 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700387 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
388 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
389 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800390 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
391 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
392 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
393
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700394 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
395 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700396 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
397 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700398
399 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
400 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Zhou Song62ea0282020-03-22 19:53:01 +0800401 [USECASE_AUDIO_RECORD_AFE_PROXY2] = "afe-proxy-record2",
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +0530402 [USECASE_AUDIO_PLAYBACK_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700403
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530404 /* Transcode loopback cases */
Surendar Karka93cd25a2018-08-28 14:21:37 +0530405 [USECASE_AUDIO_TRANSCODE_LOOPBACK_RX] = "audio-transcode-loopback-rx",
406 [USECASE_AUDIO_TRANSCODE_LOOPBACK_TX] = "audio-transcode-loopback-tx",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700407
408 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
409 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Revathi Uddarajud9f23d92020-07-27 10:55:06 +0530410 [USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY] = "audio-record-voip-low-latency",
Varun Balaraje49253e2017-07-06 19:48:56 +0530411 /* For Interactive Audio Streams */
412 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
413 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
414 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
415 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
416 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
417 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
418 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
419 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700420
Aniket Kumar Lata7fd86e12018-02-20 19:26:10 -0800421 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture",
422
Derek Chenf6318be2017-06-12 17:16:24 -0400423 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
424
425 [USECASE_AUDIO_PLAYBACK_MEDIA] = "media-playback",
426 [USECASE_AUDIO_PLAYBACK_SYS_NOTIFICATION] = "sys-notification-playback",
427 [USECASE_AUDIO_PLAYBACK_NAV_GUIDANCE] = "nav-guidance-playback",
428 [USECASE_AUDIO_PLAYBACK_PHONE] = "phone-playback",
Derek Chen1bcdc6b2020-02-06 22:44:53 -0800429 [USECASE_AUDIO_PLAYBACK_FRONT_PASSENGER] = "front-passenger-playback",
Derek Chendf05eea2019-08-01 13:57:49 -0700430 [USECASE_AUDIO_PLAYBACK_REAR_SEAT] = "rear-seat-playback",
Rahul Sharma99770982019-03-06 17:05:26 +0530431 [USECASE_AUDIO_FM_TUNER_EXT] = "fm-tuner-ext",
Derek Chena30a5f42019-12-03 11:17:09 -0500432 [USECASE_ICC_CALL] = "icc-call",
Huicheng Liu1404ba12020-09-11 01:03:25 -0400433
434 [USECASE_AUDIO_RECORD_BUS] = "audio-record",
435 [USECASE_AUDIO_RECORD_BUS_FRONT_PASSENGER] = "front-passenger-record",
436 [USECASE_AUDIO_RECORD_BUS_REAR_SEAT] = "rear-seat-record",
Fei Tongaffdf732020-02-20 20:39:05 +0800437 [USECASE_AUDIO_PLAYBACK_SYNTHESIZER] = "synth-loopback",
Susan Wange3959562021-03-11 11:50:26 -0500438 [USECASE_AUDIO_RECORD_ECHO_REF_EXT] = "echo-reference-external",
Eric Laurentb23d5282013-05-14 15:27:20 -0700439};
440
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700441static const audio_usecase_t offload_usecases[] = {
442 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700443 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
444 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
445 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
446 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
447 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
448 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
449 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
450 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700451};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800452
Varun Balaraje49253e2017-07-06 19:48:56 +0530453static const audio_usecase_t interactive_usecases[] = {
454 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
455 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
456 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
457 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
458 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
459 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
460 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
461 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
462};
463
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800464#define STRING_TO_ENUM(string) { #string, string }
465
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800466struct string_to_enum {
467 const char *name;
468 uint32_t value;
469};
470
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700471static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800472 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800473 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
474 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
475 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700476 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800477 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
478 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800479 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700480 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
481 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
482 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
483 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
484 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
485 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
486 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
487 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
488 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
489 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
490 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800491};
492
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700493static const struct string_to_enum formats_name_to_enum_table[] = {
494 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
495 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
496 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700497 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
498 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
499 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700500 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800501 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
502 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700503 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800504};
505
506//list of all supported sample rates by HDMI specification.
507static const int out_hdmi_sample_rates[] = {
508 32000, 44100, 48000, 88200, 96000, 176400, 192000,
509};
510
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700511static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800512 STRING_TO_ENUM(32000),
513 STRING_TO_ENUM(44100),
514 STRING_TO_ENUM(48000),
515 STRING_TO_ENUM(88200),
516 STRING_TO_ENUM(96000),
517 STRING_TO_ENUM(176400),
518 STRING_TO_ENUM(192000),
Mingshu pange8aedf12019-10-25 15:38:27 +0800519 STRING_TO_ENUM(352800),
520 STRING_TO_ENUM(384000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700521};
522
Carter Hsu2e429db2019-05-14 18:50:52 +0800523struct in_effect_list {
524 struct listnode list;
525 effect_handle_t handle;
526};
527
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700528static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700529static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700530static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700531//cache last MBDRC cal step level
532static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700533
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530534static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Arun Mirpuri5d170872019-03-26 13:21:31 -0700535static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800536static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530537static int out_set_pcm_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530538
Derek Chen6f293672019-04-01 01:40:24 -0700539static void adev_snd_mon_cb(void *cookie, struct str_parms *parms);
540static void in_snd_mon_cb(void * stream, struct str_parms * parms);
541static void out_snd_mon_cb(void * stream, struct str_parms * parms);
542
Zhou Song331c8e52019-08-26 14:16:12 +0800543static int configure_btsco_sample_rate(snd_device_t snd_device);
544
Vatsal Buchac09ae062018-11-14 13:25:08 +0530545#ifdef AUDIO_FEATURE_ENABLED_GCOV
546extern void __gcov_flush();
547static void enable_gcov()
548{
549 __gcov_flush();
550}
551#else
552static void enable_gcov()
553{
554}
555#endif
556
justinweng20fb6d82019-02-21 18:49:00 -0700557static int in_set_microphone_direction(const struct audio_stream_in *stream,
558 audio_microphone_direction_t dir);
559static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom);
560
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700561static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
562 int flags __unused)
563{
564 int dir = 0;
565 switch (uc_id) {
566 case USECASE_AUDIO_RECORD_LOW_LATENCY:
Revathi Uddarajud9f23d92020-07-27 10:55:06 +0530567 case USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY:
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700568 dir = 1;
569 case USECASE_AUDIO_PLAYBACK_ULL:
570 break;
571 default:
572 return false;
573 }
574
575 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
576 PCM_PLAYBACK : PCM_CAPTURE);
577 if (adev->adm_is_noirq_avail)
578 return adev->adm_is_noirq_avail(adev->adm_data,
579 adev->snd_card, dev_id, dir);
580 return false;
581}
582
583static void register_out_stream(struct stream_out *out)
584{
585 struct audio_device *adev = out->dev;
586 if (is_offload_usecase(out->usecase) ||
587 !adev->adm_register_output_stream)
588 return;
589
590 // register stream first for backward compatibility
591 adev->adm_register_output_stream(adev->adm_data,
592 out->handle,
593 out->flags);
594
595 if (!adev->adm_set_config)
596 return;
597
598 if (out->realtime)
599 adev->adm_set_config(adev->adm_data,
600 out->handle,
601 out->pcm, &out->config);
602}
603
604static void register_in_stream(struct stream_in *in)
605{
606 struct audio_device *adev = in->dev;
607 if (!adev->adm_register_input_stream)
608 return;
609
610 adev->adm_register_input_stream(adev->adm_data,
611 in->capture_handle,
612 in->flags);
613
614 if (!adev->adm_set_config)
615 return;
616
617 if (in->realtime)
618 adev->adm_set_config(adev->adm_data,
619 in->capture_handle,
620 in->pcm,
621 &in->config);
622}
623
624static void request_out_focus(struct stream_out *out, long ns)
625{
626 struct audio_device *adev = out->dev;
627
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700628 if (adev->adm_request_focus_v2)
629 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
630 else if (adev->adm_request_focus)
631 adev->adm_request_focus(adev->adm_data, out->handle);
632}
633
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700634static int request_in_focus(struct stream_in *in, long ns)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700635{
636 struct audio_device *adev = in->dev;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700637 int ret = 0;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700638
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700639 if (adev->adm_request_focus_v2_1)
640 ret = adev->adm_request_focus_v2_1(adev->adm_data, in->capture_handle, ns);
641 else if (adev->adm_request_focus_v2)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700642 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
643 else if (adev->adm_request_focus)
644 adev->adm_request_focus(adev->adm_data, in->capture_handle);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700645
646 return ret;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700647}
648
649static void release_out_focus(struct stream_out *out)
650{
651 struct audio_device *adev = out->dev;
652
653 if (adev->adm_abandon_focus)
654 adev->adm_abandon_focus(adev->adm_data, out->handle);
655}
656
657static void release_in_focus(struct stream_in *in)
658{
659 struct audio_device *adev = in->dev;
660 if (adev->adm_abandon_focus)
661 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
662}
663
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530664static int parse_snd_card_status(struct str_parms *parms, int *card,
665 card_status_t *status)
666{
667 char value[32]={0};
668 char state[32]={0};
669
670 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
671 if (ret < 0)
672 return -1;
673
674 // sscanf should be okay as value is of max length 32.
675 // same as sizeof state.
676 if (sscanf(value, "%d,%s", card, state) < 2)
677 return -1;
678
679 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
680 CARD_STATUS_OFFLINE;
681 return 0;
682}
683
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700684static inline void adjust_frames_for_device_delay(struct stream_out *out,
685 uint32_t *dsp_frames) {
686 // Adjustment accounts for A2dp encoder latency with offload usecases
687 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -0800688 if (is_a2dp_out_device_type(&out->device_list)) {
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700689 unsigned long offset =
690 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
691 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
692 }
693}
694
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700695static inline bool free_entry(void *key __unused,
696 void *value, void *context __unused)
697{
698 free(value);
699 return true;
700}
701
702static inline void free_map(Hashmap *map)
703{
704 if (map) {
705 hashmapForEach(map, free_entry, (void *) NULL);
706 hashmapFree(map);
707 }
708}
709
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800710static inline void patch_map_remove_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700711 audio_patch_handle_t patch_handle)
712{
713 if (patch_handle == AUDIO_PATCH_HANDLE_NONE)
714 return;
715
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700716 struct audio_patch_info *p_info =
717 hashmapGet(adev->patch_map, (void *) (intptr_t) patch_handle);
718 if (p_info) {
719 ALOGV("%s: Remove patch %d", __func__, patch_handle);
720 hashmapRemove(adev->patch_map, (void *) (intptr_t) patch_handle);
721 free(p_info->patch);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700722 free(p_info);
723 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700724}
725
726static inline int io_streams_map_insert(struct audio_device *adev,
727 struct audio_stream *stream,
728 audio_io_handle_t handle,
729 audio_patch_handle_t patch_handle)
730{
731 struct audio_stream_info *s_info =
732 (struct audio_stream_info *) calloc(1, sizeof(struct audio_stream_info));
733
734 if (s_info == NULL) {
735 ALOGE("%s: Could not allocate stream info", __func__);
736 return -ENOMEM;
737 }
738 s_info->stream = stream;
739 s_info->patch_handle = patch_handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700740
741 pthread_mutex_lock(&adev->lock);
742 struct audio_stream_info *stream_info =
743 hashmapPut(adev->io_streams_map, (void *) (intptr_t) handle, (void *) s_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700744 if (stream_info != NULL)
745 free(stream_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800746 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Latad13758f2020-08-06 15:11:36 -0700747 ALOGV("%s: Added stream in io_streams_map with handle %d", __func__, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700748 return 0;
749}
750
751static inline void io_streams_map_remove(struct audio_device *adev,
752 audio_io_handle_t handle)
753{
754 pthread_mutex_lock(&adev->lock);
755 struct audio_stream_info *s_info =
756 hashmapRemove(adev->io_streams_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700757 if (s_info == NULL)
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800758 goto done;
Aniket Kumar Latad13758f2020-08-06 15:11:36 -0700759 ALOGV("%s: Removed stream with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800760 patch_map_remove_l(adev, s_info->patch_handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700761 free(s_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800762done:
763 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700764 return;
765}
766
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800767static struct audio_patch_info* fetch_patch_info_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700768 audio_patch_handle_t handle)
769{
770 struct audio_patch_info *p_info = NULL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700771 p_info = (struct audio_patch_info *)
772 hashmapGet(adev->patch_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700773 return p_info;
774}
775
vivek mehtaa76401a2015-04-24 14:12:15 -0700776__attribute__ ((visibility ("default")))
777bool audio_hw_send_gain_dep_calibration(int level) {
778 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700779 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700780
781 pthread_mutex_lock(&adev_init_lock);
782
783 if (adev != NULL && adev->platform != NULL) {
784 pthread_mutex_lock(&adev->lock);
785 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700786
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530787 // cache level info for any of the use case which
788 // was not started.
789 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700790
vivek mehtaa76401a2015-04-24 14:12:15 -0700791 pthread_mutex_unlock(&adev->lock);
792 } else {
793 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
794 }
795
796 pthread_mutex_unlock(&adev_init_lock);
797
798 return ret_val;
799}
800
Ashish Jain5106d362016-05-11 19:23:33 +0530801static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
802{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800803 bool gapless_enabled = false;
804 const char *mixer_ctl_name = "Compress Gapless Playback";
805 struct mixer_ctl *ctl;
806
807 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700808 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530809
810 /*Disable gapless if its AV playback*/
811 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800812
813 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
814 if (!ctl) {
815 ALOGE("%s: Could not get ctl for mixer cmd - %s",
816 __func__, mixer_ctl_name);
817 return -EINVAL;
818 }
819
820 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
821 ALOGE("%s: Could not set gapless mode %d",
822 __func__, gapless_enabled);
823 return -EINVAL;
824 }
825 return 0;
826}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700827
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700828__attribute__ ((visibility ("default")))
829int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
830 int table_size) {
831 int ret_val = 0;
832 ALOGV("%s: enter ... ", __func__);
833
834 pthread_mutex_lock(&adev_init_lock);
835 if (adev == NULL) {
836 ALOGW("%s: adev is NULL .... ", __func__);
837 goto done;
838 }
839
840 pthread_mutex_lock(&adev->lock);
841 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
842 pthread_mutex_unlock(&adev->lock);
843done:
844 pthread_mutex_unlock(&adev_init_lock);
845 ALOGV("%s: exit ... ", __func__);
846 return ret_val;
847}
848
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800849bool audio_hw_send_qdsp_parameter(int stream_type, float vol, bool active)
Aalique Grahame22e49102018-12-18 14:23:57 -0800850{
851 bool ret = false;
852 ALOGV("%s: enter ...", __func__);
853
854 pthread_mutex_lock(&adev_init_lock);
855
856 if (adev != NULL && adev->platform != NULL) {
857 pthread_mutex_lock(&adev->lock);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800858 ret = audio_extn_qdsp_set_state(adev, stream_type, vol, active);
Aalique Grahame22e49102018-12-18 14:23:57 -0800859 pthread_mutex_unlock(&adev->lock);
860 }
861
862 pthread_mutex_unlock(&adev_init_lock);
863
864 ALOGV("%s: exit with ret %d", __func__, ret);
865 return ret;
866}
Aalique Grahame22e49102018-12-18 14:23:57 -0800867
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700868static bool is_supported_format(audio_format_t format)
869{
Eric Laurent86e17132013-09-12 17:49:30 -0700870 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530871 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530872 format == AUDIO_FORMAT_AAC_LC ||
873 format == AUDIO_FORMAT_AAC_HE_V1 ||
874 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530875 format == AUDIO_FORMAT_AAC_ADTS_LC ||
876 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
877 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530878 format == AUDIO_FORMAT_AAC_LATM_LC ||
879 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
880 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530881 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
882 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530883 format == AUDIO_FORMAT_PCM_FLOAT ||
884 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700885 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530886 format == AUDIO_FORMAT_AC3 ||
887 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700888 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530889 format == AUDIO_FORMAT_DTS ||
890 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800891 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530892 format == AUDIO_FORMAT_ALAC ||
893 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530894 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530895 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800896 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530897 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700898 format == AUDIO_FORMAT_APTX ||
899 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800900 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700901
902 return false;
903}
904
Kunlei Zhang67cc7072020-12-18 17:16:49 +0800905static bool is_supported_conc_usecase_for_power_mode_call(struct audio_device *adev)
906{
907 struct listnode *node;
908 struct audio_usecase *usecase;
909
910 list_for_each(node, &adev->usecase_list) {
911 usecase = node_to_item(node, struct audio_usecase, list);
912 if (usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
913 ALOGD("%s: FM usecase is active, not setting power mode", __func__);
914 return false;
915 }
916 }
917
918 return true;
919}
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700920static inline bool is_mmap_usecase(audio_usecase_t uc_id)
921{
922 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
Zhou Song62ea0282020-03-22 19:53:01 +0800923 (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY2) ||
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700924 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
925}
926
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700927static inline bool is_valid_volume(float left, float right)
928{
929 return ((left >= 0.0f && right >= 0.0f) ? true : false);
930}
931
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530932static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530933{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530934 ALOGV("%s", __func__);
935 audio_route_apply_and_update_path(adev->audio_route,
936 "asrc-mode");
937 adev->asrc_mode_enabled = true;
938}
939
940static void disable_asrc_mode(struct audio_device *adev)
941{
942 ALOGV("%s", __func__);
943 audio_route_reset_and_update_path(adev->audio_route,
944 "asrc-mode");
945 adev->asrc_mode_enabled = false;
946}
947
Saurav Kumarc1411662020-10-14 10:50:45 +0530948static void check_and_configure_headphone(struct audio_device *adev,
949 struct audio_usecase *uc_info,
950 snd_device_t snd_device)
951{
952 struct listnode *node;
953 struct audio_usecase *usecase;
954 int new_backend_idx, usecase_backend_idx;
955 bool spkr_hph_single_be_native_concurrency;
956
957 new_backend_idx = platform_get_backend_index(snd_device);
958 spkr_hph_single_be_native_concurrency = platform_get_spkr_hph_single_be_native_concurrency_flag();
Zhou Songd4b18c42021-01-14 15:15:29 +0800959 if ((spkr_hph_single_be_native_concurrency && (new_backend_idx == DEFAULT_CODEC_BACKEND)) ||
960 uc_info->id == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
Saurav Kumarc1411662020-10-14 10:50:45 +0530961 list_for_each(node, &adev->usecase_list) {
962 usecase = node_to_item(node, struct audio_usecase, list);
963 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
964 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
965 if (((usecase_backend_idx == HEADPHONE_BACKEND) ||
966 (usecase_backend_idx == HEADPHONE_44_1_BACKEND)) &&
967 ((usecase->stream.out->sample_rate % OUTPUT_SAMPLING_RATE_44100) == 0)) {
968 disable_audio_route(adev, usecase);
969 disable_snd_device(adev, usecase->out_snd_device);
970 usecase->stream.out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Saurav Kumar70902382020-10-28 11:16:04 +0530971 platform_check_and_set_codec_backend_cfg(adev, usecase,
972 usecase->out_snd_device);
Saurav Kumarc1411662020-10-14 10:50:45 +0530973 enable_snd_device(adev, usecase->out_snd_device);
Zhou Songd4b18c42021-01-14 15:15:29 +0800974 enable_audio_route(adev, usecase);
Saurav Kumarc1411662020-10-14 10:50:45 +0530975 }
976 }
Revathi Uddaraju2c0eac02021-07-27 02:06:42 -0700977 else if ((usecase->type != PCM_CAPTURE) && (usecase == uc_info)) {
978 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
979 if (((usecase_backend_idx == HEADPHONE_BACKEND) ||
980 (usecase_backend_idx == HEADPHONE_44_1_BACKEND)) &&
981 ((usecase->stream.out->sample_rate % OUTPUT_SAMPLING_RATE_44100) == 0)) {
982 usecase->stream.out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
983 platform_check_and_set_codec_backend_cfg(adev, usecase,
984 usecase->out_snd_device);
985 }
986 }
Saurav Kumarc1411662020-10-14 10:50:45 +0530987 }
988 }
989}
990
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530991/*
992 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
993 * 44.1 or Native DSD backends are enabled for any of current use case.
994 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
995 * - Disable current mix path use case(Headphone backend) and re-enable it with
996 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
997 * e.g. Naitve DSD or Headphone 44.1 -> + 48
998 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530999static void check_and_set_asrc_mode(struct audio_device *adev,
1000 struct audio_usecase *uc_info,
1001 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301002{
1003 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301004 int i, num_new_devices = 0;
1005 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
1006 /*
1007 *Split snd device for new combo use case
1008 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
1009 */
1010 if (platform_split_snd_device(adev->platform,
1011 snd_device,
1012 &num_new_devices,
1013 split_new_snd_devices) == 0) {
1014 for (i = 0; i < num_new_devices; i++)
1015 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
1016 } else {
1017 int new_backend_idx = platform_get_backend_index(snd_device);
1018 if (((new_backend_idx == HEADPHONE_BACKEND) ||
1019 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
1020 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
1021 !adev->asrc_mode_enabled) {
1022 struct listnode *node = NULL;
1023 struct audio_usecase *uc = NULL;
1024 struct stream_out *curr_out = NULL;
1025 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
1026 int i, num_devices, ret = 0;
1027 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301028
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301029 list_for_each(node, &adev->usecase_list) {
1030 uc = node_to_item(node, struct audio_usecase, list);
1031 curr_out = (struct stream_out*) uc->stream.out;
1032 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
1033 /*
1034 *Split snd device for existing combo use case
1035 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
1036 */
1037 ret = platform_split_snd_device(adev->platform,
1038 uc->out_snd_device,
1039 &num_devices,
1040 split_snd_devices);
1041 if (ret < 0 || num_devices == 0) {
1042 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
1043 split_snd_devices[0] = uc->out_snd_device;
1044 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -08001045 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301046 for (i = 0; i < num_devices; i++) {
1047 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
1048 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
1049 if((new_backend_idx == HEADPHONE_BACKEND) &&
1050 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
1051 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07001052 ALOGV("%s:DSD or native stream detected enabling asrcmode in hardware",
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301053 __func__);
1054 enable_asrc_mode(adev);
1055 break;
1056 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
1057 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
1058 (usecase_backend_idx == HEADPHONE_BACKEND)) {
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07001059 ALOGV("%s: 48K stream detected, disabling and enabling it \
1060 with asrcmode in hardware", __func__);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301061 disable_audio_route(adev, uc);
1062 disable_snd_device(adev, uc->out_snd_device);
1063 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
1064 if (new_backend_idx == DSD_NATIVE_BACKEND)
1065 audio_route_apply_and_update_path(adev->audio_route,
1066 "hph-true-highquality-mode");
1067 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
1068 (curr_out->bit_width >= 24))
1069 audio_route_apply_and_update_path(adev->audio_route,
1070 "hph-highquality-mode");
1071 enable_asrc_mode(adev);
1072 enable_snd_device(adev, uc->out_snd_device);
1073 enable_audio_route(adev, uc);
1074 break;
1075 }
1076 }
1077 // reset split devices count
1078 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -08001079 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301080 if (adev->asrc_mode_enabled)
1081 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301082 }
1083 }
1084 }
1085}
1086
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001087static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
1088 struct audio_effect_config effect_config,
1089 unsigned int param_value)
1090{
1091 char mixer_ctl_name[] = "Audio Effect";
1092 struct mixer_ctl *ctl;
1093 long set_values[6];
Eric Laurent637e2d42018-11-15 12:24:31 -08001094 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001095
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001096 if (in == NULL) {
1097 ALOGE("%s: active input stream is NULL", __func__);
1098 return -EINVAL;
1099 }
1100
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001101 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1102 if (!ctl) {
1103 ALOGE("%s: Could not get mixer ctl - %s",
1104 __func__, mixer_ctl_name);
1105 return -EINVAL;
1106 }
1107
1108 set_values[0] = 1; //0:Rx 1:Tx
1109 set_values[1] = in->app_type_cfg.app_type;
1110 set_values[2] = (long)effect_config.module_id;
1111 set_values[3] = (long)effect_config.instance_id;
1112 set_values[4] = (long)effect_config.param_id;
1113 set_values[5] = param_value;
1114
1115 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
1116
1117 return 0;
1118
1119}
1120
1121static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
1122 int effect_type, unsigned int *param_value)
1123{
1124 int ret = 0;
1125 struct audio_effect_config other_effect_config;
1126 struct audio_usecase *usecase = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08001127 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001128
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001129 if (in == NULL) {
1130 ALOGE("%s: active input stream is NULL", __func__);
1131 return -EINVAL;
1132 }
1133
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001134 usecase = get_usecase_from_list(adev, in->usecase);
1135 if (!usecase)
1136 return -EINVAL;
1137
1138 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
1139 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
1140 if (ret < 0) {
1141 ALOGE("%s Failed to get effect params %d", __func__, ret);
1142 return ret;
1143 }
1144
1145 if (module_id == other_effect_config.module_id) {
1146 //Same module id for AEC/NS. Values need to be combined
1147 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
1148 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
1149 *param_value |= other_effect_config.param_value;
1150 }
1151 }
1152
1153 return ret;
1154}
1155
1156static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
Gangadhar Sb0210342019-02-22 17:39:41 +05301157{
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001158 struct audio_effect_config effect_config;
1159 struct audio_usecase *usecase = NULL;
1160 int ret = 0;
1161 unsigned int param_value = 0;
Eric Laurent637e2d42018-11-15 12:24:31 -08001162 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001163
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001164 if(!voice_extn_is_dynamic_ecns_enabled())
1165 return ENOSYS;
1166
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001167 if (!in) {
1168 ALOGE("%s: Invalid input stream", __func__);
1169 return -EINVAL;
1170 }
1171
1172 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
1173
1174 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +08001175 if (usecase == NULL) {
1176 ALOGE("%s: Could not find the usecase (%d) in the list",
1177 __func__, in->usecase);
1178 return -EINVAL;
1179 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001180
1181 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
1182 if (ret < 0) {
1183 ALOGE("%s Failed to get module id %d", __func__, ret);
1184 return ret;
1185 }
1186 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
1187 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
1188
1189 if(enable)
1190 param_value = effect_config.param_value;
1191
1192 /*Special handling for AEC & NS effects Param values need to be
1193 updated if module ids are same*/
1194
1195 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
1196 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
1197 if (ret < 0)
1198 return ret;
1199 }
1200
1201 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
1202
1203 return ret;
1204}
1205
1206static void check_and_enable_effect(struct audio_device *adev)
1207{
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001208 if(!voice_extn_is_dynamic_ecns_enabled())
1209 return;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001210
Eric Laurent637e2d42018-11-15 12:24:31 -08001211 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001212
Eric Laurent637e2d42018-11-15 12:24:31 -08001213 if (in != NULL && !in->standby) {
1214 if (in->enable_aec)
1215 enable_disable_effect(adev, EFFECT_AEC, true);
1216
1217 if (in->enable_ns &&
1218 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1219 enable_disable_effect(adev, EFFECT_NS, true);
1220 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001221 }
1222}
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001223
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001224int pcm_ioctl(struct pcm *pcm, int request, ...)
1225{
1226 va_list ap;
1227 void * arg;
1228 int pcm_fd = *(int*)pcm;
1229
1230 va_start(ap, request);
1231 arg = va_arg(ap, void *);
1232 va_end(ap);
1233
1234 return ioctl(pcm_fd, request, arg);
1235}
1236
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001237int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001238 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001239{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001240 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001241 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +05301242 struct stream_out *out = NULL;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301243 struct stream_in *in = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001244 struct listnode out_devices;
Soumya Managoli6993b762018-06-28 16:04:57 +05301245 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001246
1247 if (usecase == NULL)
1248 return -EINVAL;
1249
1250 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
1251
Carter Hsu2e429db2019-05-14 18:50:52 +08001252 if (usecase->type == PCM_CAPTURE) {
1253 struct stream_in *in = usecase->stream.in;
1254 struct audio_usecase *uinfo;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001255 snd_device = usecase->in_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001256
1257 if (in) {
1258 if (in->enable_aec || in->enable_ec_port) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001259 list_init(&out_devices);
1260 update_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "", true);
Carter Hsu2e429db2019-05-14 18:50:52 +08001261 struct listnode *node;
1262 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1263 USECASE_AUDIO_PLAYBACK_VOIP);
1264 if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001265 assign_devices(&out_devices,
1266 &voip_usecase->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001267 } else if (adev->primary_output &&
1268 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001269 assign_devices(&out_devices,
1270 &adev->primary_output->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001271 } else {
1272 list_for_each(node, &adev->usecase_list) {
1273 uinfo = node_to_item(node, struct audio_usecase, list);
1274 if (uinfo->type != PCM_CAPTURE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001275 assign_devices(&out_devices,
1276 &uinfo->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001277 break;
1278 }
1279 }
1280 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001281
1282 platform_set_echo_reference(adev, true, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001283 in->ec_opened = true;
1284 }
1285 }
Guodong Huf5e614d2019-06-24 18:42:03 +08001286 } else if ((usecase->type == TRANSCODE_LOOPBACK_TX) || ((usecase->type == PCM_HFP_CALL) &&
1287 ((usecase->id == USECASE_AUDIO_HFP_SCO) || (usecase->id == USECASE_AUDIO_HFP_SCO_WB)) &&
1288 (usecase->in_snd_device == SND_DEVICE_IN_VOICE_SPEAKER_MIC_HFP_MMSECNS))) {
Carter Hsu2e429db2019-05-14 18:50:52 +08001289 snd_device = usecase->in_snd_device;
1290 } else {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001291 snd_device = usecase->out_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001292 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001293
Kunlei Zhanga3c4cb02021-03-05 16:03:54 +08001294 if (usecase->type == PCM_CAPTURE) {
1295 if (platform_get_fluence_nn_state(adev->platform) == 0) {
1296 platform_set_fluence_nn_state(adev->platform, true);
1297 ALOGD("%s: set fluence nn capture state", __func__);
1298 }
1299 }
1300
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001301#ifdef DS1_DOLBY_DAP_ENABLED
1302 audio_extn_dolby_set_dmid(adev);
1303 audio_extn_dolby_set_endpoint(adev);
1304#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001305 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001306 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301307 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001308 audio_extn_utils_send_app_type_cfg(adev, usecase);
Jasmine Cha4dcc1092019-03-04 18:12:47 +08001309 if (audio_extn_is_maxx_audio_enabled())
1310 audio_extn_ma_set_device(usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301311 audio_extn_utils_send_audio_calibration(adev, usecase);
Zhou Songbaddf9f2020-11-20 13:57:39 +08001312 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1313 out = usecase->stream.out;
1314 if (out && out->compr)
Manish Dewangan58229382017-02-02 15:48:41 +05301315 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1316 }
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301317
1318 if (usecase->type == PCM_CAPTURE) {
Kunlei Zhanga3c4cb02021-03-05 16:03:54 +08001319 if (platform_get_fluence_nn_state(adev->platform) == 1 &&
1320 adev->fluence_nn_usecase_id == USECASE_INVALID ) {
1321 adev->fluence_nn_usecase_id = usecase->id;
1322 ALOGD("%s: assign fluence nn usecase %d", __func__, usecase->id);
1323 }
1324 }
1325
1326 if (usecase->type == PCM_CAPTURE) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301327 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001328 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301329 ALOGD("%s: set custom mtmx params v1", __func__);
1330 audio_extn_set_custom_mtmx_params_v1(adev, usecase, true);
1331 }
1332 } else {
1333 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
1334 }
Manish Dewangan58229382017-02-02 15:48:41 +05301335
Andy Hung756ecc12018-10-19 17:47:12 -07001336 // we shouldn't truncate mixer_path
1337 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1338 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1339 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001340 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001341 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301342 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1343 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1344 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1345 if (parms) {
1346 audio_extn_fm_set_parameters(adev, parms);
1347 str_parms_destroy(parms);
1348 }
1349 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001350 ALOGV("%s: exit", __func__);
1351 return 0;
1352}
1353
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001354int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001355 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001356{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001357 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001358 char mixer_path[MIXER_PATH_MAX_LENGTH];
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301359 struct stream_in *in = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001360
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301361 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001362 return -EINVAL;
1363
1364 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301365 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001366 snd_device = usecase->in_snd_device;
1367 else
1368 snd_device = usecase->out_snd_device;
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001369
1370 /* disable island and power mode on supported device for voice call */
1371 if (usecase->type == VOICE_CALL) {
1372 if (usecase->in_snd_device != SND_DEVICE_NONE) {
1373 if (platform_get_island_cfg_on_device(adev->platform, usecase->in_snd_device) &&
1374 platform_get_power_mode_on_device(adev->platform, usecase->in_snd_device)) {
1375 platform_set_island_cfg_on_device(adev, usecase->in_snd_device, false);
1376 platform_set_power_mode_on_device(adev, usecase->in_snd_device, false);
1377 platform_reset_island_power_status(adev->platform, usecase->in_snd_device);
Kunlei Zhang91c4b332020-07-20 17:53:14 +08001378 if (voice_is_lte_call_active(adev))
1379 platform_set_tx_lpi_mode(adev->platform, false);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001380 ALOGD("%s: disable island cfg and power mode in voice tx path",
1381 __func__);
1382 }
1383 }
1384 if (usecase->out_snd_device != SND_DEVICE_NONE) {
1385 if (platform_get_island_cfg_on_device(adev->platform, usecase->out_snd_device) &&
1386 platform_get_power_mode_on_device(adev->platform, usecase->out_snd_device)) {
1387 platform_set_island_cfg_on_device(adev, usecase->out_snd_device, false);
1388 platform_set_power_mode_on_device(adev, usecase->out_snd_device, false);
1389 platform_reset_island_power_status(adev->platform, usecase->out_snd_device);
1390 ALOGD("%s: disable island cfg and power mode in voice rx path",
1391 __func__);
1392 }
1393 }
1394 }
1395
Andy Hung756ecc12018-10-19 17:47:12 -07001396 // we shouldn't truncate mixer_path
1397 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1398 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1399 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001400 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001401 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001402 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Carter Hsu2e429db2019-05-14 18:50:52 +08001403 if (usecase->type == PCM_CAPTURE) {
1404 struct stream_in *in = usecase->stream.in;
1405 if (in && in->ec_opened) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001406 struct listnode out_devices;
1407 list_init(&out_devices);
1408 platform_set_echo_reference(in->dev, false, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001409 in->ec_opened = false;
1410 }
1411 }
Kunlei Zhanga3c4cb02021-03-05 16:03:54 +08001412 if (usecase->id == adev->fluence_nn_usecase_id) {
1413 platform_set_fluence_nn_state(adev->platform, false);
1414 adev->fluence_nn_usecase_id = USECASE_INVALID;
1415 ALOGD("%s: reset fluence nn capture state", __func__);
1416 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001417 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301418 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301419
1420 if (usecase->type == PCM_CAPTURE) {
1421 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001422 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301423 ALOGD("%s: reset custom mtmx params v1", __func__);
1424 audio_extn_set_custom_mtmx_params_v1(adev, usecase, false);
1425 }
1426 } else {
1427 audio_extn_set_custom_mtmx_params_v2(adev, usecase, false);
1428 }
1429
Weiyin Jiang298ffd92019-06-03 14:29:30 +08001430 if ((usecase->type == PCM_PLAYBACK) &&
1431 (usecase->stream.out != NULL))
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05301432 usecase->stream.out->pspd_coeff_sent = false;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301433
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001434 ALOGV("%s: exit", __func__);
1435 return 0;
1436}
1437
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001438int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001439 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001440{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301441 int i, num_devices = 0;
1442 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001443 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1444
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001445 if (snd_device < SND_DEVICE_MIN ||
1446 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001447 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001448 return -EINVAL;
1449 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001450
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001451 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001452 ALOGE("%s: Invalid sound device returned", __func__);
1453 return -EINVAL;
1454 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001455
1456 adev->snd_dev_ref_cnt[snd_device]++;
1457
1458 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1459 (platform_split_snd_device(adev->platform,
1460 snd_device,
1461 &num_devices,
1462 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001463 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001464 __func__, snd_device, device_name);
Aniket Kumar Lata990de552019-07-11 14:20:23 -07001465 /* Set backend config for A2DP to ensure slimbus configuration
1466 is correct if A2DP is already active and backend is closed
1467 and re-opened */
1468 if (snd_device == SND_DEVICE_OUT_BT_A2DP)
1469 audio_extn_a2dp_set_source_backend_cfg();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001470 return 0;
1471 }
1472
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001473 if (audio_extn_spkr_prot_is_enabled())
1474 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001475
Aalique Grahame22e49102018-12-18 14:23:57 -08001476 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1477
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001478 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1479 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001480 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1481 goto err;
1482 }
1483 audio_extn_dev_arbi_acquire(snd_device);
1484 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001485 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001486 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001487 goto err;
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001488 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001489 } else if (platform_split_snd_device(adev->platform,
1490 snd_device,
1491 &num_devices,
1492 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301493 for (i = 0; i < num_devices; i++) {
1494 enable_snd_device(adev, new_snd_devices[i]);
1495 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001496 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001497 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001498 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301499
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001500 /* enable island and power mode on supported device */
1501 if (platform_get_island_cfg_on_device(adev->platform, snd_device) &&
1502 platform_get_power_mode_on_device(adev->platform, snd_device)) {
1503 platform_set_island_cfg_on_device(adev, snd_device, true);
1504 platform_set_power_mode_on_device(adev, snd_device, true);
Kunlei Zhang91c4b332020-07-20 17:53:14 +08001505 if (voice_is_lte_call_active(adev) &&
1506 (snd_device >= SND_DEVICE_IN_BEGIN &&
1507 snd_device < SND_DEVICE_IN_END))
1508 platform_set_tx_lpi_mode(adev->platform, true);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001509 ALOGD("%s: enable island cfg and power mode on: %s",
1510 __func__, device_name);
1511 }
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301512
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301513 if (SND_DEVICE_OUT_BT_A2DP == snd_device) {
Ramjee Singh2d2944a2021-12-14 14:13:41 +05301514
1515 struct audio_usecase *usecase;
1516 struct listnode *node;
1517 /* Disable SCO Devices and enable handset mic for active input stream */
1518 list_for_each(node, &adev->usecase_list) {
1519 usecase = node_to_item(node, struct audio_usecase, list);
1520 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
1521 is_sco_in_device_type(&usecase->stream.in->device_list)) {
1522 ALOGD("a2dp resumed, switch bt sco mic to handset mic");
1523 reassign_device_list(&usecase->stream.in->device_list,
1524 AUDIO_DEVICE_IN_BUILTIN_MIC, "");
1525 select_devices(adev, usecase->id);
1526 }
1527 }
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301528 if (audio_extn_a2dp_start_playback() < 0) {
1529 ALOGE(" fail to configure A2dp Source control path ");
1530 goto err;
1531 } else {
1532 adev->a2dp_started = true;
1533 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001534 }
Florian Pfister1a84f312018-07-19 14:38:18 +02001535
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001536 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1537 (audio_extn_a2dp_start_capture() < 0)) {
1538 ALOGE(" fail to configure A2dp Sink control path ");
1539 goto err;
1540 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301541
Mingshu Pang7be5b1d2020-03-04 15:24:38 +08001542 if ((SND_DEVICE_OUT_BT_SCO_SWB == snd_device) ||
1543 (SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC == snd_device) ||
1544 (SND_DEVICE_IN_BT_SCO_MIC_SWB == snd_device)) {
1545 if (!adev->bt_sco_on || (audio_extn_sco_start_configuration() < 0)) {
1546 ALOGE(" fail to configure sco control path ");
1547 goto err;
1548 }
Zhou Song12c29502019-03-16 10:37:18 +08001549 }
1550
Zhou Song331c8e52019-08-26 14:16:12 +08001551 configure_btsco_sample_rate(snd_device);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001552 /* due to the possibility of calibration overwrite between listen
1553 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001554 audio_extn_sound_trigger_update_device_status(snd_device,
1555 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301556 audio_extn_listen_update_device_status(snd_device,
1557 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001558 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001559 audio_extn_sound_trigger_update_device_status(snd_device,
1560 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301561 audio_extn_listen_update_device_status(snd_device,
1562 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001563 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001564 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001565 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001566 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301567
1568 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1569 !adev->native_playback_enabled &&
1570 audio_is_true_native_stream_active(adev)) {
1571 ALOGD("%s: %d: napb: enabling native mode in hardware",
1572 __func__, __LINE__);
1573 audio_route_apply_and_update_path(adev->audio_route,
1574 "true-native-mode");
1575 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301576 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301577 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1578 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001579 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001580 ALOGD("%s: init ec ref loopback", __func__);
1581 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1582 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001583 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001584 return 0;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001585err:
1586 adev->snd_dev_ref_cnt[snd_device]--;
1587 return -EINVAL;;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001588}
1589
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001590int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001591 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001592{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301593 int i, num_devices = 0;
1594 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001595 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1596
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001597 if (snd_device < SND_DEVICE_MIN ||
1598 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001599 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001600 return -EINVAL;
1601 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001602
1603 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1604 ALOGE("%s: Invalid sound device returned", __func__);
1605 return -EINVAL;
1606 }
1607
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001608 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1609 ALOGE("%s: device ref cnt is already 0", __func__);
1610 return -EINVAL;
1611 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001612
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001613 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001614
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001615
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001616 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001617 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301618
Aalique Grahame22e49102018-12-18 14:23:57 -08001619 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1620
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001621 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1622 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001623 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001624
1625 // when speaker device is disabled, reset swap.
1626 // will be renabled on usecase start
1627 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001628 } else if (platform_split_snd_device(adev->platform,
1629 snd_device,
1630 &num_devices,
1631 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301632 for (i = 0; i < num_devices; i++) {
1633 disable_snd_device(adev, new_snd_devices[i]);
1634 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001635 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001636 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001637 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001638 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001639
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301640 if (snd_device == SND_DEVICE_OUT_BT_A2DP) {
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301641 audio_extn_a2dp_stop_playback();
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301642 adev->a2dp_started = false;
1643 } else if (snd_device == SND_DEVICE_IN_BT_A2DP)
Florian Pfister1a84f312018-07-19 14:38:18 +02001644 audio_extn_a2dp_stop_capture();
Zhou Songd6d71752019-05-21 18:08:51 +08001645 else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001646 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
Ashish Jain81eb2a82015-05-13 10:52:34 +05301647 adev->is_channel_status_set = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001648 else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301649 adev->native_playback_enabled) {
1650 ALOGD("%s: %d: napb: disabling native mode in hardware",
1651 __func__, __LINE__);
1652 audio_route_reset_and_update_path(adev->audio_route,
1653 "true-native-mode");
1654 adev->native_playback_enabled = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001655 } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301656 adev->asrc_mode_enabled) {
1657 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301658 disable_asrc_mode(adev);
1659 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001660 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301661 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001662 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001663 ALOGD("%s: deinit ec ref loopback", __func__);
1664 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1665 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001666
1667 audio_extn_utils_release_snd_device(snd_device);
1668 } else {
1669 if (platform_split_snd_device(adev->platform,
1670 snd_device,
1671 &num_devices,
1672 new_snd_devices) == 0) {
1673 for (i = 0; i < num_devices; i++) {
1674 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1675 }
1676 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001677 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001678
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001679 return 0;
1680}
1681
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001682/*
1683 legend:
1684 uc - existing usecase
1685 new_uc - new usecase
1686 d1, d11, d2 - SND_DEVICE enums
1687 a1, a2 - corresponding ANDROID device enums
1688 B1, B2 - backend strings
1689
1690case 1
1691 uc->dev d1 (a1) B1
1692 new_uc->dev d1 (a1), d2 (a2) B1, B2
1693
1694 resolution: disable and enable uc->dev on d1
1695
1696case 2
1697 uc->dev d1 (a1) B1
1698 new_uc->dev d11 (a1) B1
1699
1700 resolution: need to switch uc since d1 and d11 are related
1701 (e.g. speaker and voice-speaker)
1702 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1703
1704case 3
1705 uc->dev d1 (a1) B1
1706 new_uc->dev d2 (a2) B2
1707
1708 resolution: no need to switch uc
1709
1710case 4
1711 uc->dev d1 (a1) B1
1712 new_uc->dev d2 (a2) B1
1713
1714 resolution: disable enable uc-dev on d2 since backends match
1715 we cannot enable two streams on two different devices if they
1716 share the same backend. e.g. if offload is on speaker device using
1717 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1718 using the same backend, offload must also be switched to voice-handset.
1719
1720case 5
1721 uc->dev d1 (a1) B1
1722 new_uc->dev d1 (a1), d2 (a2) B1
1723
1724 resolution: disable enable uc-dev on d2 since backends match
1725 we cannot enable two streams on two different devices if they
1726 share the same backend.
1727
1728case 6
1729 uc->dev d1 (a1) B1
1730 new_uc->dev d2 (a1) B2
1731
1732 resolution: no need to switch
1733
1734case 7
1735 uc->dev d1 (a1), d2 (a2) B1, B2
1736 new_uc->dev d1 (a1) B1
1737
1738 resolution: no need to switch
1739
Zhou Song4ba65882018-07-09 14:48:07 +08001740case 8
1741 uc->dev d1 (a1) B1
1742 new_uc->dev d11 (a1), d2 (a2) B1, B2
1743 resolution: compared to case 1, for this case, d1 and d11 are related
1744 then need to do the same as case 2 to siwtch to new uc
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301745
1746case 9
1747 uc->dev d1 (a1), d2(a2) B1 B2
1748 new_uc->dev d1 (a1), d22 (a2) B1, B2
1749 resolution: disable enable uc-dev on d2 since backends match
1750 we cannot enable two streams on two different devices if they
1751 share the same backend. This is special case for combo use case
1752 with a2dp and sco devices which uses same backend.
1753 e.g. speaker-a2dp and speaker-btsco
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001754*/
1755static snd_device_t derive_playback_snd_device(void * platform,
1756 struct audio_usecase *uc,
1757 struct audio_usecase *new_uc,
1758 snd_device_t new_snd_device)
1759{
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001760 struct listnode a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001761
1762 snd_device_t d1 = uc->out_snd_device;
1763 snd_device_t d2 = new_snd_device;
1764
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001765 list_init(&a1);
1766 list_init(&a2);
1767
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301768 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301769 case TRANSCODE_LOOPBACK_RX :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001770 assign_devices(&a1, &uc->stream.inout->out_config.device_list);
1771 assign_devices(&a2, &new_uc->stream.inout->out_config.device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301772 break;
1773 default :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001774 assign_devices(&a1, &uc->stream.out->device_list);
1775 assign_devices(&a2, &new_uc->stream.out->device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301776 break;
1777 }
1778
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001779 // Treat as a special case when a1 and a2 are not disjoint
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001780 if (!compare_devices(&a1, &a2) &&
1781 compare_devices_for_any_match(&a1 ,&a2)) {
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001782 snd_device_t d3[2];
1783 int num_devices = 0;
1784 int ret = platform_split_snd_device(platform,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001785 list_length(&a1) > 1 ? d1 : d2,
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001786 &num_devices,
1787 d3);
1788 if (ret < 0) {
1789 if (ret != -ENOSYS) {
1790 ALOGW("%s failed to split snd_device %d",
1791 __func__,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001792 list_length(&a1) > 1 ? d1 : d2);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001793 }
1794 goto end;
1795 }
1796
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001797 if (platform_check_backends_match(d3[0], d3[1])) {
1798 return d2; // case 5
1799 } else {
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301800 if ((list_length(&a1) > 1) && (list_length(&a2) > 1) &&
1801 platform_check_backends_match(d1, d2))
1802 return d2; //case 9
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001803 if (list_length(&a1) > 1)
Samyak Jaind826b502019-07-17 16:16:42 +05301804 return d1; //case 7
Garmond Leungb9eeba42018-09-18 11:10:41 -07001805 // check if d1 is related to any of d3's
1806 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001807 return d1; // case 1
1808 else
1809 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001810 }
1811 } else {
1812 if (platform_check_backends_match(d1, d2)) {
1813 return d2; // case 2, 4
1814 } else {
1815 return d1; // case 6, 3
1816 }
1817 }
1818
1819end:
1820 return d2; // return whatever was calculated before.
1821}
1822
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001823static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301824 struct audio_usecase *uc_info,
1825 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001826{
1827 struct listnode *node;
1828 struct audio_usecase *usecase;
1829 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301830 snd_device_t uc_derive_snd_device;
1831 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001832 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1833 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001834 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301835 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001836 /*
1837 * This function is to make sure that all the usecases that are active on
1838 * the hardware codec backend are always routed to any one device that is
1839 * handled by the hardware codec.
1840 * For example, if low-latency and deep-buffer usecases are currently active
1841 * on speaker and out_set_parameters(headset) is received on low-latency
1842 * output, then we have to make sure deep-buffer is also switched to headset,
1843 * because of the limitation that both the devices cannot be enabled
1844 * at the same time as they share the same backend.
1845 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001846 /*
1847 * This call is to check if we need to force routing for a particular stream
1848 * If there is a backend configuration change for the device when a
1849 * new stream starts, then ADM needs to be closed and re-opened with the new
1850 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001851 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001852 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001853 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1854 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301855 /* For a2dp device reconfigure all active sessions
1856 * with new AFE encoder format based on a2dp state
1857 */
1858 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301859 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device ||
1860 SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP == snd_device) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301861 audio_extn_a2dp_is_force_device_switch()) {
1862 force_routing = true;
1863 force_restart_session = true;
1864 }
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001865
1866 /*
1867 * Island cfg and power mode config needs to set before AFE port start.
1868 * Set force routing in case of voice device was enable before.
1869 */
1870 if (uc_info->type == VOICE_CALL &&
1871 voice_extn_is_voice_power_mode_supported() &&
Kunlei Zhang67cc7072020-12-18 17:16:49 +08001872 is_supported_conc_usecase_for_power_mode_call(adev) &&
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001873 platform_check_and_update_island_power_status(adev->platform,
1874 uc_info,
1875 snd_device)) {
1876 force_routing = true;
1877 ALOGD("%s:becf: force routing %d for power mode supported device",
1878 __func__, force_routing);
1879 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301880 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1881
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001882 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001883 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001884 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001885 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1886 switch_device[i] = false;
1887
1888 list_for_each(node, &adev->usecase_list) {
1889 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001890
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301891 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1892 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301893 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301894 platform_get_snd_device_name(usecase->out_snd_device),
1895 platform_check_backends_match(snd_device, usecase->out_snd_device));
Rahul Sharma99770982019-03-06 17:05:26 +05301896 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
1897 (usecase->type != PCM_PASSTHROUGH)) {
Ashish Jain6a65b352017-03-21 17:24:40 +05301898 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1899 usecase, uc_info, snd_device);
1900 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001901 (is_codec_backend_out_device_type(&usecase->device_list) ||
1902 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1903 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_DEVICE) ||
1904 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_HEADSET) ||
1905 is_a2dp_out_device_type(&usecase->device_list) ||
1906 is_sco_out_device_type(&usecase->device_list)) &&
Ashish Jain6a65b352017-03-21 17:24:40 +05301907 ((force_restart_session) ||
1908 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301909 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1910 __func__, use_case_table[usecase->id],
1911 platform_get_snd_device_name(usecase->out_snd_device));
1912 disable_audio_route(adev, usecase);
1913 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301914 /* Enable existing usecase on derived playback device */
1915 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301916 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301917 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001918 }
1919 }
1920
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301921 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1922 num_uc_to_switch);
1923
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001924 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001925 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001926
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301927 /* Make sure the previous devices to be disabled first and then enable the
1928 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001929 list_for_each(node, &adev->usecase_list) {
1930 usecase = node_to_item(node, struct audio_usecase, list);
1931 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001932 /* Check if output sound device to be switched can be split and if any
1933 of the split devices match with derived sound device */
1934 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1935 &num_devices, split_snd_devices) == 0) {
1936 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
1937 for (i = 0; i < num_devices; i++) {
1938 /* Disable devices that do not match with derived sound device */
1939 if (split_snd_devices[i] != derive_snd_device[usecase->id])
1940 disable_snd_device(adev, split_snd_devices[i]);
1941 }
1942 } else {
1943 disable_snd_device(adev, usecase->out_snd_device);
1944 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001945 }
1946 }
1947
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001948 list_for_each(node, &adev->usecase_list) {
1949 usecase = node_to_item(node, struct audio_usecase, list);
1950 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001951 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1952 &num_devices, split_snd_devices) == 0) {
1953 /* Enable derived sound device only if it does not match with
1954 one of the split sound devices. This is because the matching
1955 sound device was not disabled */
1956 bool should_enable = true;
1957 for (i = 0; i < num_devices; i++) {
1958 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
1959 should_enable = false;
1960 break;
1961 }
1962 }
1963 if (should_enable)
1964 enable_snd_device(adev, derive_snd_device[usecase->id]);
1965 } else {
1966 enable_snd_device(adev, derive_snd_device[usecase->id]);
1967 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001968 }
1969 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001970
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001971 /* Re-route all the usecases on the shared backend other than the
1972 specified usecase to new snd devices */
1973 list_for_each(node, &adev->usecase_list) {
1974 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301975 /* Update the out_snd_device only before enabling the audio route */
1976 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301977 usecase->out_snd_device = derive_snd_device[usecase->id];
Lakshman Chaluvarajuab7e5572020-10-28 19:29:23 +05301978 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
1979 use_case_table[usecase->id],
1980 platform_get_snd_device_name(usecase->out_snd_device));
1981 /* Update voc calibration before enabling Voice/VoIP route */
1982 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL)
1983 status = platform_switch_voice_call_device_post(adev->platform,
1984 usecase->out_snd_device,
1985 platform_get_input_snd_device(
1986 adev->platform, NULL,
1987 &uc_info->device_list,
1988 usecase->type));
1989 enable_audio_route(adev, usecase);
1990 if (usecase->stream.out && usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
1991 out_set_voip_volume(&usecase->stream.out->stream,
1992 usecase->stream.out->volume_l,
1993 usecase->stream.out->volume_r);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301994 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001995 }
1996 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001997 }
1998}
1999
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302000static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002001 struct audio_usecase *uc_info,
2002 snd_device_t snd_device)
2003{
2004 struct listnode *node;
2005 struct audio_usecase *usecase;
2006 bool switch_device[AUDIO_USECASE_MAX];
2007 int i, num_uc_to_switch = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002008 int backend_check_cond = is_codec_backend_out_device_type(&uc_info->device_list);
kunleiz5cd52b82016-11-07 17:22:52 +08002009 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002010
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302011 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
2012 snd_device);
2013 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05302014
2015 /*
2016 * Make sure out devices is checked against out codec backend device and
2017 * also in devices against in codec backend. Checking out device against in
2018 * codec backend or vice versa causes issues.
2019 */
2020 if (uc_info->type == PCM_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002021 backend_check_cond = is_codec_backend_in_device_type(&uc_info->device_list);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08002022
2023 /*
2024 * Island cfg and power mode config needs to set before AFE port start.
2025 * Set force routing in case of voice device was enable before.
2026 */
2027
2028 if (uc_info->type == VOICE_CALL &&
2029 voice_extn_is_voice_power_mode_supported() &&
Kunlei Zhang67cc7072020-12-18 17:16:49 +08002030 is_supported_conc_usecase_for_power_mode_call(adev) &&
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08002031 platform_check_and_update_island_power_status(adev->platform,
2032 uc_info,
2033 snd_device)) {
2034 force_routing = true;
2035 ALOGD("%s:becf: force routing %d for power mode supported device",
2036 __func__, force_routing);
2037 }
2038
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002039 /*
2040 * This function is to make sure that all the active capture usecases
2041 * are always routed to the same input sound device.
2042 * For example, if audio-record and voice-call usecases are currently
2043 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
2044 * is received for voice call then we have to make sure that audio-record
2045 * usecase is also switched to earpiece i.e. voice-dmic-ef,
2046 * because of the limitation that two devices cannot be enabled
2047 * at the same time if they share the same backend.
2048 */
2049 for (i = 0; i < AUDIO_USECASE_MAX; i++)
2050 switch_device[i] = false;
2051
2052 list_for_each(node, &adev->usecase_list) {
2053 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05302054 /*
2055 * TODO: Enhance below condition to handle BT sco/USB multi recording
2056 */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302057
2058 bool capture_uc_needs_routing = usecase->type != PCM_PLAYBACK && (usecase != uc_info &&
2059 (usecase->in_snd_device != snd_device || force_routing));
2060 bool call_proxy_snd_device = platform_is_call_proxy_snd_device(snd_device) ||
2061 platform_is_call_proxy_snd_device(usecase->in_snd_device);
2062 if (capture_uc_needs_routing && !call_proxy_snd_device &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002063 ((backend_check_cond &&
2064 (is_codec_backend_in_device_type(&usecase->device_list) ||
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08002065 (usecase->type == VOIP_CALL))) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08002066 ((uc_info->type == VOICE_CALL &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002067 is_single_device_type_equal(&usecase->device_list,
2068 AUDIO_DEVICE_IN_VOICE_CALL)) ||
Anver sadhique4fdc6992022-01-21 12:26:28 +05302069 platform_check_all_backends_match(snd_device,\
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002070 usecase->in_snd_device))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07002071 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05302072 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..",
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002073 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07002074 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002075 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002076 switch_device[usecase->id] = true;
2077 num_uc_to_switch++;
2078 }
2079 }
2080
2081 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07002082 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002083
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05302084 /* Make sure the previous devices to be disabled first and then enable the
2085 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002086 list_for_each(node, &adev->usecase_list) {
2087 usecase = node_to_item(node, struct audio_usecase, list);
2088 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002089 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08002090 }
2091 }
2092
2093 list_for_each(node, &adev->usecase_list) {
2094 usecase = node_to_item(node, struct audio_usecase, list);
2095 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002096 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002097 }
2098 }
2099
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002100 /* Re-route all the usecases on the shared backend other than the
2101 specified usecase to new snd devices */
2102 list_for_each(node, &adev->usecase_list) {
2103 usecase = node_to_item(node, struct audio_usecase, list);
2104 /* Update the in_snd_device only before enabling the audio route */
2105 if (switch_device[usecase->id] ) {
2106 usecase->in_snd_device = snd_device;
Lakshman Chaluvarajuab7e5572020-10-28 19:29:23 +05302107 /* Update voc calibration before enabling Voice/VoIP route */
2108 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
2109 snd_device_t voip_snd_device;
2110 voip_snd_device = platform_get_output_snd_device(adev->platform,
2111 usecase->stream.out,
2112 usecase->type);
2113 status = platform_switch_voice_call_device_post(adev->platform,
2114 voip_snd_device,
2115 usecase->in_snd_device);
kunleiz5cd52b82016-11-07 17:22:52 +08002116 }
Lakshman Chaluvarajuab7e5572020-10-28 19:29:23 +05302117 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002118 }
2119 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002120 }
2121}
2122
Mingming Yin3a941d42016-02-17 18:08:05 -08002123static void reset_hdmi_sink_caps(struct stream_out *out) {
2124 int i = 0;
2125
2126 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
2127 out->supported_channel_masks[i] = 0;
2128 }
2129 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
2130 out->supported_formats[i] = 0;
2131 }
2132 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
2133 out->supported_sample_rates[i] = 0;
2134 }
2135}
2136
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002137/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08002138static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002139{
Mingming Yin3a941d42016-02-17 18:08:05 -08002140 int ret = 0, i = 0, j = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002141 int channels = platform_edid_get_max_channels_v2(out->dev->platform,
2142 out->extconn.cs.controller,
2143 out->extconn.cs.stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002144
Mingming Yin3a941d42016-02-17 18:08:05 -08002145 reset_hdmi_sink_caps(out);
2146
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002147 /* Cache ext disp type */
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002148 ret = platform_get_ext_disp_type_v2(adev->platform,
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002149 out->extconn.cs.controller,
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002150 out->extconn.cs.stream);
2151 if(ret < 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002152 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07002153 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002154 }
2155
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002156 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002157 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08002158 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002159 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08002160 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
2161 case 6:
2162 ALOGV("%s: HDMI supports 5.1 channels", __func__);
2163 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
2164 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
2165 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
2166 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
2167 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002168 break;
2169 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08002170 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002171 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002172 break;
2173 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002174
2175 // check channel format caps
2176 i = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002177 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_AC3,
2178 out->extconn.cs.controller,
2179 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002180 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
2181 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
2182 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
2183 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
2184 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
2185 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
2186 }
2187
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002188 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD,
2189 out->extconn.cs.controller,
2190 out->extconn.cs.stream)) {
Ben Romberger1aaaf862017-04-06 17:49:46 -07002191 ALOGV(":%s HDMI supports TRUE HD format", __func__);
2192 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
2193 }
2194
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002195 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS,
2196 out->extconn.cs.controller,
2197 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002198 ALOGV(":%s HDMI supports DTS format", __func__);
2199 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
2200 }
2201
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002202 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS_HD,
2203 out->extconn.cs.controller,
2204 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002205 ALOGV(":%s HDMI supports DTS HD format", __func__);
2206 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
2207 }
2208
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002209 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_IEC61937,
2210 out->extconn.cs.controller,
2211 out->extconn.cs.stream)) {
Naresh Tanniru928f0862017-04-07 16:44:23 -07002212 ALOGV(":%s HDMI supports IEC61937 format", __func__);
2213 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
2214 }
2215
Mingming Yin3a941d42016-02-17 18:08:05 -08002216
2217 // check sample rate caps
2218 i = 0;
2219 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002220 if (platform_is_edid_supported_sample_rate_v2(out->dev->platform, out_hdmi_sample_rates[j],
2221 out->extconn.cs.controller,
2222 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002223 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
2224 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
2225 }
2226 }
2227
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002228 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002229}
2230
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002231static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
2232 uint32_t *supported_sample_rates __unused,
2233 uint32_t max_rates __unused)
2234{
2235 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
2236 supported_sample_rates,
2237 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05302238 ssize_t i = 0;
2239
2240 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002241 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
2242 supported_sample_rates[i]);
2243 }
2244 return count;
2245}
2246
2247static inline int read_usb_sup_channel_masks(bool is_playback,
2248 audio_channel_mask_t *supported_channel_masks,
2249 uint32_t max_masks)
2250{
2251 int channels = audio_extn_usb_get_max_channels(is_playback);
2252 int channel_count;
2253 uint32_t num_masks = 0;
2254 if (channels > MAX_HIFI_CHANNEL_COUNT)
2255 channels = MAX_HIFI_CHANNEL_COUNT;
2256
2257 if (is_playback) {
Eric Laurent68a87112019-05-01 18:07:29 -07002258 // start from 2 channels as framework currently doesn't support mono.
2259 if (channels >= FCC_2) {
2260 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(FCC_2);
2261 }
2262 for (channel_count = FCC_2;
2263 channel_count <= channels && num_masks < max_masks;
2264 ++channel_count) {
2265 supported_channel_masks[num_masks++] =
2266 audio_channel_mask_for_index_assignment_from_count(channel_count);
2267 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002268 } else {
vincenttewf51c94e2019-05-07 10:28:53 +08002269 // For capture we report all supported channel masks from 1 channel up.
2270 channel_count = MIN_CHANNEL_COUNT;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002271 // audio_channel_in_mask_from_count() does the right conversion to either positional or
2272 // indexed mask
Eric Laurent68a87112019-05-01 18:07:29 -07002273 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
2274 audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
2275 if (channel_count <= FCC_2) {
2276 mask = audio_channel_in_mask_from_count(channel_count);
2277 supported_channel_masks[num_masks++] = mask;
2278 }
2279 const audio_channel_mask_t index_mask =
2280 audio_channel_mask_for_index_assignment_from_count(channel_count);
2281 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
2282 supported_channel_masks[num_masks++] = index_mask;
2283 }
2284 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002285 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302286
vincenttewf51c94e2019-05-07 10:28:53 +08002287 for (size_t i = 0; i < num_masks; ++i) {
2288 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
2289 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302290 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002291 return num_masks;
2292}
2293
2294static inline int read_usb_sup_formats(bool is_playback __unused,
2295 audio_format_t *supported_formats,
2296 uint32_t max_formats __unused)
2297{
2298 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
2299 switch (bitwidth) {
2300 case 24:
2301 // XXX : usb.c returns 24 for s24 and s24_le?
2302 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
2303 break;
2304 case 32:
2305 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
2306 break;
2307 case 16:
2308 default :
2309 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
2310 break;
2311 }
2312 ALOGV("%s: %s supported format %d", __func__,
2313 is_playback ? "P" : "C", bitwidth);
2314 return 1;
2315}
2316
2317static inline int read_usb_sup_params_and_compare(bool is_playback,
2318 audio_format_t *format,
2319 audio_format_t *supported_formats,
2320 uint32_t max_formats,
2321 audio_channel_mask_t *mask,
2322 audio_channel_mask_t *supported_channel_masks,
2323 uint32_t max_masks,
2324 uint32_t *rate,
2325 uint32_t *supported_sample_rates,
2326 uint32_t max_rates) {
2327 int ret = 0;
2328 int num_formats;
2329 int num_masks;
2330 int num_rates;
2331 int i;
2332
2333 num_formats = read_usb_sup_formats(is_playback, supported_formats,
2334 max_formats);
2335 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
2336 max_masks);
2337
2338 num_rates = read_usb_sup_sample_rates(is_playback,
2339 supported_sample_rates, max_rates);
2340
2341#define LUT(table, len, what, dflt) \
2342 for (i=0; i<len && (table[i] != what); i++); \
2343 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
2344
2345 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
2346 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
2347 LUT(supported_sample_rates, num_rates, *rate, 0);
2348
2349#undef LUT
2350 return ret < 0 ? -EINVAL : 0; // HACK TBD
2351}
2352
Alexy Josephb1379942016-01-29 15:49:38 -08002353audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002354 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002355{
2356 struct audio_usecase *usecase;
2357 struct listnode *node;
2358
2359 list_for_each(node, &adev->usecase_list) {
2360 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002361 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002362 ALOGV("%s: usecase id %d", __func__, usecase->id);
2363 return usecase->id;
2364 }
2365 }
2366 return USECASE_INVALID;
2367}
2368
Alexy Josephb1379942016-01-29 15:49:38 -08002369struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002370 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002371{
2372 struct audio_usecase *usecase;
2373 struct listnode *node;
2374
2375 list_for_each(node, &adev->usecase_list) {
2376 usecase = node_to_item(node, struct audio_usecase, list);
2377 if (usecase->id == uc_id)
2378 return usecase;
2379 }
2380 return NULL;
2381}
2382
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302383/*
2384 * is a true native playback active
2385 */
2386bool audio_is_true_native_stream_active(struct audio_device *adev)
2387{
2388 bool active = false;
2389 int i = 0;
2390 struct listnode *node;
2391
2392 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
2393 ALOGV("%s:napb: not in true mode or non hdphones device",
2394 __func__);
2395 active = false;
2396 goto exit;
2397 }
2398
2399 list_for_each(node, &adev->usecase_list) {
2400 struct audio_usecase *uc;
2401 uc = node_to_item(node, struct audio_usecase, list);
2402 struct stream_out *curr_out =
2403 (struct stream_out*) uc->stream.out;
2404
2405 if (curr_out && PCM_PLAYBACK == uc->type) {
2406 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
2407 "(%d) device %s", __func__, i++, use_case_table[uc->id],
2408 uc->id, curr_out->sample_rate,
2409 curr_out->bit_width,
2410 platform_get_snd_device_name(uc->out_snd_device));
2411
2412 if (is_offload_usecase(uc->id) &&
2413 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
2414 active = true;
2415 ALOGD("%s:napb:native stream detected", __func__);
2416 }
2417 }
2418 }
2419exit:
2420 return active;
2421}
2422
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002423uint32_t adev_get_dsp_bit_width_enforce_mode()
2424{
2425 if (adev == NULL) {
2426 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
2427 return 0;
2428 }
2429 return adev->dsp_bit_width_enforce_mode;
2430}
2431
2432static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
2433{
2434 char value[PROPERTY_VALUE_MAX];
2435 int trial;
2436 uint32_t dsp_bit_width_enforce_mode = 0;
2437
2438 if (!mixer) {
2439 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
2440 __func__);
2441 return 0;
2442 }
2443
2444 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
2445 value, NULL) > 0) {
2446 trial = atoi(value);
2447 switch (trial) {
2448 case 16:
2449 dsp_bit_width_enforce_mode = 16;
2450 break;
2451 case 24:
2452 dsp_bit_width_enforce_mode = 24;
2453 break;
2454 case 32:
2455 dsp_bit_width_enforce_mode = 32;
2456 break;
2457 default:
2458 dsp_bit_width_enforce_mode = 0;
2459 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
2460 break;
2461 }
2462 }
2463
2464 return dsp_bit_width_enforce_mode;
2465}
2466
2467static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
2468 uint32_t enforce_mode,
2469 bool enable)
2470{
2471 struct mixer_ctl *ctl = NULL;
2472 const char *mixer_ctl_name = "ASM Bit Width";
2473 uint32_t asm_bit_width_mode = 0;
2474
2475 if (enforce_mode == 0) {
2476 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
2477 return;
2478 }
2479
2480 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
2481 if (!ctl) {
2482 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2483 __func__, mixer_ctl_name);
2484 return;
2485 }
2486
2487 if (enable)
2488 asm_bit_width_mode = enforce_mode;
2489 else
2490 asm_bit_width_mode = 0;
2491
2492 ALOGV("%s DSP bit width feature status is %d width=%d",
2493 __func__, enable, asm_bit_width_mode);
2494 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2495 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2496 asm_bit_width_mode);
2497
2498 return;
2499}
2500
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302501/*
2502 * if native DSD playback active
2503 */
2504bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2505{
2506 bool active = false;
2507 struct listnode *node = NULL;
2508 struct audio_usecase *uc = NULL;
2509 struct stream_out *curr_out = NULL;
2510
2511 list_for_each(node, &adev->usecase_list) {
2512 uc = node_to_item(node, struct audio_usecase, list);
2513 curr_out = (struct stream_out*) uc->stream.out;
2514
2515 if (curr_out && PCM_PLAYBACK == uc->type &&
2516 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2517 active = true;
2518 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302519 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302520 }
2521 }
2522 return active;
2523}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302524
2525static bool force_device_switch(struct audio_usecase *usecase)
2526{
2527 bool ret = false;
2528 bool is_it_true_mode = false;
2529
Zhou Song30f2c3e2018-02-08 14:02:15 +08002530 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302531 usecase->type == TRANSCODE_LOOPBACK_RX ||
2532 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002533 return false;
2534 }
2535
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002536 if(usecase->stream.out == NULL) {
2537 ALOGE("%s: stream.out is NULL", __func__);
2538 return false;
2539 }
2540
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302541 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002542 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002543 (compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADSET) ||
2544 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADPHONE))) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302545 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2546 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2547 (!is_it_true_mode && adev->native_playback_enabled)){
2548 ret = true;
2549 ALOGD("napb: time to toggle native mode");
2550 }
2551 }
2552
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302553 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302554 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2555 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002556 if(is_a2dp_out_device_type(&usecase->stream.out->device_list) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302557 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302558 ALOGD("Force a2dp device switch to update new encoder config");
2559 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002560 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302561
Florian Pfister1a84f312018-07-19 14:38:18 +02002562 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302563 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2564 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002565 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302566 return ret;
2567}
2568
Aalique Grahame22e49102018-12-18 14:23:57 -08002569static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2570{
2571 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2572}
2573
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302574bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2575{
2576 bool ret=false;
2577 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
Zhou Song5657f492019-08-07 11:30:39 +08002578 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
2579 out_snd_device == SND_DEVICE_OUT_BT_SCO_SWB) ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302580 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2581 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
Zhou Song5657f492019-08-07 11:30:39 +08002582 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302583 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
Mingshu Pang16093502020-04-20 11:21:16 +08002584 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC ||
2585 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC)
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302586 ret = true;
2587
2588 return ret;
2589}
2590
2591bool is_a2dp_device(snd_device_t out_snd_device)
2592{
2593 bool ret=false;
2594 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2595 ret = true;
2596
2597 return ret;
2598}
2599
2600bool is_bt_soc_on(struct audio_device *adev)
2601{
2602 struct mixer_ctl *ctl;
2603 char *mixer_ctl_name = "BT SOC status";
2604 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2605 bool bt_soc_status = true;
2606 if (!ctl) {
2607 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2608 __func__, mixer_ctl_name);
2609 /*This is to ensure we dont break targets which dont have the kernel change*/
2610 return true;
2611 }
2612 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2613 ALOGD("BT SOC status: %d",bt_soc_status);
2614 return bt_soc_status;
2615}
2616
Zhou Song331c8e52019-08-26 14:16:12 +08002617static int configure_btsco_sample_rate(snd_device_t snd_device)
2618{
2619 struct mixer_ctl *ctl = NULL;
2620 struct mixer_ctl *ctl_sr_rx = NULL, *ctl_sr_tx = NULL, *ctl_sr = NULL;
2621 char *rate_str = NULL;
2622 bool is_rx_dev = true;
2623
2624 if (is_btsco_device(snd_device, snd_device)) {
2625 ctl_sr_tx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate TX");
2626 ctl_sr_rx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate RX");
2627 if (!ctl_sr_tx || !ctl_sr_rx) {
2628 ctl_sr = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate");
2629 if (!ctl_sr)
2630 return -ENOSYS;
2631 }
2632
2633 switch (snd_device) {
2634 case SND_DEVICE_OUT_BT_SCO:
2635 rate_str = "KHZ_8";
2636 break;
2637 case SND_DEVICE_IN_BT_SCO_MIC_NREC:
2638 case SND_DEVICE_IN_BT_SCO_MIC:
2639 rate_str = "KHZ_8";
2640 is_rx_dev = false;
2641 break;
2642 case SND_DEVICE_OUT_BT_SCO_WB:
2643 rate_str = "KHZ_16";
2644 break;
2645 case SND_DEVICE_IN_BT_SCO_MIC_WB_NREC:
2646 case SND_DEVICE_IN_BT_SCO_MIC_WB:
2647 rate_str = "KHZ_16";
2648 is_rx_dev = false;
2649 break;
2650 default:
2651 return 0;
2652 }
2653
2654 ctl = (ctl_sr == NULL) ? (is_rx_dev ? ctl_sr_rx : ctl_sr_tx) : ctl_sr;
2655 if (mixer_ctl_set_enum_by_string(ctl, rate_str) != 0)
2656 return -ENOSYS;
2657 }
2658 return 0;
2659}
2660
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302661int out_standby_l(struct audio_stream *stream);
2662
Eric Laurent637e2d42018-11-15 12:24:31 -08002663struct stream_in *adev_get_active_input(const struct audio_device *adev)
2664{
2665 struct listnode *node;
2666 struct stream_in *last_active_in = NULL;
2667
2668 /* Get last added active input.
2669 * TODO: We may use a priority mechanism to pick highest priority active source */
2670 list_for_each(node, &adev->usecase_list)
2671 {
2672 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2673 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL)
2674 last_active_in = usecase->stream.in;
2675 }
2676
2677 return last_active_in;
2678}
2679
2680struct stream_in *get_voice_communication_input(const struct audio_device *adev)
2681{
2682 struct listnode *node;
2683
2684 /* First check active inputs with voice communication source and then
2685 * any input if audio mode is in communication */
2686 list_for_each(node, &adev->usecase_list)
2687 {
2688 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2689 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
2690 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
2691 return usecase->stream.in;
2692 }
2693 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION)
2694 return adev_get_active_input(adev);
2695
2696 return NULL;
2697}
2698
Carter Hsu2e429db2019-05-14 18:50:52 +08002699/*
2700 * Aligned with policy.h
2701 */
2702static inline int source_priority(int inputSource)
2703{
2704 switch (inputSource) {
2705 case AUDIO_SOURCE_VOICE_COMMUNICATION:
2706 return 9;
2707 case AUDIO_SOURCE_CAMCORDER:
2708 return 8;
2709 case AUDIO_SOURCE_VOICE_PERFORMANCE:
2710 return 7;
2711 case AUDIO_SOURCE_UNPROCESSED:
2712 return 6;
2713 case AUDIO_SOURCE_MIC:
2714 return 5;
2715 case AUDIO_SOURCE_ECHO_REFERENCE:
2716 return 4;
2717 case AUDIO_SOURCE_FM_TUNER:
2718 return 3;
2719 case AUDIO_SOURCE_VOICE_RECOGNITION:
2720 return 2;
2721 case AUDIO_SOURCE_HOTWORD:
2722 return 1;
2723 default:
2724 break;
2725 }
2726 return 0;
2727}
2728
2729static struct stream_in *get_priority_input(struct audio_device *adev)
2730{
2731 struct listnode *node;
2732 struct audio_usecase *usecase;
2733 int last_priority = 0, priority;
2734 struct stream_in *priority_in = NULL;
2735 struct stream_in *in;
2736
2737 list_for_each(node, &adev->usecase_list) {
2738 usecase = node_to_item(node, struct audio_usecase, list);
2739 if (usecase->type == PCM_CAPTURE) {
2740 in = usecase->stream.in;
2741 if (!in)
2742 continue;
2743 priority = source_priority(in->source);
2744
2745 if (priority > last_priority) {
2746 last_priority = priority;
2747 priority_in = in;
2748 }
2749 }
2750 }
2751 return priority_in;
2752}
2753
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002754int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002755{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002756 snd_device_t out_snd_device = SND_DEVICE_NONE;
2757 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002758 struct audio_usecase *usecase = NULL;
2759 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002760 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002761 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302762 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002763 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002764 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002765
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302766 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2767
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002768 usecase = get_usecase_from_list(adev, uc_id);
2769 if (usecase == NULL) {
2770 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2771 return -EINVAL;
2772 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002773
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002774 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002775 (usecase->type == VOIP_CALL) ||
Derek Chena30a5f42019-12-03 11:17:09 -05002776 (usecase->type == PCM_HFP_CALL)||
Fei Tongaffdf732020-02-20 20:39:05 +08002777 (usecase->type == ICC_CALL) ||
2778 (usecase->type == SYNTH_LOOPBACK)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302779 if(usecase->stream.out == NULL) {
2780 ALOGE("%s: stream.out is NULL", __func__);
2781 return -EINVAL;
2782 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002783 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS)) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002784 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev,
2785 uc_id);
2786 in_snd_device = audio_extn_auto_hal_get_input_snd_device(adev,
2787 uc_id);
2788 } else {
2789 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302790 usecase->stream.out, usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002791 in_snd_device = platform_get_input_snd_device(adev->platform,
2792 NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302793 &usecase->stream.out->device_list,
2794 usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002795 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002796 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302797 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302798 if (usecase->stream.inout == NULL) {
2799 ALOGE("%s: stream.inout is NULL", __func__);
2800 return -EINVAL;
2801 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002802 assign_devices(&stream_out.device_list, &usecase->stream.inout->out_config.device_list);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302803 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2804 stream_out.format = usecase->stream.inout->out_config.format;
2805 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
Jaideep Sharma477917f2020-03-13 18:13:33 +05302806 out_snd_device = platform_get_output_snd_device(adev->platform, &stream_out, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002807 assign_devices(&usecase->device_list,
2808 &usecase->stream.inout->out_config.device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302809 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2810 if (usecase->stream.inout == NULL) {
2811 ALOGE("%s: stream.inout is NULL", __func__);
2812 return -EINVAL;
2813 }
Manisha Agarwal03297972020-04-17 15:36:55 +05302814 struct listnode out_devices;
2815 list_init(&out_devices);
2816 in_snd_device = platform_get_input_snd_device(adev->platform, NULL,
2817 &out_devices, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002818 assign_devices(&usecase->device_list,
2819 &usecase->stream.inout->in_config.device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002820 } else {
2821 /*
2822 * If the voice call is active, use the sound devices of voice call usecase
2823 * so that it would not result any device switch. All the usecases will
2824 * be switched to new device when select_devices() is called for voice call
2825 * usecase. This is to avoid switching devices for voice call when
2826 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002827 * choose voice call device only if the use case device is
2828 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002829 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002830 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002831 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002832 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002833 if ((vc_usecase) && ((is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2834 is_codec_backend_out_device_type(&usecase->device_list)) ||
2835 (is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2836 is_codec_backend_in_device_type(&usecase->device_list)) ||
2837 is_single_device_type_equal(&vc_usecase->device_list,
2838 AUDIO_DEVICE_OUT_HEARING_AID) ||
2839 is_single_device_type_equal(&usecase->device_list,
Robert Lee8a6aaf32019-09-20 16:40:19 +08002840 AUDIO_DEVICE_IN_VOICE_CALL) ||
2841 (is_single_device_type_equal(&usecase->device_list,
Gautam Manam8fa06162021-09-24 10:41:29 +05302842 AUDIO_DEVICE_IN_BUILTIN_MIC) &&
2843 is_single_device_type_equal(&vc_usecase->device_list,
2844 AUDIO_DEVICE_OUT_USB_HEADSET)) ||
2845 (is_single_device_type_equal(&usecase->device_list,
Robert Lee8a6aaf32019-09-20 16:40:19 +08002846 AUDIO_DEVICE_IN_USB_HEADSET) &&
2847 is_single_device_type_equal(&vc_usecase->device_list,
Kamalakar Yalasiri5edba852021-01-28 14:52:38 +05302848 AUDIO_DEVICE_OUT_USB_HEADSET))||
Gautam Manamf4002142021-09-13 22:05:56 +05302849 (is_single_device_type_equal(&usecase->device_list,
2850 AUDIO_DEVICE_IN_USB_HEADSET) &&
2851 is_codec_backend_out_device_type(&vc_usecase->device_list)) ||
Kamalakar Yalasiri5edba852021-01-28 14:52:38 +05302852 (is_single_device_type_equal(&usecase->device_list,
2853 AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) &&
2854 is_codec_backend_out_device_type(&vc_usecase->device_list)))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002855 in_snd_device = vc_usecase->in_snd_device;
2856 out_snd_device = vc_usecase->out_snd_device;
2857 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002858 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002859 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002860 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002861 if ((voip_usecase != NULL) &&
2862 (usecase->type == PCM_PLAYBACK) &&
2863 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002864 out_snd_device_backend_match = platform_check_backends_match(
2865 voip_usecase->out_snd_device,
2866 platform_get_output_snd_device(
2867 adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302868 usecase->stream.out, usecase->type));
yidongh02ef86f2017-04-21 15:36:04 +08002869 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002870 if ((voip_usecase) && (is_codec_backend_out_device_type(&voip_usecase->device_list) &&
2871 (is_codec_backend_out_device_type(&usecase->device_list) ||
2872 is_codec_backend_in_device_type(&usecase->device_list)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002873 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002874 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002875 in_snd_device = voip_usecase->in_snd_device;
2876 out_snd_device = voip_usecase->out_snd_device;
2877 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002878 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002879 hfp_ucid = audio_extn_hfp_get_usecase();
2880 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002881 if ((hfp_usecase) && is_codec_backend_out_device_type(&hfp_usecase->device_list)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002882 in_snd_device = hfp_usecase->in_snd_device;
2883 out_snd_device = hfp_usecase->out_snd_device;
2884 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002885 }
2886 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302887 if (usecase->stream.out == NULL) {
2888 ALOGE("%s: stream.out is NULL", __func__);
2889 return -EINVAL;
2890 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002891 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002892 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002893 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002894 struct stream_out *voip_out = adev->primary_output;
2895 struct stream_in *voip_in = get_voice_communication_input(adev);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002896 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS))
Guodong Hu267bdf82019-08-12 19:22:32 +08002897 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev, uc_id);
2898 else
2899 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302900 usecase->stream.out,
2901 usecase->type);
kunleizdcf967a2018-08-07 17:09:11 +08002902 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizdcf967a2018-08-07 17:09:11 +08002903
Eric Laurent637e2d42018-11-15 12:24:31 -08002904 if (voip_usecase)
2905 voip_out = voip_usecase->stream.out;
2906
2907 if (usecase->stream.out == voip_out && voip_in != NULL)
2908 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002909 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002910 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302911 if (usecase->stream.in == NULL) {
2912 ALOGE("%s: stream.in is NULL", __func__);
2913 return -EINVAL;
2914 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002915 assign_devices(&usecase->device_list, &usecase->stream.in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002916 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002917 if (in_snd_device == SND_DEVICE_NONE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002918 struct listnode out_devices;
Eric Laurent637e2d42018-11-15 12:24:31 -08002919 struct stream_in *voip_in = get_voice_communication_input(adev);
Carter Hsu2e429db2019-05-14 18:50:52 +08002920 struct stream_in *priority_in = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08002921
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002922 list_init(&out_devices);
Eric Laurent637e2d42018-11-15 12:24:31 -08002923 if (voip_in != NULL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002924 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
2925 USECASE_AUDIO_PLAYBACK_VOIP);
2926
Carter Hsu2e429db2019-05-14 18:50:52 +08002927 usecase->stream.in->enable_ec_port = false;
2928
Zhou Song503196b2021-07-23 17:31:05 +08002929 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY ||
2930 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY2) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002931 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_TELEPHONY_TX, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002932 } else if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002933 assign_devices(&out_devices, &voip_usecase->stream.out->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002934 } else if (adev->primary_output &&
2935 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002936 assign_devices(&out_devices, &adev->primary_output->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002937 } else {
2938 /* forcing speaker o/p device to get matching i/p pair
2939 in case o/p is not routed from same primary HAL */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002940 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002941 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002942 priority_in = voip_in;
2943 } else {
2944 /* get the input with the highest priority source*/
2945 priority_in = get_priority_input(adev);
2946
Susan Wang727dd6b2021-03-26 11:28:59 -04002947 if (!priority_in ||
2948 audio_extn_auto_hal_overwrite_priority_for_auto(usecase->stream.in))
Carter Hsu2e429db2019-05-14 18:50:52 +08002949 priority_in = usecase->stream.in;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002950 }
Huicheng Liu1404ba12020-09-11 01:03:25 -04002951 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_IN_BUS)){
2952 in_snd_device = audio_extn_auto_hal_get_snd_device_for_car_audio_stream(priority_in->car_audio_stream);
2953 }
2954 else
2955 in_snd_device = platform_get_input_snd_device(adev->platform,
2956 priority_in,
2957 &out_devices,
2958 usecase->type);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002959 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002960 }
2961 }
2962
2963 if (out_snd_device == usecase->out_snd_device &&
2964 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302965
2966 if (!force_device_switch(usecase))
2967 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002968 }
2969
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002970 if (!compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS) &&
Guodong Hu267bdf82019-08-12 19:22:32 +08002971 ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002972 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready()))) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002973 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2974 return 0;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302975 }
2976
Aalique Grahame22e49102018-12-18 14:23:57 -08002977 if (out_snd_device != SND_DEVICE_NONE &&
2978 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
2979 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2980 __func__,
2981 use_case_table[uc_id],
2982 adev->last_logged_snd_device[uc_id][0],
2983 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
2984 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
2985 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
2986 -1,
2987 out_snd_device,
2988 platform_get_snd_device_name(out_snd_device),
2989 platform_get_snd_device_acdb_id(out_snd_device));
2990 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
2991 }
2992 if (in_snd_device != SND_DEVICE_NONE &&
2993 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
2994 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2995 __func__,
2996 use_case_table[uc_id],
2997 adev->last_logged_snd_device[uc_id][1],
2998 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
2999 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
3000 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
3001 -1,
3002 in_snd_device,
3003 platform_get_snd_device_name(in_snd_device),
3004 platform_get_snd_device_acdb_id(in_snd_device));
3005 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
3006 }
3007
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003008
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003009 /*
3010 * Limitation: While in call, to do a device switch we need to disable
3011 * and enable both RX and TX devices though one of them is same as current
3012 * device.
3013 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07003014 if ((usecase->type == VOICE_CALL) &&
3015 (usecase->in_snd_device != SND_DEVICE_NONE) &&
3016 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07003017 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07003018 }
3019
3020 if (((usecase->type == VOICE_CALL) ||
3021 (usecase->type == VOIP_CALL)) &&
3022 (usecase->out_snd_device != SND_DEVICE_NONE)) {
3023 /* Disable sidetone only if voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303024 if (voice_is_call_state_active_in_call(adev) ||
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07003025 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07003026 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003027
3028 /* Disable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303029 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003030 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08003031 }
3032
Aalique Grahame22e49102018-12-18 14:23:57 -08003033 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
3034 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003035 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303036 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08003037 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
3038 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
3039 else
3040 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303041 }
3042
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003043 /* Disable current sound devices */
3044 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003045 disable_audio_route(adev, usecase);
3046 disable_snd_device(adev, usecase->out_snd_device);
Gautam Manam274f4752021-09-24 10:58:49 +05303047 if (usecase->id == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
3048 disable_snd_device(adev, SND_DEVICE_OUT_HAPTICS);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003049 }
3050
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003051 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003052 disable_audio_route(adev, usecase);
3053 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003054 }
3055
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08003056 /* Applicable only on the targets that has external modem.
3057 * New device information should be sent to modem before enabling
3058 * the devices to reduce in-call device switch time.
3059 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07003060 if ((usecase->type == VOICE_CALL) &&
3061 (usecase->in_snd_device != SND_DEVICE_NONE) &&
3062 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08003063 status = platform_switch_voice_call_enable_device_config(adev->platform,
3064 out_snd_device,
3065 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07003066 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08003067
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003068 /* Enable new sound devices */
3069 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08003070 check_usecases_codec_backend(adev, usecase, out_snd_device);
Saurav Kumarc1411662020-10-14 10:50:45 +05303071 check_and_configure_headphone(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05303072 if (platform_check_codec_asrc_support(adev->platform))
3073 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003074 enable_snd_device(adev, out_snd_device);
Zhou Songd9bd9302020-08-04 16:34:45 +08003075 /* Enable haptics device for haptic usecase */
3076 if (usecase->id == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
3077 enable_snd_device(adev, SND_DEVICE_OUT_HAPTICS);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003078 }
3079
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07003080 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303081 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003082 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07003083 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003084
Lakshman Chaluvarajuab7e5572020-10-28 19:29:23 +05303085 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL)
Eric Laurentb23d5282013-05-14 15:27:20 -07003086 status = platform_switch_voice_call_device_post(adev->platform,
3087 out_snd_device,
3088 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08003089
sangwoo170731f2013-06-08 15:36:36 +09003090 usecase->in_snd_device = in_snd_device;
3091 usecase->out_snd_device = out_snd_device;
3092
Dhananjay Kumard6d32152016-10-13 16:11:03 +05303093 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
3094 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05303095 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003096 if ((24 == usecase->stream.out->bit_width) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003097 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_SPEAKER)) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003098 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3099 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
3100 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
3101 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
3102 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
3103 /*
3104 * To best utlize DSP, check if the stream sample rate is supported/multiple of
3105 * configured device sample rate, if not update the COPP rate to be equal to the
3106 * device sample rate, else open COPP at stream sample rate
3107 */
3108 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
3109 usecase->stream.out->sample_rate,
3110 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05303111 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
Preetam Singh Ranawat590d0432019-09-30 14:39:47 +05303112 out_snd_device != SND_DEVICE_OUT_HEADPHONES &&
3113 out_snd_device != SND_DEVICE_OUT_HEADPHONES_HIFI_FILTER &&
Ashish Jain4826f6c2017-02-06 13:33:20 +05303114 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003115 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
3116 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
3117 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3118 }
Weiyin Jiangcdece202019-07-08 16:13:16 +08003119 }
3120 enable_audio_route(adev, usecase);
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003121
Shalini Manjunatha5e610912020-12-29 13:02:25 +05303122 if (uc_id == USECASE_AUDIO_PLAYBACK_VOIP) {
3123 struct stream_in *voip_in = get_voice_communication_input(adev);
3124 struct audio_usecase *voip_in_usecase = NULL;
3125 voip_in_usecase = get_usecase_from_list(adev, USECASE_AUDIO_RECORD_VOIP);
3126 if (voip_in != NULL &&
3127 voip_in_usecase != NULL &&
3128 !(out_snd_device == AUDIO_DEVICE_OUT_SPEAKER ||
3129 out_snd_device == AUDIO_DEVICE_OUT_SPEAKER_SAFE) &&
3130 (voip_in_usecase->in_snd_device ==
3131 platform_get_input_snd_device(adev->platform, voip_in,
3132 &usecase->stream.out->device_list,usecase->type))) {
3133 /*
3134 * if VOIP TX is enabled before VOIP RX, needs to re-route the TX path
3135 * for enabling echo-reference-voip with correct port
3136 */
3137 ALOGD("%s: VOIP TX is enabled before VOIP RX,needs to re-route the TX path",__func__);
3138 disable_audio_route(adev, voip_in_usecase);
3139 disable_snd_device(adev, voip_in_usecase->in_snd_device);
3140 enable_snd_device(adev, voip_in_usecase->in_snd_device);
3141 enable_audio_route(adev, voip_in_usecase);
3142 }
3143 }
Ramjee Singhcdf67af2021-09-29 14:20:27 +05303144 if (voice_extn_compress_voip_is_active(adev)) {
3145 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
3146 USECASE_COMPRESS_VOIP_CALL);
3147 /*
3148 * If only compress voip input is opened voip out will be primary out.
3149 * Need to consider re-routing to select correct i/p pair
3150 */
3151 if ((voip_usecase != NULL) &&
3152 (usecase->type == PCM_PLAYBACK) &&
3153 (usecase->stream.out == voip_usecase->stream.out)) {
3154 in_snd_device = platform_get_input_snd_device(adev->platform,
3155 NULL,
3156 &usecase->stream.out->device_list,
3157 usecase->type);
3158 if (voip_usecase->in_snd_device != in_snd_device ) {
3159 ALOGD("%s:Re routing compress voip tx snd device matching voip rx pair",
3160 __func__);
3161 disable_audio_route(adev, voip_usecase);
3162 disable_snd_device(adev, voip_usecase->in_snd_device);
3163 voip_usecase->in_snd_device = in_snd_device;
3164 voip_usecase->out_snd_device = usecase->out_snd_device;
3165 /* Route all TX usecase to Compress voip BE */
3166 check_usecases_capture_codec_backend(adev, voip_usecase, in_snd_device);
3167 enable_snd_device(adev, in_snd_device);
3168 /* Send Voice related calibration for RX /TX pair */
3169 status = platform_switch_voice_call_device_post(adev->platform,
3170 out_snd_device,
3171 in_snd_device);
3172 enable_audio_route(adev, voip_usecase);
3173 }
3174 }
3175 }
Shalini Manjunatha5e610912020-12-29 13:02:25 +05303176
3177
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08003178 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08003179
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003180 /* If input stream is already running then effect needs to be
3181 applied on the new input device that's being enabled here. */
Eric Laurent637e2d42018-11-15 12:24:31 -08003182 if (in_snd_device != SND_DEVICE_NONE)
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003183 check_and_enable_effect(adev);
3184
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003185 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003186 /* Enable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303187 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003188 voice_check_and_update_aanc_path(adev, out_snd_device, true);
3189
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003190 /* Enable sidetone only if other voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303191 if (voice_is_call_state_active_in_call(adev) ||
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003192 voice_extn_compress_voip_is_started(adev))
3193 voice_set_sidetone(adev, out_snd_device, true);
3194 }
3195
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003196 /* Applicable only on the targets that has external modem.
3197 * Enable device command should be sent to modem only after
3198 * enabling voice call mixer controls
3199 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07003200 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003201 status = platform_switch_voice_call_usecase_route_post(adev->platform,
3202 out_snd_device,
3203 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303204
3205 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003206 struct stream_in *in = adev_get_active_input(adev);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303207 if (usecase->type == VOIP_CALL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003208 if (in != NULL && !in->standby) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303209 if (is_bt_soc_on(adev) == false){
3210 ALOGD("BT SCO MIC disconnected while in connection");
Eric Laurent637e2d42018-11-15 12:24:31 -08003211 if (in->pcm != NULL)
3212 pcm_stop(in->pcm);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303213 }
3214 }
3215 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
3216 && usecase->stream.out->started) {
3217 if (is_bt_soc_on(adev) == false) {
3218 ALOGD("BT SCO/A2DP disconnected while in connection");
3219 out_standby_l(&usecase->stream.out->stream.common);
3220 }
3221 }
3222 } else if ((usecase->stream.out != NULL) &&
3223 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05303224 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
3225 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Weiyin Jiang0d373242019-07-25 13:18:17 +08003226 (usecase->type != PCM_CAPTURE) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303227 usecase->stream.out->started) {
3228 if (is_bt_soc_on(adev) == false) {
3229 ALOGD("BT SCO/A2dp disconnected while in connection");
3230 out_standby_l(&usecase->stream.out->stream.common);
3231 }
3232 }
3233 }
3234
Yung Ti Su70cb8242018-06-22 17:38:47 +08003235 if (usecase->type != PCM_CAPTURE && usecase == voip_usecase) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003236 struct stream_out *voip_out = voip_usecase->stream.out;
3237 audio_extn_utils_send_app_type_gain(adev,
3238 voip_out->app_type_cfg.app_type,
3239 &voip_out->app_type_cfg.gain[0]);
3240 }
3241
Ajender Reddyb940b832021-07-07 11:51:42 +05303242 ALOGD("%s: done",__func__);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303243
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003244 return status;
3245}
3246
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003247static int stop_input_stream(struct stream_in *in)
3248{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303249 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003250 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05303251
3252 if (in == NULL) {
3253 ALOGE("%s: stream_in ptr is NULL", __func__);
3254 return -EINVAL;
3255 }
3256
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003257 struct audio_device *adev = in->dev;
Carter Hsu2e429db2019-05-14 18:50:52 +08003258 struct stream_in *priority_in = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003259
Eric Laurent994a6932013-07-17 11:51:42 -07003260 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003261 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003262 uc_info = get_usecase_from_list(adev, in->usecase);
3263 if (uc_info == NULL) {
3264 ALOGE("%s: Could not find the usecase (%d) in the list",
3265 __func__, in->usecase);
3266 return -EINVAL;
3267 }
3268
Carter Hsu2e429db2019-05-14 18:50:52 +08003269 priority_in = get_priority_input(adev);
3270
Derek Chenea197282019-01-07 17:35:01 -08003271 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3272 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003273
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003274 /* Close in-call recording streams */
3275 voice_check_and_stop_incall_rec_usecase(adev, in);
3276
Eric Laurent150dbfe2013-02-27 14:31:02 -08003277 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003278 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003279
3280 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003281 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003282
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003283 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303284 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_PRIMARY);
3285
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003286 list_remove(&uc_info->list);
3287 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003288
Carter Hsu2e429db2019-05-14 18:50:52 +08003289 if (priority_in == in) {
3290 priority_in = get_priority_input(adev);
Sujin Panicker110f7942021-08-26 17:01:22 +05303291 if (priority_in) {
3292 if (is_usb_in_device_type(&priority_in->device_list)) {
3293 if (audio_extn_usb_connected(NULL))
3294 select_devices(adev, priority_in->usecase);
3295 } else {
3296 select_devices(adev, priority_in->usecase);
3297 }
3298 }
Carter Hsu2e429db2019-05-14 18:50:52 +08003299 }
3300
Vatsal Buchac09ae062018-11-14 13:25:08 +05303301 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07003302 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003303 return ret;
3304}
3305
3306int start_input_stream(struct stream_in *in)
3307{
3308 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08003309 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003310 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05303311
3312 if (in == NULL) {
3313 ALOGE("%s: stream_in ptr is NULL", __func__);
3314 return -EINVAL;
3315 }
3316
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003317 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07003318 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07003319 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003320
Mingming Yin2664a5b2015-09-03 10:53:11 -07003321 if (get_usecase_from_list(adev, usecase) == NULL)
3322 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303323 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
3324 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003325
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303326 if (CARD_STATUS_OFFLINE == in->card_status||
3327 CARD_STATUS_OFFLINE == adev->card_status) {
3328 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303329 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303330 goto error_config;
3331 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303332
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003333 if (is_sco_in_device_type(&in->device_list)) {
Lakshman Chaluvaraju87f53aa2021-02-02 15:50:11 +05303334 if (!adev->bt_sco_on || audio_extn_a2dp_source_is_ready()) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303335 ALOGE("%s: SCO profile is not ready, return error", __func__);
3336 ret = -EIO;
3337 goto error_config;
3338 }
3339 }
3340
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003341 /* Check if source matches incall recording usecase criteria */
3342 ret = voice_check_and_set_incall_rec_usecase(adev, in);
3343 if (ret)
3344 goto error_config;
3345 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07003346 ALOGV("%s: usecase(%d)", __func__, in->usecase);
3347
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303348 if (audio_extn_cin_attached_usecase(in))
3349 audio_extn_cin_acquire_usecase(in);
3350
Mingming Yin2664a5b2015-09-03 10:53:11 -07003351 if (get_usecase_from_list(adev, in->usecase) != NULL) {
3352 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
3353 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Weiyin Jiang38c0e612020-09-10 16:10:51 +08003354 ret = -EINVAL;
3355 goto error_config;
Mingming Yin2664a5b2015-09-03 10:53:11 -07003356 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003357
Eric Laurentb23d5282013-05-14 15:27:20 -07003358 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003359 if (in->pcm_device_id < 0) {
3360 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
3361 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08003362 ret = -EINVAL;
3363 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003364 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003365
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003366 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003367
3368 if (!uc_info) {
3369 ret = -ENOMEM;
3370 goto error_config;
3371 }
3372
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003373 uc_info->id = in->usecase;
3374 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003375 uc_info->stream.in = in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003376 list_init(&uc_info->device_list);
3377 assign_devices(&uc_info->device_list, &in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003378 uc_info->in_snd_device = SND_DEVICE_NONE;
3379 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003380
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003381 list_add_tail(&adev->usecase_list, &uc_info->list);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003382 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303383 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3384 adev->perf_lock_opts,
3385 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003386 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003387
Derek Chenea197282019-01-07 17:35:01 -08003388 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3389 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003390
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05303391 android_atomic_acquire_cas(true, false, &(in->capture_stopped));
3392
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303393 if (audio_extn_cin_attached_usecase(in)) {
Manish Dewangan46e07982018-12-13 18:18:59 +05303394 ret = audio_extn_cin_open_input_stream(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303395 if (ret)
3396 goto error_open;
3397 else
3398 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003399 }
3400
Haynes Mathew George16081042017-05-31 17:16:49 -07003401 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003402 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003403 ALOGE("%s: pcm stream not ready", __func__);
3404 goto error_open;
3405 }
3406 ret = pcm_start(in->pcm);
3407 if (ret < 0) {
3408 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3409 goto error_open;
3410 }
3411 } else {
3412 unsigned int flags = PCM_IN | PCM_MONOTONIC;
3413 unsigned int pcm_open_retry_count = 0;
3414
Zhou Song62ea0282020-03-22 19:53:01 +08003415 if ((in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) ||
3416 (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003417 flags |= PCM_MMAP | PCM_NOIRQ;
3418 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
3419 } else if (in->realtime) {
3420 flags |= PCM_MMAP | PCM_NOIRQ;
3421 }
3422
Garmond Leunge2433c32017-09-28 21:51:22 -07003423 if (audio_extn_ffv_get_stream() == in) {
3424 ALOGD("%s: ffv stream, update pcm config", __func__);
3425 audio_extn_ffv_update_pcm_config(&config);
3426 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003427 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3428 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3429
3430 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003431 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07003432 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07003433 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003434 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303435 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303436 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3437 adev->card_status = CARD_STATUS_OFFLINE;
3438 in->card_status = CARD_STATUS_OFFLINE;
3439 ret = -EIO;
3440 goto error_open;
3441 }
3442
Haynes Mathew George16081042017-05-31 17:16:49 -07003443 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3444 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3445 if (in->pcm != NULL) {
3446 pcm_close(in->pcm);
3447 in->pcm = NULL;
3448 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003449 if (pcm_open_retry_count == 0) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003450 ret = -EIO;
3451 goto error_open;
3452 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003453 pcm_open_retry_count--;
Haynes Mathew George16081042017-05-31 17:16:49 -07003454 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3455 continue;
3456 }
3457 break;
3458 }
3459
3460 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003461 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07003462 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003463 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003464 if (ret < 0) {
3465 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3466 pcm_close(in->pcm);
3467 in->pcm = NULL;
3468 goto error_open;
3469 }
3470 register_in_stream(in);
3471 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003472 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07003473 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003474 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003475 if (ret < 0) {
3476 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003477 pcm_close(in->pcm);
3478 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003479 goto error_open;
3480 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003481 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003482 }
3483
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003484 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07003485 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
3486 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003487
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003488 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303489 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
3490
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303491done_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003492 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303493 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Manisha Agarwal4c2402e2020-10-21 12:02:57 +05303494 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303495 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003496 return ret;
3497
3498error_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003499 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303500 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003501 stop_input_stream(in);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003502
Eric Laurentc8400632013-02-14 19:04:54 -08003503error_config:
Weiyin Jiang38c0e612020-09-10 16:10:51 +08003504 if (audio_extn_cin_attached_usecase(in))
3505 audio_extn_cin_close_input_stream(in);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303506 /*
3507 * sleep 50ms to allow sufficient time for kernel
3508 * drivers to recover incases like SSR.
3509 */
3510 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003511 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303512 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003513 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003514}
3515
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003516void lock_input_stream(struct stream_in *in)
3517{
3518 pthread_mutex_lock(&in->pre_lock);
3519 pthread_mutex_lock(&in->lock);
3520 pthread_mutex_unlock(&in->pre_lock);
3521}
3522
3523void lock_output_stream(struct stream_out *out)
3524{
3525 pthread_mutex_lock(&out->pre_lock);
3526 pthread_mutex_lock(&out->lock);
3527 pthread_mutex_unlock(&out->pre_lock);
3528}
3529
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003530/* must be called with out->lock locked */
3531static int send_offload_cmd_l(struct stream_out* out, int command)
3532{
3533 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
3534
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003535 if (!cmd) {
3536 ALOGE("failed to allocate mem for command 0x%x", command);
3537 return -ENOMEM;
3538 }
3539
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003540 ALOGVV("%s %d", __func__, command);
3541
3542 cmd->cmd = command;
3543 list_add_tail(&out->offload_cmd_list, &cmd->node);
3544 pthread_cond_signal(&out->offload_cond);
3545 return 0;
3546}
3547
Gautam Manam14c198b2020-12-24 14:08:04 +05303548/* must be called with out->lock */
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003549static void stop_compressed_output_l(struct stream_out *out)
3550{
Gautam Manam14c198b2020-12-24 14:08:04 +05303551 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003552 out->offload_state = OFFLOAD_STATE_IDLE;
Gautam Manam14c198b2020-12-24 14:08:04 +05303553 pthread_mutex_unlock(&out->latch_lock);
Weiyin Jiang906db3c2021-03-02 13:17:04 +08003554
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003555 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003556 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003557 if (out->compr != NULL) {
3558 compress_stop(out->compr);
3559 while (out->offload_thread_blocked) {
3560 pthread_cond_wait(&out->cond, &out->lock);
3561 }
3562 }
3563}
3564
Varun Balaraje49253e2017-07-06 19:48:56 +05303565bool is_interactive_usecase(audio_usecase_t uc_id)
3566{
3567 unsigned int i;
3568 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
3569 if (uc_id == interactive_usecases[i])
3570 return true;
3571 }
3572 return false;
3573}
3574
3575static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
3576{
3577 audio_usecase_t ret_uc = USECASE_INVALID;
3578 unsigned int intract_uc_index;
3579 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3580
3581 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
3582 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
3583 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
3584 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
3585 ret_uc = interactive_usecases[intract_uc_index];
3586 break;
3587 }
3588 }
3589
3590 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
3591 return ret_uc;
3592}
3593
3594static void free_interactive_usecase(struct audio_device *adev,
3595 audio_usecase_t uc_id)
3596{
3597 unsigned int interact_uc_index;
3598 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3599
3600 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
3601 if (interactive_usecases[interact_uc_index] == uc_id) {
3602 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
3603 break;
3604 }
3605 }
3606 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
3607}
3608
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003609bool is_offload_usecase(audio_usecase_t uc_id)
3610{
3611 unsigned int i;
3612 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
3613 if (uc_id == offload_usecases[i])
3614 return true;
3615 }
3616 return false;
3617}
3618
Dhananjay Kumarac341582017-02-23 23:42:25 +05303619static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003620{
vivek mehta446c3962015-09-14 10:57:35 -07003621 audio_usecase_t ret_uc = USECASE_INVALID;
3622 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003623 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003624 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05303625 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07003626 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
3627 else
3628 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003629
vivek mehta446c3962015-09-14 10:57:35 -07003630 pthread_mutex_lock(&adev->lock);
3631 if (get_usecase_from_list(adev, ret_uc) != NULL)
3632 ret_uc = USECASE_INVALID;
3633 pthread_mutex_unlock(&adev->lock);
3634
3635 return ret_uc;
3636 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003637
3638 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003639 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3640 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3641 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3642 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003643 break;
3644 }
3645 }
vivek mehta446c3962015-09-14 10:57:35 -07003646
3647 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3648 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003649}
3650
3651static void free_offload_usecase(struct audio_device *adev,
3652 audio_usecase_t uc_id)
3653{
vivek mehta446c3962015-09-14 10:57:35 -07003654 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003655 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003656
3657 if (!adev->multi_offload_enable)
3658 return;
3659
3660 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3661 if (offload_usecases[offload_uc_index] == uc_id) {
3662 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003663 break;
3664 }
3665 }
3666 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3667}
3668
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003669static void *offload_thread_loop(void *context)
3670{
3671 struct stream_out *out = (struct stream_out *) context;
3672 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003673 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003674
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003675 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08003676 set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003677 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3678
3679 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003680 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003681 out->offload_state = OFFLOAD_STATE_IDLE;
3682 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003683 for (;;) {
3684 struct offload_cmd *cmd = NULL;
3685 stream_callback_event_t event;
3686 bool send_callback = false;
3687
3688 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3689 __func__, list_empty(&out->offload_cmd_list),
3690 out->offload_state);
3691 if (list_empty(&out->offload_cmd_list)) {
3692 ALOGV("%s SLEEPING", __func__);
3693 pthread_cond_wait(&out->offload_cond, &out->lock);
3694 ALOGV("%s RUNNING", __func__);
3695 continue;
3696 }
3697
3698 item = list_head(&out->offload_cmd_list);
3699 cmd = node_to_item(item, struct offload_cmd, node);
3700 list_remove(item);
3701
3702 ALOGVV("%s STATE %d CMD %d out->compr %p",
3703 __func__, out->offload_state, cmd->cmd, out->compr);
3704
3705 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3706 free(cmd);
3707 break;
3708 }
3709
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003710 // allow OFFLOAD_CMD_ERROR reporting during standby
3711 // this is needed to handle failures during compress_open
3712 // Note however that on a pause timeout, the stream is closed
3713 // and no offload usecase will be active. Therefore this
3714 // special case is needed for compress_open failures alone
3715 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3716 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003717 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003718 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003719 pthread_cond_signal(&out->cond);
3720 continue;
3721 }
3722 out->offload_thread_blocked = true;
3723 pthread_mutex_unlock(&out->lock);
3724 send_callback = false;
3725 switch(cmd->cmd) {
3726 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003727 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003728 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003729 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003730 send_callback = true;
3731 event = STREAM_CBK_EVENT_WRITE_READY;
3732 break;
3733 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003734 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303735 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003736 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303737 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003738 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303739 if (ret < 0)
3740 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303741 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303742 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003743 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003744 else
3745 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003746 if (-ENETRESET != ret && !(-EINTR == ret &&
3747 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303748 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303749 pthread_mutex_lock(&out->lock);
3750 out->send_new_metadata = 1;
3751 out->send_next_track_params = true;
3752 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303753 event = STREAM_CBK_EVENT_DRAIN_READY;
3754 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3755 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303756 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003757 break;
3758 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003759 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003760 ret = compress_drain(out->compr);
3761 ALOGD("copl(%p):out of compress_drain", out);
3762 // EINTR check avoids drain interruption due to SSR
3763 if (-ENETRESET != ret && !(-EINTR == ret &&
3764 CARD_STATUS_OFFLINE == out->card_status)) {
3765 send_callback = true;
3766 event = STREAM_CBK_EVENT_DRAIN_READY;
3767 } else
3768 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003769 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303770 case OFFLOAD_CMD_ERROR:
3771 ALOGD("copl(%p): sending error callback to AF", out);
3772 send_callback = true;
3773 event = STREAM_CBK_EVENT_ERROR;
3774 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003775 default:
3776 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3777 break;
3778 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003779 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003780 out->offload_thread_blocked = false;
3781 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003782 if (send_callback && out->client_callback) {
3783 ALOGVV("%s: sending client_callback event %d", __func__, event);
3784 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003785 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003786 free(cmd);
3787 }
3788
3789 pthread_cond_signal(&out->cond);
3790 while (!list_empty(&out->offload_cmd_list)) {
3791 item = list_head(&out->offload_cmd_list);
3792 list_remove(item);
3793 free(node_to_item(item, struct offload_cmd, node));
3794 }
3795 pthread_mutex_unlock(&out->lock);
3796
3797 return NULL;
3798}
3799
3800static int create_offload_callback_thread(struct stream_out *out)
3801{
3802 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3803 list_init(&out->offload_cmd_list);
3804 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3805 offload_thread_loop, out);
3806 return 0;
3807}
3808
3809static int destroy_offload_callback_thread(struct stream_out *out)
3810{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003811 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003812 stop_compressed_output_l(out);
3813 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3814
3815 pthread_mutex_unlock(&out->lock);
3816 pthread_join(out->offload_thread, (void **) NULL);
3817 pthread_cond_destroy(&out->offload_cond);
3818
3819 return 0;
3820}
3821
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003822static int stop_output_stream(struct stream_out *out)
3823{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303824 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003825 struct audio_usecase *uc_info;
3826 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003827 bool has_voip_usecase =
3828 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003829
Eric Laurent994a6932013-07-17 11:51:42 -07003830 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003831 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003832 uc_info = get_usecase_from_list(adev, out->usecase);
3833 if (uc_info == NULL) {
3834 ALOGE("%s: Could not find the usecase (%d) in the list",
3835 __func__, out->usecase);
3836 return -EINVAL;
3837 }
3838
Zhou Songbaddf9f2020-11-20 13:57:39 +08003839 out->a2dp_muted = false;
3840
Derek Chenea197282019-01-07 17:35:01 -08003841 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3842 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003843
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003844 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303845 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003846 if (adev->visualizer_stop_output != NULL)
3847 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003848
3849 audio_extn_dts_remove_state_notifier_node(out->usecase);
3850
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003851 if (adev->offload_effects_stop_output != NULL)
3852 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07003853 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3854 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3855 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003856 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003857
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003858 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3859 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003860 voice_set_device_mute_flag(adev, false);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003861 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003862
Eric Laurent150dbfe2013-02-27 14:31:02 -08003863 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003864 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003865
3866 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003867 disable_snd_device(adev, uc_info->out_snd_device);
Zhou Songd9bd9302020-08-04 16:34:45 +08003868 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
3869 disable_snd_device(adev, SND_DEVICE_OUT_HAPTICS);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003870
Aalique Grahame22e49102018-12-18 14:23:57 -08003871 audio_extn_extspk_update(adev->extspk);
3872
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003873 if (is_offload_usecase(out->usecase)) {
3874 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3875 adev->dsp_bit_width_enforce_mode,
3876 false);
3877 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003878 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003879 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3880 false);
3881
3882 if (ret != 0)
3883 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3884 /* default service interval was successfully updated,
3885 reopen USB backend with new service interval */
3886 ret = 0;
3887 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003888
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003889 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303890 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003891 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303892 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003893 ALOGV("Disable passthrough , reset mixer to pcm");
3894 /* NO_PASSTHROUGH */
Meng Wang4c32fb42020-01-16 17:57:11 +08003895#ifdef AUDIO_GKI_ENABLED
3896 /* out->compr_config.codec->reserved[0] is for compr_passthr */
3897 out->compr_config.codec->reserved[0] = 0;
3898#else
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003899 out->compr_config.codec->compr_passthr = 0;
Meng Wang4c32fb42020-01-16 17:57:11 +08003900#endif
Mingming Yin21854652016-04-13 11:54:02 -07003901 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003902 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3903 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003904
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303905 /* Must be called after removing the usecase from list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003906 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL))
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303907 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303908
Manish Dewangan21a850a2017-08-14 12:03:55 +05303909 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003910 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3911 if (ret < 0)
3912 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3913 }
3914
Zhou Song642ec432020-12-23 16:11:10 +08003915 /* trigger voip input to reroute when voip output changes to hearing aid */
Aalique Grahame22e49102018-12-18 14:23:57 -08003916 if (has_voip_usecase ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003917 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003918 struct listnode *node;
3919 struct audio_usecase *usecase;
3920 list_for_each(node, &adev->usecase_list) {
3921 usecase = node_to_item(node, struct audio_usecase, list);
Zhou Song642ec432020-12-23 16:11:10 +08003922 if (usecase->type == PCM_PLAYBACK || usecase == uc_info ||
3923 (usecase->type == PCM_CAPTURE &&
Revathi Uddarajud9f23d92020-07-27 10:55:06 +05303924 usecase->id != USECASE_AUDIO_RECORD_VOIP &&
Zhou Song642ec432020-12-23 16:11:10 +08003925 usecase->id != USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY))
Aalique Grahame22e49102018-12-18 14:23:57 -08003926 continue;
3927
3928 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
3929 __func__, usecase->id, use_case_table[usecase->id],
3930 out->usecase, use_case_table[out->usecase]);
3931 select_devices(adev, usecase->id);
3932 }
3933 }
3934
Garmond Leung5fd0b552018-04-17 11:56:12 -07003935 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003936 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003937 return ret;
3938}
3939
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003940struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
3941 unsigned int flags, unsigned int pcm_open_retry_count,
3942 struct pcm_config *config)
3943{
3944 struct pcm* pcm = NULL;
3945
3946 while (1) {
3947 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
3948 if (pcm == NULL || !pcm_is_ready(pcm)) {
3949 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
3950 if (pcm != NULL) {
3951 pcm_close(pcm);
3952 pcm = NULL;
3953 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003954 if (pcm_open_retry_count == 0)
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003955 return NULL;
3956
Weiyin Jiang72197252019-10-09 11:49:32 +08003957 pcm_open_retry_count--;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003958 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3959 continue;
3960 }
3961 break;
3962 }
3963
3964 if (pcm_is_ready(pcm)) {
3965 int ret = pcm_prepare(pcm);
3966 if (ret < 0) {
3967 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3968 pcm_close(pcm);
3969 pcm = NULL;
3970 }
3971 }
3972
3973 return pcm;
3974}
3975
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003976int start_output_stream(struct stream_out *out)
3977{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003978 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003979 struct audio_usecase *uc_info;
3980 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003981 char mixer_ctl_name[128];
3982 struct mixer_ctl *ctl = NULL;
3983 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303984 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003985 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003986
Haynes Mathew George380745d2017-10-04 15:27:45 -07003987 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003988 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3989 ret = -EINVAL;
3990 goto error_config;
3991 }
3992
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003993 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303994 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003995 get_device_types(&out->device_list), is_haptic_usecase);
3996
3997 bool is_speaker_active = compare_device_type(&out->device_list,
3998 AUDIO_DEVICE_OUT_SPEAKER);
3999 bool is_speaker_safe_active = compare_device_type(&out->device_list,
4000 AUDIO_DEVICE_OUT_SPEAKER_SAFE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304001
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304002 if (CARD_STATUS_OFFLINE == out->card_status ||
4003 CARD_STATUS_OFFLINE == adev->card_status) {
4004 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05304005 ret = -EIO;
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004006 goto error_fatal;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304007 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05304008
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004009 //Update incall music usecase to reflect correct voice session
4010 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
4011 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
4012 if (ret != 0) {
4013 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
4014 __func__, ret);
4015 goto error_config;
4016 }
4017 }
4018
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004019 if (is_a2dp_out_device_type(&out->device_list)) {
Florian Pfister1a84f312018-07-19 14:38:18 +02004020 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004021 if (is_speaker_active || is_speaker_safe_active) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304022 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304023 } else {
Zhou Songd01e7a22020-09-23 22:49:01 +08004024 if (!is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304025 ALOGE("%s: A2DP profile is not ready, return error", __func__);
4026 ret = -EAGAIN;
4027 goto error_config;
4028 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304029 }
4030 }
4031 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004032 if (is_sco_out_device_type(&out->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304033 if (!adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004034 if (is_speaker_active) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304035 //combo usecase just by pass a2dp
4036 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004037 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304038 } else {
4039 ALOGE("%s: SCO profile is not ready, return error", __func__);
4040 ret = -EAGAIN;
4041 goto error_config;
4042 }
4043 }
4044 }
4045
Eric Laurentb23d5282013-05-14 15:27:20 -07004046 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004047 if (out->pcm_device_id < 0) {
4048 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
4049 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004050 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004051 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004052 }
4053
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004054 if (is_haptic_usecase) {
Meng Wang51d8c2a2020-04-27 15:23:21 +08004055 adev->haptic_pcm_device_id = platform_get_pcm_device_id(
4056 USECASE_AUDIO_PLAYBACK_HAPTICS, PCM_PLAYBACK);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004057 if (adev->haptic_pcm_device_id < 0) {
4058 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
4059 __func__, adev->haptic_pcm_device_id, out->usecase);
4060 ret = -EINVAL;
4061 goto error_config;
4062 }
4063 }
4064
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004065 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004066
4067 if (!uc_info) {
4068 ret = -ENOMEM;
4069 goto error_config;
4070 }
4071
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004072 uc_info->id = out->usecase;
4073 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004074 uc_info->stream.out = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004075 list_init(&uc_info->device_list);
4076 assign_devices(&uc_info->device_list, &out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004077 uc_info->in_snd_device = SND_DEVICE_NONE;
4078 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07004079
4080 /* This must be called before adding this usecase to the list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004081 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07004082 audio_extn_usb_check_and_set_svc_int(uc_info, true);
4083 /* USB backend is not reopened immediately.
4084 This is eventually done as part of select_devices */
4085 }
4086
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004087 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004088
Wei Wangf7ca6c92017-11-21 14:51:20 -08004089 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304090 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4091 adev->perf_lock_opts,
4092 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304093
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004094 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05304095 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304096 if (audio_extn_passthru_is_enabled() &&
4097 audio_extn_passthru_is_passthrough_stream(out)) {
4098 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304099 }
4100 }
4101
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004102 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02004103 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304104 if (!a2dp_combo) {
4105 check_a2dp_restore_l(adev, out, false);
4106 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004107 struct listnode dev;
4108 list_init(&dev);
4109 assign_devices(&dev, &out->device_list);
4110 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4111 reassign_device_list(&out->device_list,
4112 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aalique Grahame22e49102018-12-18 14:23:57 -08004113 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004114 reassign_device_list(&out->device_list,
4115 AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304116 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004117 assign_devices(&out->device_list, &dev);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304118 }
4119 } else {
Revathi Uddarajub26e3932020-06-10 14:51:02 +05304120 select_devices(adev, out->usecase);
4121 if (is_a2dp_out_device_type(&out->device_list) &&
4122 !adev->a2dp_started) {
4123 if (is_speaker_active || is_speaker_safe_active) {
4124 struct listnode dev;
4125 list_init(&dev);
4126 assign_devices(&dev, &out->device_list);
4127 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4128 reassign_device_list(&out->device_list,
4129 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
4130 else
4131 reassign_device_list(&out->device_list,
4132 AUDIO_DEVICE_OUT_SPEAKER, "");
4133 select_devices(adev, out->usecase);
4134 assign_devices(&out->device_list, &dev);
4135 } else {
4136 ret = -EINVAL;
4137 goto error_open;
4138 }
4139 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304140 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004141
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004142 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
4143 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07004144 voice_set_device_mute_flag(adev, true);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004145 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07004146
Derek Chenea197282019-01-07 17:35:01 -08004147 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
4148 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08004149
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004150 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
4151 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07004152
4153 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07004154 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07004155 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4156 ALOGE("%s: pcm stream not ready", __func__);
4157 goto error_open;
4158 }
4159 ret = pcm_start(out->pcm);
4160 if (ret < 0) {
4161 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
4162 goto error_open;
4163 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07004164 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07004165 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004166 unsigned int flags = PCM_OUT;
4167 unsigned int pcm_open_retry_count = 0;
4168 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
4169 flags |= PCM_MMAP | PCM_NOIRQ;
4170 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004171 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08004172 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004173 } else
4174 flags |= PCM_MONOTONIC;
4175
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004176 if ((adev->vr_audio_mode_enabled) &&
4177 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
4178 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4179 "PCM_Dev %d Topology", out->pcm_device_id);
4180 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4181 if (!ctl) {
4182 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
4183 __func__, mixer_ctl_name);
4184 } else {
4185 //if success use ULLPP
4186 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
4187 __func__, mixer_ctl_name, out->pcm_device_id);
4188 //There is a still a possibility that some sessions
4189 // that request for FAST|RAW when 3D audio is active
4190 //can go through ULLPP. Ideally we expects apps to
4191 //listen to audio focus and stop concurrent playback
4192 //Also, we will look for mode flag (voice_in_communication)
4193 //before enabling the realtime flag.
4194 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
4195 }
4196 }
4197
Vatsal Bucha3f39f222021-06-29 16:16:55 +05304198 platform_set_stream_channel_map(adev->platform, out->channel_mask,
4199 out->pcm_device_id, -1, &out->channel_map_param.channel_map[0]);
Surendar Karka91fa3682018-07-02 18:12:12 +05304200
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004201 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
4202 flags, pcm_open_retry_count,
4203 &(out->config));
4204 if (out->pcm == NULL) {
4205 ret = -EIO;
4206 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004207 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004208
4209 if (is_haptic_usecase) {
4210 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
4211 adev->haptic_pcm_device_id,
4212 flags, pcm_open_retry_count,
4213 &(adev->haptics_config));
4214 // failure to open haptics pcm shouldnt stop audio,
4215 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07004216
4217 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
4218 ALOGD("%s: enable haptic audio synchronization", __func__);
4219 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
4220 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004221 }
4222
Zhou Song2b8f28f2017-09-11 10:51:38 +08004223 // apply volume for voip playback after path is set up
4224 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
4225 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05304226 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
4227 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304228 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
4229 out->apply_volume = false;
Derek Chenf13dd492018-11-13 14:53:51 -08004230 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
4231 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304232 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004233 } else {
Zhou Song79929fe2020-01-20 17:57:43 +08004234 /*
4235 * set custom channel map if:
4236 * 1. neither mono nor stereo clips i.e. channels > 2 OR
4237 * 2. custom channel map has been set by client
4238 * else default channel map of FC/FR/FL can always be set to DSP
4239 */
4240 if (popcount(out->channel_mask) > 2 || out->channel_map_param.channel_map[0])
4241 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Weiyin Jiang810a80d2021-01-18 16:04:31 +08004242 out->pcm_device_id, -1, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08004243 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
4244 adev->dsp_bit_width_enforce_mode,
4245 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004246 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07004247 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004248 out->compr = compress_open(adev->snd_card,
4249 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004250 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004251 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05304252 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05304253 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
4254 adev->card_status = CARD_STATUS_OFFLINE;
4255 out->card_status = CARD_STATUS_OFFLINE;
4256 ret = -EIO;
4257 goto error_open;
4258 }
4259
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004260 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004261 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004262 compress_close(out->compr);
4263 out->compr = NULL;
4264 ret = -EIO;
4265 goto error_open;
4266 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304267 /* compress_open sends params of the track, so reset the flag here */
4268 out->is_compr_metadata_avail = false;
4269
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004270 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004271 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07004272
Fred Oh3f43e742015-03-04 18:42:34 -08004273 /* Since small bufs uses blocking writes, a write will be blocked
4274 for the default max poll time (20s) in the event of an SSR.
4275 Reduce the poll time to observe and deal with SSR faster.
4276 */
Ashish Jain5106d362016-05-11 19:23:33 +05304277 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08004278 compress_set_max_poll_wait(out->compr, 1000);
4279 }
4280
Manish Dewangan69426c82017-01-30 17:35:36 +05304281 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05304282 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05304283
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004284 audio_extn_dts_create_state_notifier_node(out->usecase);
4285 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4286 popcount(out->channel_mask),
4287 out->playback_started);
4288
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004289#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304290 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004291 audio_extn_dolby_send_ddp_endp_params(adev);
4292#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05304293 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
4294 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004295 if (adev->visualizer_start_output != NULL)
4296 adev->visualizer_start_output(out->handle, out->pcm_device_id);
4297 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05304298 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004299 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004300 }
Derek Chenf13dd492018-11-13 14:53:51 -08004301
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004302 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf13dd492018-11-13 14:53:51 -08004303 /* Update cached volume from media to offload/direct stream */
4304 struct listnode *node = NULL;
4305 list_for_each(node, &adev->active_outputs_list) {
4306 streams_output_ctxt_t *out_ctxt = node_to_item(node,
4307 streams_output_ctxt_t,
4308 list);
4309 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
4310 out->volume_l = out_ctxt->output->volume_l;
4311 out->volume_r = out_ctxt->output->volume_r;
4312 }
4313 }
4314 out_set_compr_volume(&out->stream,
4315 out->volume_l, out->volume_r);
4316 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004317 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004318
4319 if (ret == 0) {
4320 register_out_stream(out);
4321 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07004322 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4323 ALOGE("%s: pcm stream not ready", __func__);
4324 goto error_open;
4325 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004326 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004327 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004328 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004329 if (ret < 0)
4330 goto error_open;
4331 }
4332 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004333 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304334 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Jaideep Sharma0fa53812020-09-17 09:00:11 +05304335 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004336
vivek mehtad15d2bf2019-05-17 13:35:10 -07004337 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
4338 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4339 audio_low_latency_hint_start();
4340 }
4341
Manish Dewangan21a850a2017-08-14 12:03:55 +05304342 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07004343 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07004344 if (ret < 0)
4345 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
4346 }
4347
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004348 // consider a scenario where on pause lower layers are tear down.
4349 // so on resume, swap mixer control need to be sent only when
4350 // backend is active, hence rather than sending from enable device
4351 // sending it from start of streamtream
4352
4353 platform_set_swap_channels(adev, true);
4354
Haynes Mathew George380745d2017-10-04 15:27:45 -07004355 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304356 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004357 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004358error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004359 if (adev->haptic_pcm) {
4360 pcm_close(adev->haptic_pcm);
4361 adev->haptic_pcm = NULL;
4362 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004363 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304364 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004365 stop_output_stream(out);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004366error_fatal:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05304367 /*
4368 * sleep 50ms to allow sufficient time for kernel
4369 * drivers to recover incases like SSR.
4370 */
4371 usleep(50000);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004372error_config:
Haynes Mathew George380745d2017-10-04 15:27:45 -07004373 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304374 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004375 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004376}
4377
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004378static int check_input_parameters(uint32_t sample_rate,
4379 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08004380 int channel_count,
4381 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004382{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004383 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004384
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304385 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
4386 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
4387 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07004388 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02004389 !audio_extn_compr_cap_format_supported(format) &&
4390 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004391 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004392
Aalique Grahame22e49102018-12-18 14:23:57 -08004393 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
4394 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
4395 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
4396 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
4397 return -EINVAL;
4398 }
4399
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004400 switch (channel_count) {
4401 case 1:
4402 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304403 case 3:
4404 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004405 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07004406 case 8:
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05304407 case 10:
4408 case 12:
4409 case 14:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004410 break;
4411 default:
4412 ret = -EINVAL;
4413 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004414
4415 switch (sample_rate) {
4416 case 8000:
4417 case 11025:
4418 case 12000:
4419 case 16000:
4420 case 22050:
4421 case 24000:
4422 case 32000:
4423 case 44100:
4424 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004425 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304426 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004427 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304428 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004429 break;
4430 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004431 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004432 }
4433
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004434 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004435}
4436
Naresh Tanniru04f71882018-06-26 17:46:22 +05304437
4438/** Add a value in a list if not already present.
4439 * @return true if value was successfully inserted or already present,
4440 * false if the list is full and does not contain the value.
4441 */
4442static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
4443 for (size_t i = 0; i < list_length; i++) {
4444 if (list[i] == value) return true; // value is already present
4445 if (list[i] == 0) { // no values in this slot
4446 list[i] = value;
4447 return true; // value inserted
4448 }
4449 }
4450 return false; // could not insert value
4451}
4452
4453/** Add channel_mask in supported_channel_masks if not already present.
4454 * @return true if channel_mask was successfully inserted or already present,
4455 * false if supported_channel_masks is full and does not contain channel_mask.
4456 */
4457static void register_channel_mask(audio_channel_mask_t channel_mask,
4458 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
4459 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
4460 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
4461}
4462
4463/** Add format in supported_formats if not already present.
4464 * @return true if format was successfully inserted or already present,
4465 * false if supported_formats is full and does not contain format.
4466 */
4467static void register_format(audio_format_t format,
4468 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
4469 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
4470 "%s: stream can not declare supporting its format %x", __func__, format);
4471}
4472/** Add sample_rate in supported_sample_rates if not already present.
4473 * @return true if sample_rate was successfully inserted or already present,
4474 * false if supported_sample_rates is full and does not contain sample_rate.
4475 */
4476static void register_sample_rate(uint32_t sample_rate,
4477 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
4478 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
4479 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
4480}
4481
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004482static inline uint32_t lcm(uint32_t num1, uint32_t num2)
4483{
4484 uint32_t high = num1, low = num2, temp = 0;
4485
4486 if (!num1 || !num2)
4487 return 0;
4488
4489 if (num1 < num2) {
4490 high = num2;
4491 low = num1;
4492 }
4493
4494 while (low != 0) {
4495 temp = low;
4496 low = high % low;
4497 high = temp;
4498 }
4499 return (num1 * num2)/high;
4500}
4501
4502static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
4503{
4504 uint32_t remainder = 0;
4505
4506 if (!multiplier)
4507 return num;
4508
4509 remainder = num % multiplier;
4510 if (remainder)
4511 num += (multiplier - remainder);
4512
4513 return num;
4514}
4515
Aalique Grahame22e49102018-12-18 14:23:57 -08004516static size_t get_stream_buffer_size(size_t duration_ms,
4517 uint32_t sample_rate,
4518 audio_format_t format,
4519 int channel_count,
4520 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004521{
4522 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004523 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004524
Aalique Grahame22e49102018-12-18 14:23:57 -08004525 size = (sample_rate * duration_ms) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004526 if (is_low_latency)
4527 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304528
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004529 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08004530 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004531
Ralf Herzbd08d632018-09-28 15:50:49 +02004532 /* make sure the size is multiple of 32 bytes and additionally multiple of
4533 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004534 * At 48 kHz mono 16-bit PCM:
4535 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
4536 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004537 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004538 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004539 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07004540
4541 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004542}
4543
Aalique Grahame22e49102018-12-18 14:23:57 -08004544static size_t get_input_buffer_size(uint32_t sample_rate,
4545 audio_format_t format,
4546 int channel_count,
4547 bool is_low_latency)
4548{
4549 /* Don't know if USB HIFI in this context so use true to be conservative */
4550 if (check_input_parameters(sample_rate, format, channel_count,
4551 true /*is_usb_hifi */) != 0)
4552 return 0;
4553
4554 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4555 sample_rate,
4556 format,
4557 channel_count,
4558 is_low_latency);
4559}
4560
Derek Chenf6318be2017-06-12 17:16:24 -04004561size_t get_output_period_size(uint32_t sample_rate,
4562 audio_format_t format,
4563 int channel_count,
4564 int duration /*in millisecs*/)
Ashish Jain058165c2016-09-28 23:18:48 +05304565{
4566 size_t size = 0;
4567 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
4568
4569 if ((duration == 0) || (sample_rate == 0) ||
4570 (bytes_per_sample == 0) || (channel_count == 0)) {
4571 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
4572 bytes_per_sample, channel_count);
4573 return -EINVAL;
4574 }
4575
4576 size = (sample_rate *
4577 duration *
4578 bytes_per_sample *
4579 channel_count) / 1000;
4580 /*
4581 * To have same PCM samples for all channels, the buffer size requires to
4582 * be multiple of (number of channels * bytes per sample)
4583 * For writes to succeed, the buffer must be written at address which is multiple of 32
4584 */
4585 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
4586
4587 return (size/(channel_count * bytes_per_sample));
4588}
4589
Zhou Song48453a02018-01-10 17:50:59 +08004590static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05304591{
4592 uint64_t actual_frames_rendered = 0;
Weiyin Jiang4813da12020-05-28 00:37:28 +08004593 uint64_t written_frames = 0;
4594 uint64_t kernel_frames = 0;
4595 uint64_t dsp_frames = 0;
4596 uint64_t signed_frames = 0;
4597 size_t kernel_buffer_size = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304598
4599 /* This adjustment accounts for buffering after app processor.
4600 * It is based on estimated DSP latency per use case, rather than exact.
4601 */
George Gao9ba8a142020-07-23 14:30:03 -07004602 dsp_frames = platform_render_latency(out) *
Weiyin Jiang4813da12020-05-28 00:37:28 +08004603 out->sample_rate / 1000000LL;
Ashish Jain5106d362016-05-11 19:23:33 +05304604
Zhou Song48453a02018-01-10 17:50:59 +08004605 pthread_mutex_lock(&out->position_query_lock);
Weiyin Jiang4813da12020-05-28 00:37:28 +08004606 written_frames = out->written /
4607 (audio_bytes_per_sample(out->hal_ip_format) * popcount(out->channel_mask));
4608
Ashish Jain5106d362016-05-11 19:23:33 +05304609 /* not querying actual state of buffering in kernel as it would involve an ioctl call
4610 * which then needs protection, this causes delay in TS query for pcm_offload usecase
4611 * hence only estimate.
4612 */
Weiyin Jiang4813da12020-05-28 00:37:28 +08004613 kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
4614 kernel_frames = kernel_buffer_size /
4615 (audio_bytes_per_sample(out->hal_op_format) * popcount(out->channel_mask));
Ashish Jain5106d362016-05-11 19:23:33 +05304616
Weiyin Jiang4813da12020-05-28 00:37:28 +08004617 if (written_frames >= (kernel_frames + dsp_frames))
4618 signed_frames = written_frames - kernel_frames - dsp_frames;
Ashish Jain5106d362016-05-11 19:23:33 +05304619
Zhou Song48453a02018-01-10 17:50:59 +08004620 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05304621 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08004622 if (timestamp != NULL )
4623 *timestamp = out->writeAt;
4624 } else if (timestamp != NULL) {
4625 clock_gettime(CLOCK_MONOTONIC, timestamp);
4626 }
4627 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304628
Weiyin Jiang4813da12020-05-28 00:37:28 +08004629 ALOGVV("%s signed frames %lld written frames %lld kernel frames %lld dsp frames %lld",
4630 __func__, signed_frames, written_frames, kernel_frames, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05304631
4632 return actual_frames_rendered;
4633}
4634
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004635static uint32_t out_get_sample_rate(const struct audio_stream *stream)
4636{
4637 struct stream_out *out = (struct stream_out *)stream;
4638
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004639 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004640}
4641
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004642static int out_set_sample_rate(struct audio_stream *stream __unused,
4643 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004644{
4645 return -ENOSYS;
4646}
4647
4648static size_t out_get_buffer_size(const struct audio_stream *stream)
4649{
4650 struct stream_out *out = (struct stream_out *)stream;
4651
Varun Balaraje49253e2017-07-06 19:48:56 +05304652 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05304653 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05304654 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304655 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4656 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
4657 else
4658 return out->compr_config.fragment_size;
4659 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004660 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304661 else if (is_offload_usecase(out->usecase) &&
4662 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304663 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004664
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004665 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004666 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004667}
4668
4669static uint32_t out_get_channels(const struct audio_stream *stream)
4670{
4671 struct stream_out *out = (struct stream_out *)stream;
4672
4673 return out->channel_mask;
4674}
4675
4676static audio_format_t out_get_format(const struct audio_stream *stream)
4677{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004678 struct stream_out *out = (struct stream_out *)stream;
4679
4680 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004681}
4682
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004683static int out_set_format(struct audio_stream *stream __unused,
4684 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004685{
4686 return -ENOSYS;
4687}
4688
4689static int out_standby(struct audio_stream *stream)
4690{
4691 struct stream_out *out = (struct stream_out *)stream;
4692 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07004693 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004694
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304695 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4696 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004697
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004698 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004699 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004700 if (adev->adm_deregister_stream)
4701 adev->adm_deregister_stream(adev->adm_data, out->handle);
4702
Weiyin Jiang280ea742020-09-08 20:28:22 +08004703 if (is_offload_usecase(out->usecase)) {
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004704 stop_compressed_output_l(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08004705 }
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004706
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004707 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004708 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004709 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4710 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304711 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08004712 pthread_mutex_unlock(&adev->lock);
4713 pthread_mutex_unlock(&out->lock);
4714 ALOGD("VOIP output entered standby");
4715 return 0;
4716 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004717 if (out->pcm) {
4718 pcm_close(out->pcm);
4719 out->pcm = NULL;
4720 }
Meng Wanga09da002020-04-20 12:56:04 +08004721 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4722 if (adev->haptic_pcm) {
4723 pcm_close(adev->haptic_pcm);
4724 adev->haptic_pcm = NULL;
4725 }
4726
4727 if (adev->haptic_buffer != NULL) {
4728 free(adev->haptic_buffer);
4729 adev->haptic_buffer = NULL;
4730 adev->haptic_buffer_size = 0;
4731 }
4732 adev->haptic_pcm_device_id = 0;
4733 }
4734
Haynes Mathew George16081042017-05-31 17:16:49 -07004735 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4736 do_stop = out->playback_started;
4737 out->playback_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07004738
4739 if (out->mmap_shared_memory_fd >= 0) {
4740 ALOGV("%s: closing mmap_shared_memory_fd = %d",
4741 __func__, out->mmap_shared_memory_fd);
4742 close(out->mmap_shared_memory_fd);
4743 out->mmap_shared_memory_fd = -1;
4744 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004745 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004746 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004747 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304748 out->send_next_track_params = false;
4749 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004750 out->gapless_mdata.encoder_delay = 0;
4751 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004752 if (out->compr != NULL) {
4753 compress_close(out->compr);
4754 out->compr = NULL;
4755 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004756 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004757 if (do_stop) {
4758 stop_output_stream(out);
4759 }
Lakshman Chaluvaraju06677b42019-06-24 10:04:52 +05304760 // if fm is active route on selected device in UI
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004761 audio_extn_fm_route_on_selected_device(adev, &out->device_list);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004762 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004763 }
4764 pthread_mutex_unlock(&out->lock);
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07004765 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004766 return 0;
4767}
4768
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304769static int out_on_error(struct audio_stream *stream)
4770{
4771 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004772 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304773
4774 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004775 // always send CMD_ERROR for offload streams, this
4776 // is needed e.g. when SSR happens within compress_open
4777 // since the stream is active, offload_callback_thread is also active.
4778 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
4779 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004780 }
4781 pthread_mutex_unlock(&out->lock);
4782
4783 status = out_standby(&out->stream.common);
4784
4785 lock_output_stream(out);
4786 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004787 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304788 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05304789
4790 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
4791 ALOGD("Setting previous card status if offline");
4792 out->prev_card_status_offline = true;
4793 }
4794
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304795 pthread_mutex_unlock(&out->lock);
4796
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004797 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304798}
4799
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304800/*
Weiyin Jiang280ea742020-09-08 20:28:22 +08004801 * standby implementation without locks, assumes that the callee already
4802 * has taken adev and out lock.
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304803 */
4804int out_standby_l(struct audio_stream *stream)
4805{
4806 struct stream_out *out = (struct stream_out *)stream;
4807 struct audio_device *adev = out->dev;
4808
4809 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4810 stream, out->usecase, use_case_table[out->usecase]);
4811
4812 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07004813 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304814 if (adev->adm_deregister_stream)
4815 adev->adm_deregister_stream(adev->adm_data, out->handle);
4816
Weiyin Jiang280ea742020-09-08 20:28:22 +08004817 if (is_offload_usecase(out->usecase)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304818 stop_compressed_output_l(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08004819 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304820
4821 out->standby = true;
4822 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4823 voice_extn_compress_voip_close_output_stream(stream);
4824 out->started = 0;
4825 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07004826 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304827 return 0;
4828 } else if (!is_offload_usecase(out->usecase)) {
4829 if (out->pcm) {
4830 pcm_close(out->pcm);
4831 out->pcm = NULL;
4832 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004833 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4834 if (adev->haptic_pcm) {
4835 pcm_close(adev->haptic_pcm);
4836 adev->haptic_pcm = NULL;
4837 }
4838
4839 if (adev->haptic_buffer != NULL) {
4840 free(adev->haptic_buffer);
4841 adev->haptic_buffer = NULL;
4842 adev->haptic_buffer_size = 0;
4843 }
4844 adev->haptic_pcm_device_id = 0;
4845 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304846 } else {
4847 ALOGD("copl(%p):standby", out);
4848 out->send_next_track_params = false;
4849 out->is_compr_metadata_avail = false;
4850 out->gapless_mdata.encoder_delay = 0;
4851 out->gapless_mdata.encoder_padding = 0;
4852 if (out->compr != NULL) {
4853 compress_close(out->compr);
4854 out->compr = NULL;
4855 }
4856 }
4857 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004858 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304859 }
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07004860 ALOGV("%s: exit", __func__);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304861 return 0;
4862}
4863
Aalique Grahame22e49102018-12-18 14:23:57 -08004864static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004865{
Aalique Grahame22e49102018-12-18 14:23:57 -08004866 struct stream_out *out = (struct stream_out *)stream;
4867
4868 // We try to get the lock for consistency,
4869 // but it isn't necessary for these variables.
4870 // If we're not in standby, we may be blocked on a write.
4871 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
4872 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
4873 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
Dechen Chai22768452021-07-30 09:29:16 +05304874#ifndef LINUX_ENABLED
Andy Hunga1f48fa2019-07-01 18:14:53 -07004875 char buffer[256]; // for statistics formatting
4876 if (!is_offload_usecase(out->usecase)) {
4877 simple_stats_to_string(&out->fifo_underruns, buffer, sizeof(buffer));
4878 dprintf(fd, " Fifo frame underruns: %s\n", buffer);
4879 }
4880
Andy Hungc6bfd4a2019-07-01 18:26:00 -07004881 if (out->start_latency_ms.n > 0) {
4882 simple_stats_to_string(&out->start_latency_ms, buffer, sizeof(buffer));
4883 dprintf(fd, " Start latency ms: %s\n", buffer);
4884 }
Dechen Chai22768452021-07-30 09:29:16 +05304885#endif
Aalique Grahame22e49102018-12-18 14:23:57 -08004886 if (locked) {
4887 pthread_mutex_unlock(&out->lock);
4888 }
4889
Dechen Chai22768452021-07-30 09:29:16 +05304890#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -08004891 // dump error info
4892 (void)error_log_dump(
4893 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Dechen Chai22768452021-07-30 09:29:16 +05304894#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004895 return 0;
4896}
4897
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004898static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
4899{
4900 int ret = 0;
4901 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08004902
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004903 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004904 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004905 return -EINVAL;
4906 }
4907
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304908 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08004909
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004910 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
4911 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304912 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004913 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004914 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
4915 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304916 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004917 }
4918
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004919 ALOGV("%s new encoder delay %u and padding %u", __func__,
4920 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
4921
4922 return 0;
4923}
4924
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004925static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
4926{
4927 return out == adev->primary_output || out == adev->voice_tx_output;
4928}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004929
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304930// note: this call is safe only if the stream_cb is
4931// removed first in close_output_stream (as is done now).
4932static void out_snd_mon_cb(void * stream, struct str_parms * parms)
4933{
4934 if (!stream || !parms)
4935 return;
4936
4937 struct stream_out *out = (struct stream_out *)stream;
4938 struct audio_device *adev = out->dev;
4939
4940 card_status_t status;
4941 int card;
4942 if (parse_snd_card_status(parms, &card, &status) < 0)
4943 return;
4944
4945 pthread_mutex_lock(&adev->lock);
4946 bool valid_cb = (card == adev->snd_card);
4947 pthread_mutex_unlock(&adev->lock);
4948
4949 if (!valid_cb)
4950 return;
4951
4952 lock_output_stream(out);
4953 if (out->card_status != status)
4954 out->card_status = status;
4955 pthread_mutex_unlock(&out->lock);
4956
4957 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
4958 use_case_table[out->usecase],
4959 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4960
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304961 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304962 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304963 if (voice_is_call_state_active(adev) &&
4964 out == adev->primary_output) {
4965 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
4966 pthread_mutex_lock(&adev->lock);
4967 voice_stop_call(adev);
4968 adev->mode = AUDIO_MODE_NORMAL;
4969 pthread_mutex_unlock(&adev->lock);
4970 }
4971 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304972 return;
4973}
4974
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004975int route_output_stream(struct stream_out *out,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004976 struct listnode *devices)
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004977{
4978 struct audio_device *adev = out->dev;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004979 int ret = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004980 struct listnode new_devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004981 bool bypass_a2dp = false;
4982 bool reconfig = false;
4983 unsigned long service_interval = 0;
4984
4985 ALOGD("%s: enter: usecase(%d: %s) devices %x",
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004986 __func__, out->usecase, use_case_table[out->usecase], get_device_types(devices));
4987
4988 list_init(&new_devices);
4989 assign_devices(&new_devices, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004990
4991 lock_output_stream(out);
4992 pthread_mutex_lock(&adev->lock);
4993
4994 /*
4995 * When HDMI cable is unplugged the music playback is paused and
4996 * the policy manager sends routing=0. But the audioflinger continues
4997 * to write data until standby time (3sec). As the HDMI core is
4998 * turned off, the write gets blocked.
4999 * Avoid this by routing audio to speaker until standby.
5000 */
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08005001 if (is_single_device_type_equal(&out->device_list,
5002 AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005003 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005004 !audio_extn_passthru_is_passthrough_stream(out) &&
5005 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005006 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005007 }
5008 /*
5009 * When A2DP is disconnected the
5010 * music playback is paused and the policy manager sends routing=0
5011 * But the audioflinger continues to write data until standby time
5012 * (3sec). As BT is turned off, the write gets blocked.
5013 * Avoid this by routing audio to speaker until standby.
5014 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005015 if (is_a2dp_out_device_type(&out->device_list) &&
5016 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005017 !audio_extn_a2dp_source_is_ready() &&
5018 !adev->bt_sco_on) {
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 /*
Weiyin Jiangabedea32020-12-09 12:49:19 +08005022 * When USB headset is disconnected the music playback paused
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005023 * and the policy manager send routing=0. But if the USB is connected
5024 * back before the standby time, AFE is not closed and opened
5025 * when USB is connected back. So routing to speker will guarantee
5026 * AFE reconfiguration and AFE will be opend once USB is connected again
5027 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005028 if (is_usb_out_device_type(&out->device_list) &&
5029 list_empty(&new_devices) &&
5030 !audio_extn_usb_connected(NULL)) {
Sujin Panicker84d953a2020-11-16 17:39:54 +05305031 if (adev->mode == AUDIO_MODE_IN_CALL || adev->mode == AUDIO_MODE_IN_COMMUNICATION)
5032 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_EARPIECE, "");
5033 else
5034 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005035 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005036 /* To avoid a2dp to sco overlapping / BT device improper state
5037 * check with BT lib about a2dp streaming support before routing
5038 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005039 if (is_a2dp_out_device_type(&new_devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005040 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005041 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER) ||
5042 compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005043 //combo usecase just by pass a2dp
5044 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
5045 bypass_a2dp = true;
5046 } else {
5047 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
5048 /* update device to a2dp and don't route as BT returned error
5049 * However it is still possible a2dp routing called because
5050 * of current active device disconnection (like wired headset)
5051 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005052 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005053 pthread_mutex_unlock(&adev->lock);
5054 pthread_mutex_unlock(&out->lock);
5055 goto error;
5056 }
5057 }
5058 }
5059
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005060 // Workaround: If routing to an non existing usb device, fail gracefully
5061 // The routing request will otherwise block during 10 second
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005062 if (is_usb_out_device_type(&new_devices)) {
5063 struct str_parms *parms =
5064 str_parms_create_str(get_usb_device_address(&new_devices));
5065 if (!parms)
5066 goto error;
Weiyin Jiangabedea32020-12-09 12:49:19 +08005067 if (!audio_extn_usb_connected(NULL)) {
5068 ALOGW("%s: ignoring rerouting to non existing USB card", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005069 pthread_mutex_unlock(&adev->lock);
5070 pthread_mutex_unlock(&out->lock);
5071 str_parms_destroy(parms);
5072 ret = -ENOSYS;
5073 goto error;
5074 }
5075 str_parms_destroy(parms);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005076 }
5077
Weiyin Jiang80c8f9a2020-01-10 20:42:08 +08005078 // Workaround: If routing to an non existing hdmi device, fail gracefully
5079 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
5080 (platform_get_edid_info_v2(adev->platform,
5081 out->extconn.cs.controller,
5082 out->extconn.cs.stream) != 0)) {
5083 ALOGW("out_set_parameters() ignoring rerouting to non existing HDMI/DP");
5084 pthread_mutex_unlock(&adev->lock);
5085 pthread_mutex_unlock(&out->lock);
5086 ret = -ENOSYS;
5087 goto error;
5088 }
5089
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005090 /*
5091 * select_devices() call below switches all the usecases on the same
5092 * backend to the new device. Refer to check_usecases_codec_backend() in
5093 * the select_devices(). But how do we undo this?
5094 *
5095 * For example, music playback is active on headset (deep-buffer usecase)
5096 * and if we go to ringtones and select a ringtone, low-latency usecase
5097 * will be started on headset+speaker. As we can't enable headset+speaker
5098 * and headset devices at the same time, select_devices() switches the music
5099 * playback to headset+speaker while starting low-lateny usecase for ringtone.
5100 * So when the ringtone playback is completed, how do we undo the same?
5101 *
5102 * We are relying on the out_set_parameters() call on deep-buffer output,
5103 * once the ringtone playback is ended.
5104 * NOTE: We should not check if the current devices are same as new devices.
5105 * Because select_devices() must be called to switch back the music
5106 * playback to headset.
5107 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005108 if (!list_empty(&new_devices)) {
5109 bool same_dev = compare_devices(&out->device_list, &new_devices);
5110 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005111
5112 if (output_drives_call(adev, out)) {
5113 if (!voice_is_call_state_active(adev)) {
5114 if (adev->mode == AUDIO_MODE_IN_CALL) {
5115 adev->current_call_output = out;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005116 ret = voice_start_call(adev);
5117 }
5118 } else {
Kunlei Zhang253ad102020-10-14 16:21:28 +08005119 platform_is_volume_boost_supported_device(adev->platform, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005120 adev->current_call_output = out;
5121 voice_update_devices_for_all_voice_usecases(adev);
5122 }
5123 }
5124
Mingshu Pang971ff702020-09-09 15:28:22 +08005125 if (is_usb_out_device_type(&out->device_list)) {
5126 service_interval = audio_extn_usb_find_service_interval(false, true /*playback*/);
5127 audio_extn_usb_set_service_interval(true /*playback*/,
5128 service_interval,
5129 &reconfig);
5130 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
5131 }
5132
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005133 if (!out->standby) {
5134 if (!same_dev) {
5135 ALOGV("update routing change");
5136 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
5137 adev->perf_lock_opts,
5138 adev->perf_lock_opts_size);
5139 if (adev->adm_on_routing_change)
5140 adev->adm_on_routing_change(adev->adm_data,
5141 out->handle);
5142 }
5143 if (!bypass_a2dp) {
5144 select_devices(adev, out->usecase);
5145 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005146 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
5147 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005148 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005149 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005150 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005151 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005152 }
5153
5154 if (!same_dev) {
5155 // on device switch force swap, lower functions will make sure
5156 // to check if swap is allowed or not.
5157 platform_set_swap_channels(adev, true);
5158 audio_extn_perf_lock_release(&adev->perf_lock_handle);
5159 }
Zhou Songbaddf9f2020-11-20 13:57:39 +08005160 pthread_mutex_lock(&out->latch_lock);
5161 if (!is_a2dp_out_device_type(&out->device_list) || audio_extn_a2dp_source_is_ready()) {
5162 if (out->a2dp_muted) {
5163 out->a2dp_muted = false;
5164 if (is_offload_usecase(out->usecase))
5165 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5166 else if (out->usecase != USECASE_AUDIO_PLAYBACK_VOIP)
5167 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Weiyin Jiang280ea742020-09-08 20:28:22 +08005168 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005169 }
Zhou Songbaddf9f2020-11-20 13:57:39 +08005170 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP && !out->a2dp_muted)
5171 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
5172 pthread_mutex_unlock(&out->latch_lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005173 }
5174 }
5175
5176 pthread_mutex_unlock(&adev->lock);
5177 pthread_mutex_unlock(&out->lock);
5178
5179 /*handles device and call state changes*/
5180 audio_extn_extspk_update(adev->extspk);
5181
Revathi Uddaraju4255a632021-12-02 05:11:13 -08005182 clear_devices(&new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005183error:
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005184 ALOGV("%s: exit: code(%d)", __func__, ret);
5185 return ret;
5186}
5187
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005188static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
5189{
5190 struct stream_out *out = (struct stream_out *)stream;
5191 struct audio_device *adev = out->dev;
5192 struct str_parms *parms;
5193 char value[32];
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005194 int ret = 0, err;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005195 int ext_controller = -1;
5196 int ext_stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005197
sangwoobc677242013-08-08 16:53:43 +09005198 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005199 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005200 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305201 if (!parms)
5202 goto error;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005203
5204 err = platform_get_controller_stream_from_params(parms, &ext_controller,
5205 &ext_stream);
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08005206 if (err == 0) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005207 out->extconn.cs.controller = ext_controller;
5208 out->extconn.cs.stream = ext_stream;
5209 ALOGD("%s: usecase(%s) new controller/stream (%d/%d)", __func__,
5210 use_case_table[out->usecase], out->extconn.cs.controller,
5211 out->extconn.cs.stream);
5212 }
5213
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005214 if (out == adev->primary_output) {
5215 pthread_mutex_lock(&adev->lock);
5216 audio_extn_set_parameters(adev, parms);
5217 pthread_mutex_unlock(&adev->lock);
5218 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005219 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005220 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005221 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005222
5223 audio_extn_dts_create_state_notifier_node(out->usecase);
5224 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5225 popcount(out->channel_mask),
5226 out->playback_started);
5227
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08005228 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005229 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005230
Surendar Karkaf51b5842018-04-26 11:28:38 +05305231 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
5232 sizeof(value));
5233 if (err >= 0) {
5234 if (!strncmp("true", value, sizeof("true")) || atoi(value))
5235 audio_extn_send_dual_mono_mixing_coefficients(out);
5236 }
5237
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305238 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5239 if (err >= 0) {
5240 strlcpy(out->profile, value, sizeof(out->profile));
5241 ALOGV("updating stream profile with value '%s'", out->profile);
5242 lock_output_stream(out);
5243 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
5244 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005245 &out->device_list, out->flags,
5246 out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305247 out->sample_rate, out->bit_width,
5248 out->channel_mask, out->profile,
5249 &out->app_type_cfg);
5250 pthread_mutex_unlock(&out->lock);
5251 }
5252
Alexy Joseph98988832017-01-13 14:56:59 -08005253 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005254 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
5255 // and vendor.audio.hal.output.suspend.supported is set to true
5256 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08005257 //check suspend parameter only for low latency and if the property
5258 //is enabled
5259 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
5260 ALOGI("%s: got suspend_playback %s", __func__, value);
5261 lock_output_stream(out);
5262 if (!strncmp(value, "false", 5)) {
5263 //suspend_playback=false is supposed to set QOS value back to 75%
5264 //the mixer control sent with value Enable will achieve that
5265 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5266 } else if (!strncmp (value, "true", 4)) {
5267 //suspend_playback=true is supposed to remove QOS value
5268 //resetting the mixer control will set the default value
5269 //for the mixer control which is Disable and this removes the QOS vote
5270 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5271 } else {
5272 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
5273 " got %s", __func__, value);
5274 ret = -1;
5275 }
5276
5277 if (ret != 0) {
5278 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
5279 __func__, out->pm_qos_mixer_path, ret);
5280 }
5281
5282 pthread_mutex_unlock(&out->lock);
5283 }
5284 }
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005285
Alexy Joseph98988832017-01-13 14:56:59 -08005286 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005287 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305288error:
Eric Laurent994a6932013-07-17 11:51:42 -07005289 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005290 return ret;
5291}
5292
Paul McLeana50b7332018-12-17 08:24:21 -07005293static int in_set_microphone_direction(const struct audio_stream_in *stream,
5294 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07005295 struct stream_in *in = (struct stream_in *)stream;
5296
5297 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
5298
5299 in->direction = dir;
5300
5301 if (in->standby)
5302 return 0;
5303
5304 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07005305}
5306
5307static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07005308 struct stream_in *in = (struct stream_in *)stream;
5309
5310 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
5311
5312 if (zoom > 1.0 || zoom < -1.0)
5313 return -EINVAL;
5314
5315 in->zoom = zoom;
5316
5317 if (in->standby)
5318 return 0;
5319
5320 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07005321}
5322
5323
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005324static bool stream_get_parameter_channels(struct str_parms *query,
5325 struct str_parms *reply,
5326 audio_channel_mask_t *supported_channel_masks) {
5327 int ret = -1;
5328 char value[512];
5329 bool first = true;
5330 size_t i, j;
5331
5332 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
5333 ret = 0;
5334 value[0] = '\0';
5335 i = 0;
5336 while (supported_channel_masks[i] != 0) {
5337 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5338 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
5339 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305340 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005341
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305342 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005343 first = false;
5344 break;
5345 }
5346 }
5347 i++;
5348 }
5349 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5350 }
5351 return ret == 0;
5352}
5353
5354static bool stream_get_parameter_formats(struct str_parms *query,
5355 struct str_parms *reply,
5356 audio_format_t *supported_formats) {
5357 int ret = -1;
5358 char value[256];
5359 size_t i, j;
5360 bool first = true;
5361
5362 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
5363 ret = 0;
5364 value[0] = '\0';
5365 i = 0;
5366 while (supported_formats[i] != 0) {
5367 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5368 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
5369 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305370 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005371 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305372 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005373 first = false;
5374 break;
5375 }
5376 }
5377 i++;
5378 }
5379 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
5380 }
5381 return ret == 0;
5382}
5383
5384static bool stream_get_parameter_rates(struct str_parms *query,
5385 struct str_parms *reply,
5386 uint32_t *supported_sample_rates) {
5387
5388 int i;
5389 char value[256];
5390 int ret = -1;
5391 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
5392 ret = 0;
5393 value[0] = '\0';
5394 i=0;
5395 int cursor = 0;
5396 while (supported_sample_rates[i]) {
5397 int avail = sizeof(value) - cursor;
5398 ret = snprintf(value + cursor, avail, "%s%d",
5399 cursor > 0 ? "|" : "",
5400 supported_sample_rates[i]);
5401 if (ret < 0 || ret >= avail) {
5402 // if cursor is at the last element of the array
5403 // overwrite with \0 is duplicate work as
5404 // snprintf already put a \0 in place.
5405 // else
5406 // we had space to write the '|' at value[cursor]
5407 // (which will be overwritten) or no space to fill
5408 // the first element (=> cursor == 0)
5409 value[cursor] = '\0';
5410 break;
5411 }
5412 cursor += ret;
5413 ++i;
5414 }
5415 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
5416 value);
5417 }
5418 return ret >= 0;
5419}
5420
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005421static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
5422{
5423 struct stream_out *out = (struct stream_out *)stream;
5424 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005425 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005426 char value[256];
5427 struct str_parms *reply = str_parms_create();
5428 size_t i, j;
5429 int ret;
5430 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005431
5432 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005433 if (reply) {
5434 str_parms_destroy(reply);
5435 }
5436 if (query) {
5437 str_parms_destroy(query);
5438 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005439 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
5440 return NULL;
5441 }
5442
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005443 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005444 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
5445 if (ret >= 0) {
5446 value[0] = '\0';
5447 i = 0;
5448 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005449 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5450 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005451 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005452 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005453 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005454 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005455 first = false;
5456 break;
5457 }
5458 }
5459 i++;
5460 }
5461 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5462 str = str_parms_to_str(reply);
5463 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005464 voice_extn_out_get_parameters(out, query, reply);
5465 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005466 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005467
Alexy Joseph62142aa2015-11-16 15:10:34 -08005468
5469 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
5470 if (ret >= 0) {
5471 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05305472 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
5473 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08005474 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305475 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005476 } else {
5477 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05305478 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005479 }
5480 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005481 if (str)
5482 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08005483 str = str_parms_to_str(reply);
5484 }
5485
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005486 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
5487 if (ret >= 0) {
5488 value[0] = '\0';
5489 i = 0;
5490 first = true;
5491 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005492 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5493 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005494 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005495 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005496 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005497 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005498 first = false;
5499 break;
5500 }
5501 }
5502 i++;
5503 }
5504 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005505 if (str)
5506 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005507 str = str_parms_to_str(reply);
5508 }
Mingming Yin3a941d42016-02-17 18:08:05 -08005509
5510 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
5511 if (ret >= 0) {
5512 value[0] = '\0';
5513 i = 0;
5514 first = true;
5515 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005516 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
5517 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005518 if (!first) {
5519 strlcat(value, "|", sizeof(value));
5520 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005521 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08005522 first = false;
5523 break;
5524 }
5525 }
5526 i++;
5527 }
5528 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
5529 if (str)
5530 free(str);
5531 str = str_parms_to_str(reply);
5532 }
5533
Alexy Joseph98988832017-01-13 14:56:59 -08005534 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
5535 //only low latency track supports suspend_resume
5536 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005537 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08005538 if (str)
5539 free(str);
5540 str = str_parms_to_str(reply);
5541 }
5542
5543
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005544 str_parms_destroy(query);
5545 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07005546 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005547 return str;
5548}
5549
5550static uint32_t out_get_latency(const struct audio_stream_out *stream)
5551{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005552 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005553 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08005554 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005555
Alexy Josephaa54c872014-12-03 02:46:47 -08005556 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05305557 lock_output_stream(out);
5558 latency = audio_extn_utils_compress_get_dsp_latency(out);
5559 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005560 } else if ((out->realtime) ||
5561 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005562 // since the buffer won't be filled up faster than realtime,
5563 // return a smaller number
5564 if (out->config.rate)
5565 period_ms = (out->af_period_multiplier * out->config.period_size *
5566 1000) / (out->config.rate);
5567 else
5568 period_ms = 0;
George Gao9ba8a142020-07-23 14:30:03 -07005569 latency = period_ms + platform_render_latency(out) / 1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005570 } else {
5571 latency = (out->config.period_count * out->config.period_size * 1000) /
Mingshu Pangf69a88d2021-04-30 16:14:39 +08005572 (out->config.rate);
5573 if (out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER)
5574 latency += platform_render_latency(out)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005575 }
5576
Zhou Songd2537a02020-06-11 22:04:46 +08005577 if (!out->standby && is_a2dp_out_device_type(&out->device_list))
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08005578 latency += audio_extn_a2dp_get_encoder_latency();
5579
Anish Kumar50ebcbf2014-12-09 04:01:39 +05305580 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08005581 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005582}
5583
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305584static float AmpToDb(float amplification)
5585{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305586 float db = DSD_VOLUME_MIN_DB;
5587 if (amplification > 0) {
5588 db = 20 * log10(amplification);
5589 if(db < DSD_VOLUME_MIN_DB)
5590 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305591 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305592 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305593}
5594
Arun Mirpuri5d170872019-03-26 13:21:31 -07005595static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
5596 float right)
5597{
5598 struct stream_out *out = (struct stream_out *)stream;
5599 long volume = 0;
5600 char mixer_ctl_name[128] = "";
5601 struct audio_device *adev = out->dev;
5602 struct mixer_ctl *ctl = NULL;
5603 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5604 PCM_PLAYBACK);
5605
5606 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5607 "Playback %d Volume", pcm_device_id);
5608 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5609 if (!ctl) {
5610 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5611 __func__, mixer_ctl_name);
5612 return -EINVAL;
5613 }
5614 if (left != right)
5615 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
5616 __func__, left, right);
5617 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
5618 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
5619 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
5620 __func__, mixer_ctl_name, volume);
5621 return -EINVAL;
5622 }
5623 return 0;
5624}
5625
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305626static int out_set_compr_volume(struct audio_stream_out *stream, float left,
5627 float right)
5628{
5629 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305630 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305631 char mixer_ctl_name[128];
5632 struct audio_device *adev = out->dev;
5633 struct mixer_ctl *ctl;
5634 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5635 PCM_PLAYBACK);
5636
5637 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5638 "Compress Playback %d Volume", pcm_device_id);
5639 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5640 if (!ctl) {
5641 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5642 __func__, mixer_ctl_name);
5643 return -EINVAL;
5644 }
5645 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
5646 __func__, mixer_ctl_name, left, right);
5647 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
5648 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
5649 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5650
5651 return 0;
5652}
5653
Zhou Song2b8f28f2017-09-11 10:51:38 +08005654static int out_set_voip_volume(struct audio_stream_out *stream, float left,
5655 float right)
5656{
5657 struct stream_out *out = (struct stream_out *)stream;
5658 char mixer_ctl_name[] = "App Type Gain";
5659 struct audio_device *adev = out->dev;
5660 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305661 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08005662
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07005663 if (!is_valid_volume(left, right)) {
5664 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
5665 __func__, left, right);
5666 return -EINVAL;
5667 }
5668
Zhou Song2b8f28f2017-09-11 10:51:38 +08005669 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5670 if (!ctl) {
5671 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5672 __func__, mixer_ctl_name);
5673 return -EINVAL;
5674 }
5675
5676 set_values[0] = 0; //0: Rx Session 1:Tx Session
5677 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305678 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
5679 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005680
5681 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
5682 return 0;
5683}
5684
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305685static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
5686 float right)
5687{
5688 struct stream_out *out = (struct stream_out *)stream;
5689 /* Volume control for pcm playback */
5690 if (left != right) {
5691 return -EINVAL;
5692 } else {
5693 char mixer_ctl_name[128];
5694 struct audio_device *adev = out->dev;
5695 struct mixer_ctl *ctl;
5696 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5697 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
5698 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5699 if (!ctl) {
5700 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5701 return -EINVAL;
5702 }
5703
5704 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
5705 int ret = mixer_ctl_set_value(ctl, 0, volume);
5706 if (ret < 0) {
5707 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
5708 return -EINVAL;
5709 }
5710
5711 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
5712
5713 return 0;
5714 }
5715}
5716
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005717static int out_set_volume(struct audio_stream_out *stream, float left,
5718 float right)
5719{
Eric Laurenta9024de2013-04-04 09:19:12 -07005720 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005721 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305722 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005723
Arun Mirpuri5d170872019-03-26 13:21:31 -07005724 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07005725 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
5726 /* only take left channel into account: the API is for stereo anyway */
5727 out->muted = (left == 0.0f);
5728 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005729 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305730 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005731 /*
5732 * Set mute or umute on HDMI passthrough stream.
5733 * Only take left channel into account.
5734 * Mute is 0 and unmute 1
5735 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305736 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305737 } else if (out->format == AUDIO_FORMAT_DSD){
5738 char mixer_ctl_name[128] = "DSD Volume";
5739 struct audio_device *adev = out->dev;
5740 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5741
5742 if (!ctl) {
5743 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5744 __func__, mixer_ctl_name);
5745 return -EINVAL;
5746 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05305747 volume[0] = (long)(AmpToDb(left));
5748 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305749 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5750 return 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005751 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS) &&
Derek Chendf05eea2019-08-01 13:57:49 -07005752 (out->car_audio_stream == CAR_AUDIO_STREAM_MEDIA)) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005753 ALOGD("%s: Overriding offload set volume for media bus stream", __func__);
5754 struct listnode *node = NULL;
5755 list_for_each(node, &adev->active_outputs_list) {
5756 streams_output_ctxt_t *out_ctxt = node_to_item(node,
5757 streams_output_ctxt_t,
5758 list);
5759 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
5760 out->volume_l = out_ctxt->output->volume_l;
5761 out->volume_r = out_ctxt->output->volume_r;
5762 }
5763 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08005764 pthread_mutex_lock(&out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +08005765 if (!out->a2dp_muted) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005766 ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5767 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08005768 pthread_mutex_unlock(&out->latch_lock);
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005769 return ret;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005770 } else {
Weiyin Jiang280ea742020-09-08 20:28:22 +08005771 pthread_mutex_lock(&out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +08005772 ALOGV("%s: compress mute %d", __func__, out->a2dp_muted);
5773 if (!out->a2dp_muted)
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305774 ret = out_set_compr_volume(stream, left, right);
5775 out->volume_l = left;
5776 out->volume_r = right;
Weiyin Jiang280ea742020-09-08 20:28:22 +08005777 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305778 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005779 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005780 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005781 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
5782 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Songbaddf9f2020-11-20 13:57:39 +08005783 pthread_mutex_lock(&out->latch_lock);
Aalique Grahame22e49102018-12-18 14:23:57 -08005784 if (!out->standby) {
5785 audio_extn_utils_send_app_type_gain(out->dev,
5786 out->app_type_cfg.app_type,
5787 &out->app_type_cfg.gain[0]);
Zhou Songbaddf9f2020-11-20 13:57:39 +08005788 if (!out->a2dp_muted)
5789 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08005790 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08005791 out->volume_l = left;
5792 out->volume_r = right;
Zhou Songbaddf9f2020-11-20 13:57:39 +08005793 pthread_mutex_unlock(&out->latch_lock);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005794 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005795 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5796 ALOGV("%s: MMAP set volume called", __func__);
5797 if (!out->standby)
5798 ret = out_set_mmap_volume(stream, left, right);
5799 out->volume_l = left;
5800 out->volume_r = right;
5801 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305802 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05305803 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5804 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Zhou Songbaddf9f2020-11-20 13:57:39 +08005805 pthread_mutex_lock(&out->latch_lock);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305806 /* Volume control for pcm playback */
Zhou Songbaddf9f2020-11-20 13:57:39 +08005807 if (!out->standby && !out->a2dp_muted)
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305808 ret = out_set_pcm_volume(stream, left, right);
5809 else
5810 out->apply_volume = true;
5811
5812 out->volume_l = left;
5813 out->volume_r = right;
Zhou Songbaddf9f2020-11-20 13:57:39 +08005814 pthread_mutex_unlock(&out->latch_lock);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305815 return ret;
Derek Chenf13dd492018-11-13 14:53:51 -08005816 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
5817 ALOGV("%s: bus device set volume called", __func__);
Zhou Songbaddf9f2020-11-20 13:57:39 +08005818 pthread_mutex_lock(&out->latch_lock);
5819 if (!out->standby && !out->a2dp_muted)
Derek Chenf13dd492018-11-13 14:53:51 -08005820 ret = out_set_pcm_volume(stream, left, right);
5821 out->volume_l = left;
5822 out->volume_r = right;
Zhou Songbaddf9f2020-11-20 13:57:39 +08005823 pthread_mutex_unlock(&out->latch_lock);
Derek Chenf13dd492018-11-13 14:53:51 -08005824 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07005825 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005826
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005827 return -ENOSYS;
5828}
5829
Zhou Songc9672822017-08-16 16:01:39 +08005830static void update_frames_written(struct stream_out *out, size_t bytes)
5831{
5832 size_t bpf = 0;
5833
5834 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
5835 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
5836 bpf = 1;
5837 else if (!is_offload_usecase(out->usecase))
5838 bpf = audio_bytes_per_sample(out->format) *
5839 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08005840
5841 pthread_mutex_lock(&out->position_query_lock);
5842 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08005843 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08005844 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
5845 }
5846 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08005847}
5848
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005849int split_and_write_audio_haptic_data(struct stream_out *out,
5850 const void *buffer, size_t bytes_to_write)
5851{
5852 struct audio_device *adev = out->dev;
5853
5854 int ret = 0;
5855 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5856 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
5857 size_t frame_size = channel_count * bytes_per_sample;
5858 size_t frame_count = bytes_to_write / frame_size;
5859
5860 bool force_haptic_path =
5861 property_get_bool("vendor.audio.test_haptic", false);
5862
5863 // extract Haptics data from Audio buffer
5864 bool alloc_haptic_buffer = false;
5865 int haptic_channel_count = adev->haptics_config.channels;
5866 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
5867 size_t audio_frame_size = frame_size - haptic_frame_size;
5868 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
5869
5870 if (adev->haptic_buffer == NULL) {
5871 alloc_haptic_buffer = true;
5872 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
5873 free(adev->haptic_buffer);
5874 adev->haptic_buffer_size = 0;
5875 alloc_haptic_buffer = true;
5876 }
5877
5878 if (alloc_haptic_buffer) {
5879 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08005880 if(adev->haptic_buffer == NULL) {
5881 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
5882 return -ENOMEM;
5883 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005884 adev->haptic_buffer_size = total_haptic_buffer_size;
5885 }
5886
5887 size_t src_index = 0, aud_index = 0, hap_index = 0;
5888 uint8_t *audio_buffer = (uint8_t *)buffer;
5889 uint8_t *haptic_buffer = adev->haptic_buffer;
5890
5891 // This is required for testing only. This works for stereo data only.
5892 // One channel is fed to audio stream and other to haptic stream for testing.
5893 if (force_haptic_path)
5894 audio_frame_size = haptic_frame_size = bytes_per_sample;
5895
5896 for (size_t i = 0; i < frame_count; i++) {
5897 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
5898 audio_frame_size);
5899 aud_index += audio_frame_size;
5900 src_index += audio_frame_size;
5901
5902 if (adev->haptic_pcm)
5903 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
5904 haptic_frame_size);
5905 hap_index += haptic_frame_size;
5906 src_index += haptic_frame_size;
5907
5908 // This is required for testing only.
5909 // Discard haptic channel data.
5910 if (force_haptic_path)
5911 src_index += haptic_frame_size;
5912 }
5913
5914 // write to audio pipeline
5915 ret = pcm_write(out->pcm, (void *)audio_buffer,
5916 frame_count * audio_frame_size);
5917
5918 // write to haptics pipeline
5919 if (adev->haptic_pcm)
5920 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
5921 frame_count * haptic_frame_size);
5922
5923 return ret;
5924}
5925
Aalique Grahame22e49102018-12-18 14:23:57 -08005926#ifdef NO_AUDIO_OUT
5927static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
5928 const void *buffer __unused, size_t bytes)
5929{
5930 struct stream_out *out = (struct stream_out *)stream;
5931
5932 /* No Output device supported other than BT for playback.
5933 * Sleep for the amount of buffer duration
5934 */
5935 lock_output_stream(out);
5936 usleep(bytes * 1000000 / audio_stream_out_frame_size(
5937 (const struct audio_stream_out *)&out->stream) /
5938 out_get_sample_rate(&out->stream.common));
5939 pthread_mutex_unlock(&out->lock);
5940 return bytes;
5941}
5942#endif
5943
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005944static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
5945 size_t bytes)
5946{
5947 struct stream_out *out = (struct stream_out *)stream;
5948 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07005949 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305950 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005951 const size_t frame_size = audio_stream_out_frame_size(stream);
5952 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305953 struct audio_usecase *usecase = NULL;
Meng Wang4c32fb42020-01-16 17:57:11 +08005954 uint32_t compr_passthr = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005955
Haynes Mathew George380745d2017-10-04 15:27:45 -07005956 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005957 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305958
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305959 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08005960
Dhananjay Kumarac341582017-02-23 23:42:25 +05305961 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305962 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05305963 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
5964 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005965 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305966 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05305967 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05305968 ALOGD(" %s: sound card is not active/SSR state", __func__);
5969 ret= -EIO;
5970 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305971 }
5972 }
5973
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305974 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305975 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305976 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305977 goto exit;
5978 }
5979
Haynes Mathew George16081042017-05-31 17:16:49 -07005980 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5981 ret = -EINVAL;
5982 goto exit;
5983 }
5984
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005985 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305986 !out->is_iec61937_info_available) {
5987
5988 if (!audio_extn_passthru_is_passthrough_stream(out)) {
5989 out->is_iec61937_info_available = true;
5990 } else if (audio_extn_passthru_is_enabled()) {
5991 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05305992 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05305993
5994 if((out->format == AUDIO_FORMAT_DTS) ||
5995 (out->format == AUDIO_FORMAT_DTS_HD)) {
5996 ret = audio_extn_passthru_update_dts_stream_configuration(out,
5997 buffer, bytes);
5998 if (ret) {
5999 if (ret != -ENOSYS) {
6000 out->is_iec61937_info_available = false;
6001 ALOGD("iec61937 transmission info not yet updated retry");
6002 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306003 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05306004 /* if stream has started and after that there is
6005 * stream config change (iec transmission config)
6006 * then trigger select_device to update backend configuration.
6007 */
6008 out->stream_config_changed = true;
6009 pthread_mutex_lock(&adev->lock);
6010 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306011 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08006012 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306013 ret = -EINVAL;
6014 goto exit;
6015 }
Manish Dewangan671a4202017-08-18 17:30:46 +05306016 pthread_mutex_unlock(&adev->lock);
6017 out->stream_config_changed = false;
6018 out->is_iec61937_info_available = true;
6019 }
6020 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05306021
Meng Wang4c32fb42020-01-16 17:57:11 +08006022#ifdef AUDIO_GKI_ENABLED
6023 /* out->compr_config.codec->reserved[0] is for compr_passthr */
6024 compr_passthr = out->compr_config.codec->reserved[0];
6025#else
6026 compr_passthr = out->compr_config.codec->compr_passthr;
6027#endif
6028
Garmond Leung317cbf12017-09-13 16:20:50 -07006029 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Meng Wang4c32fb42020-01-16 17:57:11 +08006030 (compr_passthr == PASSTHROUGH) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05306031 (out->is_iec61937_info_available == true)) {
6032 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
6033 ret = -EINVAL;
6034 goto exit;
6035 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05306036 }
6037 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306038
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006039 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02006040 (audio_extn_a2dp_source_is_suspended())) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006041 if (!(compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER) ||
6042 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Zhou Songd01e7a22020-09-23 22:49:01 +08006043 if (!is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306044 ret = -EIO;
6045 goto exit;
6046 }
6047 }
6048 }
6049
Weiyin Jiangabedea32020-12-09 12:49:19 +08006050 if (is_usb_out_device_type(&out->device_list) &&
6051 !audio_extn_usb_connected(NULL)) {
6052 ret = -EIO;
6053 goto exit;
6054 }
6055
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006056 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07006057 out->standby = false;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006058 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
6059
Eric Laurent150dbfe2013-02-27 14:31:02 -08006060 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006061 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
6062 ret = voice_extn_compress_voip_start_output_stream(out);
6063 else
6064 ret = start_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006065 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006066 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07006067 out->standby = true;
Weiyin Jiangac2bae82020-07-29 17:23:53 +08006068 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006069 goto exit;
6070 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306071 out->started = 1;
Andy Hunga1f48fa2019-07-01 18:14:53 -07006072 out->last_fifo_valid = false; // we're coming out of standby, last_fifo isn't valid.
Weiyin Jiangac2bae82020-07-29 17:23:53 +08006073
6074 if ((last_known_cal_step != -1) && (adev->platform != NULL)) {
vivek mehtab72d08d2016-04-29 03:16:47 -07006075 ALOGD("%s: retry previous failed cal level set", __func__);
Weiyin Jiangac2bae82020-07-29 17:23:53 +08006076 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05306077 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07006078 }
Weiyin Jiangac2bae82020-07-29 17:23:53 +08006079 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306080
6081 if ((out->is_iec61937_info_available == true) &&
6082 (audio_extn_passthru_is_passthrough_stream(out))&&
6083 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
6084 ret = -EINVAL;
6085 goto exit;
6086 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05306087 if (out->set_dual_mono)
6088 audio_extn_send_dual_mono_mixing_coefficients(out);
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006089
Dechen Chai22768452021-07-30 09:29:16 +05306090#ifndef LINUX_ENABLED
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006091 // log startup time in ms.
6092 simple_stats_log(
6093 &out->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Dechen Chai22768452021-07-30 09:29:16 +05306094#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006095 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006096
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006097 if (adev->is_channel_status_set == false &&
6098 compare_device_type(&out->device_list,
6099 AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Alexy Josephb1379942016-01-29 15:49:38 -08006100 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05306101 adev->is_channel_status_set = true;
6102 }
6103
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05306104 if ((adev->use_old_pspd_mix_ctrl == true) &&
6105 (out->pspd_coeff_sent == false)) {
6106 /*
6107 * Need to resend pspd coefficients after stream started for
6108 * older kernel version as it does not save the coefficients
6109 * and also stream has to be started for coeff to apply.
6110 */
6111 usecase = get_usecase_from_list(adev, out->usecase);
6112 if (usecase != NULL) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05306113 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05306114 out->pspd_coeff_sent = true;
6115 }
6116 }
6117
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006118 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08006119 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006120 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006121 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006122 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
6123 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05306124 if (out->send_next_track_params && out->is_compr_metadata_avail) {
6125 ALOGD("copl(%p):send next track params in gapless", out);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08006126 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05306127 out->send_next_track_params = false;
6128 out->is_compr_metadata_avail = false;
6129 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006130 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05306131 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306132 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006133
Ashish Jain83a6cc22016-06-28 14:34:17 +05306134 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05306135 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05306136 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05306137 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006138 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05306139 return -EINVAL;
6140 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05306141 audio_format_t dst_format = out->hal_op_format;
6142 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306143
Dieter Luecking5d57def2018-09-07 14:23:37 +02006144 /* prevent division-by-zero */
6145 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
6146 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
6147 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
6148 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05306149 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006150 ATRACE_END();
6151 return -EINVAL;
6152 }
6153
Ashish Jainf1eaa582016-05-23 20:54:24 +05306154 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
6155 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
6156
Ashish Jain83a6cc22016-06-28 14:34:17 +05306157 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05306158 dst_format,
6159 buffer,
6160 src_format,
6161 frames);
6162
Ashish Jain83a6cc22016-06-28 14:34:17 +05306163 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05306164 bytes_to_write);
6165
6166 /*Convert written bytes in audio flinger format*/
6167 if (ret > 0)
6168 ret = ((ret * format_to_bitwidth_table[out->format]) /
6169 format_to_bitwidth_table[dst_format]);
6170 }
6171 } else
6172 ret = compress_write(out->compr, buffer, bytes);
6173
Zhou Songc9672822017-08-16 16:01:39 +08006174 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
6175 update_frames_written(out, bytes);
6176
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306177 if (ret < 0)
6178 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08006179 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05306180 /*msg to cb thread only if non blocking write is enabled*/
6181 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05306182 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006183 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05306184 } else if (-ENETRESET == ret) {
6185 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306186 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05306187 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05306188 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006189 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05306190 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006191 }
Ashish Jain5106d362016-05-11 19:23:33 +05306192
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05306193 /* Call compr start only when non-zero bytes of data is there to be rendered */
6194 if (!out->playback_started && ret > 0) {
6195 int status = compress_start(out->compr);
6196 if (status < 0) {
6197 ret = status;
6198 ALOGE("%s: compr start failed with err %d", __func__, errno);
6199 goto exit;
6200 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07006201 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006202 out->playback_started = 1;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006203 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006204 out->offload_state = OFFLOAD_STATE_PLAYING;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006205 pthread_mutex_unlock(&out->latch_lock);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006206
6207 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6208 popcount(out->channel_mask),
6209 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006210 }
6211 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006212 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006213 return ret;
6214 } else {
6215 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006216 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006217 if (out->muted)
6218 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006219 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
6220 __func__, frames, frame_size, bytes_to_write);
6221
Aalique Grahame22e49102018-12-18 14:23:57 -08006222 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07006223 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
6224 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
6225 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006226 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
6227 int16_t *src = (int16_t *)buffer;
6228 int16_t *dst = (int16_t *)buffer;
6229
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006230 LOG_ALWAYS_FATAL_IF(channel_count > 2 ||
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006231 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08006232 "out_write called for %s use case with wrong properties",
6233 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006234
6235 /*
6236 * FIXME: this can be removed once audio flinger mixer supports
6237 * mono output
6238 */
6239
6240 /*
6241 * Code below goes over each frame in the buffer and adds both
6242 * L and R samples and then divides by 2 to convert to mono
6243 */
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006244 if (channel_count == 2) {
6245 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
6246 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
6247 }
6248 bytes_to_write /= 2;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006249 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006250 }
Andy Hunga1f48fa2019-07-01 18:14:53 -07006251
6252 // Note: since out_get_presentation_position() is called alternating with out_write()
6253 // by AudioFlinger, we can check underruns using the prior timestamp read.
6254 // (Alternately we could check if the buffer is empty using pcm_get_htimestamp().
6255 if (out->last_fifo_valid) {
6256 // compute drain to see if there is an underrun.
6257 const int64_t current_ns = systemTime(SYSTEM_TIME_MONOTONIC); // sys call
Dhananjay Kumara4429632020-07-11 02:53:37 +05306258 int64_t time_diff_ns = current_ns - out->last_fifo_time_ns;
6259 int64_t frames_by_time =
6260 ((time_diff_ns > 0) && (time_diff_ns < (INT64_MAX / out->config.rate))) ?
6261 (time_diff_ns * out->config.rate / NANOS_PER_SECOND) : 0;
Andy Hunga1f48fa2019-07-01 18:14:53 -07006262 const int64_t underrun = frames_by_time - out->last_fifo_frames_remaining;
6263
6264 if (underrun > 0) {
Dechen Chai22768452021-07-30 09:29:16 +05306265#ifndef LINUX_ENABLED
Andy Hunga1f48fa2019-07-01 18:14:53 -07006266 simple_stats_log(&out->fifo_underruns, underrun);
Dechen Chai22768452021-07-30 09:29:16 +05306267#endif
Andy Hunga1f48fa2019-07-01 18:14:53 -07006268
6269 ALOGW("%s: underrun(%lld) "
6270 "frames_by_time(%lld) > out->last_fifo_frames_remaining(%lld)",
6271 __func__,
6272 (long long)out->fifo_underruns.n,
6273 (long long)frames_by_time,
6274 (long long)out->last_fifo_frames_remaining);
6275 }
6276 out->last_fifo_valid = false; // we're writing below, mark fifo info as stale.
6277 }
6278
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306279 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006280
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006281 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006282
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006283 if (out->config.rate)
6284 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
6285 out->config.rate;
6286
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006287 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006288 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
6289
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006290 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006291 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006292 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306293 out->convert_buffer != NULL) {
6294
6295 memcpy_by_audio_format(out->convert_buffer,
6296 out->hal_op_format,
6297 buffer,
6298 out->hal_ip_format,
6299 out->config.period_size * out->config.channels);
6300
6301 ret = pcm_write(out->pcm, out->convert_buffer,
6302 (out->config.period_size *
6303 out->config.channels *
6304 format_to_bitwidth_table[out->hal_op_format]));
6305 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05306306 /*
6307 * To avoid underrun in DSP when the application is not pumping
6308 * data at required rate, check for the no. of bytes and ignore
6309 * pcm_write if it is less than actual buffer size.
6310 * It is a work around to a change in compress VOIP driver.
6311 */
6312 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
6313 bytes < (out->config.period_size * out->config.channels *
6314 audio_bytes_per_sample(out->format))) {
6315 size_t voip_buf_size =
6316 out->config.period_size * out->config.channels *
6317 audio_bytes_per_sample(out->format);
6318 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
6319 __func__, bytes, voip_buf_size);
6320 usleep(((uint64_t)voip_buf_size - bytes) *
6321 1000000 / audio_stream_out_frame_size(stream) /
6322 out_get_sample_rate(&out->stream.common));
6323 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006324 } else {
6325 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
6326 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
6327 else
6328 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
6329 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306330 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006331
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006332 release_out_focus(out);
6333
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306334 if (ret < 0)
6335 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08006336 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05306337 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006338 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006339 }
6340
6341exit:
Zhou Songc9672822017-08-16 16:01:39 +08006342 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306343 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306344 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306345 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006346 pthread_mutex_unlock(&out->lock);
6347
6348 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006349 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08006350 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306351 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306352 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306353 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306354 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306355 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306356 out->standby = true;
6357 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306358 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006359 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
6360 /* prevent division-by-zero */
6361 uint32_t stream_size = audio_stream_out_frame_size(stream);
6362 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006363
Dieter Luecking5d57def2018-09-07 14:23:37 +02006364 if ((stream_size == 0) || (srate == 0)) {
6365 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
6366 ATRACE_END();
6367 return -EINVAL;
6368 }
6369 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
6370 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006371 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05306372 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006373 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006374 return ret;
6375 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006376 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07006377 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006378 return bytes;
6379}
6380
6381static int out_get_render_position(const struct audio_stream_out *stream,
6382 uint32_t *dsp_frames)
6383{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006384 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08006385
6386 if (dsp_frames == NULL)
6387 return -EINVAL;
6388
6389 *dsp_frames = 0;
6390 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08006391 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05306392
6393 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
6394 * this operation and adev_close_output_stream(where out gets reset).
6395 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05306396 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006397 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05306398 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006399 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05306400 return 0;
6401 }
6402
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006403 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05306404 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306405 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006406 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306407 if (ret < 0)
6408 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006409 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05306410 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006411 }
Naresh Tanniru80659832014-06-04 18:17:56 +05306412 if (-ENETRESET == ret) {
6413 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306414 out->card_status = CARD_STATUS_OFFLINE;
6415 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306416 } else if(ret < 0) {
6417 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306418 ret = -EINVAL;
6419 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05306420 /*
6421 * Handle corner case where compress session is closed during SSR
6422 * and timestamp is queried
6423 */
6424 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306425 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306426 } else if (out->prev_card_status_offline) {
6427 ALOGE("ERROR: previously sound card was offline,return error");
6428 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306429 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306430 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006431 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05306432 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306433 pthread_mutex_unlock(&out->lock);
6434 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08006435 } else if (audio_is_linear_pcm(out->format)) {
6436 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006437 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08006438 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006439 } else
6440 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006441}
6442
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006443static int out_add_audio_effect(const struct audio_stream *stream __unused,
6444 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006445{
6446 return 0;
6447}
6448
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006449static int out_remove_audio_effect(const struct audio_stream *stream __unused,
6450 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006451{
6452 return 0;
6453}
6454
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006455static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
6456 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006457{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05306458 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006459}
6460
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006461static int out_get_presentation_position(const struct audio_stream_out *stream,
6462 uint64_t *frames, struct timespec *timestamp)
6463{
6464 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05306465 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07006466 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006467
Ashish Jain5106d362016-05-11 19:23:33 +05306468 /* below piece of code is not guarded against any lock because audioFliner serializes
6469 * this operation and adev_close_output_stream( where out gets reset).
6470 */
6471 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05306472 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006473 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05306474 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
6475 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
6476 return 0;
6477 }
6478
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006479 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006480
Ashish Jain5106d362016-05-11 19:23:33 +05306481 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
6482 ret = compress_get_tstamp(out->compr, &dsp_frames,
6483 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08006484 // Adjustment accounts for A2dp encoder latency with offload usecases
6485 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006486 if (is_a2dp_out_device_type(&out->device_list)) {
yidongh0515e042017-07-06 15:00:34 +08006487 unsigned long offset =
6488 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
6489 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
6490 }
Ashish Jain5106d362016-05-11 19:23:33 +05306491 ALOGVV("%s rendered frames %ld sample_rate %d",
6492 __func__, dsp_frames, out->sample_rate);
6493 *frames = dsp_frames;
6494 if (ret < 0)
6495 ret = -errno;
6496 if (-ENETRESET == ret) {
6497 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306498 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05306499 ret = -EINVAL;
6500 } else
6501 ret = 0;
6502 /* this is the best we can do */
6503 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07006504 } else {
6505 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08006506 unsigned int avail;
6507 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
George Gao62ebc722019-07-29 16:29:44 -07006508 uint64_t signed_frames = 0;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006509 uint64_t frames_temp = 0;
George Gao62ebc722019-07-29 16:29:44 -07006510
Andy Hunga1f48fa2019-07-01 18:14:53 -07006511 if (out->kernel_buffer_size > avail) {
6512 frames_temp = out->last_fifo_frames_remaining = out->kernel_buffer_size - avail;
6513 } else {
6514 ALOGW("%s: avail:%u > kernel_buffer_size:%zu clamping!",
6515 __func__, avail, out->kernel_buffer_size);
6516 avail = out->kernel_buffer_size;
6517 frames_temp = out->last_fifo_frames_remaining = 0;
6518 }
6519 out->last_fifo_valid = true;
6520 out->last_fifo_time_ns = audio_utils_ns_from_timespec(timestamp);
6521
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006522 if (out->written >= frames_temp)
6523 signed_frames = out->written - frames_temp;
George Gao62ebc722019-07-29 16:29:44 -07006524
Andy Hunga1f48fa2019-07-01 18:14:53 -07006525 ALOGVV("%s: frames:%lld avail:%u kernel_buffer_size:%zu",
6526 __func__, (long long)signed_frames, avail, out->kernel_buffer_size);
6527
Weiyin Jiangd4633762018-03-16 12:05:03 +08006528 // This adjustment accounts for buffering after app processor.
6529 // It is based on estimated DSP latency per use case, rather than exact.
George Gao9ba8a142020-07-23 14:30:03 -07006530 frames_temp = platform_render_latency(out) *
Robert Lee58215542019-07-15 20:55:12 +08006531 out->sample_rate / 1000000LL;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006532 if (signed_frames >= frames_temp)
6533 signed_frames -= frames_temp;
Aniket Kumar Lataff613152017-07-18 18:19:21 -07006534
Weiyin Jiangd4633762018-03-16 12:05:03 +08006535 // Adjustment accounts for A2dp encoder latency with non offload usecases
6536 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006537 if (is_a2dp_out_device_type(&out->device_list)) {
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006538 frames_temp = audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000;
6539 if (signed_frames >= frames_temp)
6540 signed_frames -= frames_temp;
Weiyin Jiangd4633762018-03-16 12:05:03 +08006541 }
6542
6543 // It would be unusual for this value to be negative, but check just in case ...
George Gao62ebc722019-07-29 16:29:44 -07006544 *frames = signed_frames;
6545 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006546 }
Eric Laurenta7a33042019-07-10 16:20:22 -07006547 } else if (out->card_status == CARD_STATUS_OFFLINE ||
6548 // audioflinger still needs position updates when A2DP is suspended
Jasmine Cha5c2517f2019-09-09 11:07:28 +08006549 (is_a2dp_out_device_type(&out->device_list) && audio_extn_a2dp_source_is_suspended())) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306550 *frames = out->written;
6551 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306552 if (is_offload_usecase(out->usecase))
6553 ret = -EINVAL;
6554 else
6555 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006556 }
6557 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006558 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006559 return ret;
6560}
6561
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006562static int out_set_callback(struct audio_stream_out *stream,
6563 stream_callback_t callback, void *cookie)
6564{
6565 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006566 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006567
6568 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006569 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006570 out->client_callback = callback;
6571 out->client_cookie = cookie;
6572 if (out->adsp_hdlr_stream_handle) {
6573 ret = audio_extn_adsp_hdlr_stream_set_callback(
6574 out->adsp_hdlr_stream_handle,
6575 callback,
6576 cookie);
6577 if (ret)
6578 ALOGW("%s:adsp hdlr callback registration failed %d",
6579 __func__, ret);
6580 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006581 pthread_mutex_unlock(&out->lock);
6582 return 0;
6583}
6584
6585static int out_pause(struct audio_stream_out* stream)
6586{
6587 struct stream_out *out = (struct stream_out *)stream;
6588 int status = -ENOSYS;
6589 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006590 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006591 ALOGD("copl(%p):pause compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306592 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006593 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006594 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006595 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306596 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05306597 status = compress_pause(out->compr);
6598
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006599 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006600
Mingming Yin21854652016-04-13 11:54:02 -07006601 if (audio_extn_passthru_is_active()) {
6602 ALOGV("offload use case, pause passthru");
6603 audio_extn_passthru_on_pause(out);
6604 }
6605
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306606 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006607 audio_extn_dts_notify_playback_state(out->usecase, 0,
6608 out->sample_rate, popcount(out->channel_mask),
6609 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006610 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08006611 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006612 pthread_mutex_unlock(&out->lock);
6613 }
6614 return status;
6615}
6616
6617static int out_resume(struct audio_stream_out* stream)
6618{
6619 struct stream_out *out = (struct stream_out *)stream;
6620 int status = -ENOSYS;
6621 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006622 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006623 ALOGD("copl(%p):resume compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306624 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006625 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006626 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006627 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306628 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306629 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07006630 }
6631 if (!status) {
6632 out->offload_state = OFFLOAD_STATE_PLAYING;
6633 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306634 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006635 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6636 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006637 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08006638 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006639 pthread_mutex_unlock(&out->lock);
6640 }
6641 return status;
6642}
6643
6644static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
6645{
6646 struct stream_out *out = (struct stream_out *)stream;
6647 int status = -ENOSYS;
6648 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006649 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006650 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006651 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
6652 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
6653 else
6654 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
6655 pthread_mutex_unlock(&out->lock);
6656 }
6657 return status;
6658}
6659
6660static int out_flush(struct audio_stream_out* stream)
6661{
6662 struct stream_out *out = (struct stream_out *)stream;
6663 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006664 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006665 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006666 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006667 pthread_mutex_lock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006668 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
Gautam Manam14c198b2020-12-24 14:08:04 +05306669 pthread_mutex_unlock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006670 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006671 } else {
6672 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
Gautam Manam14c198b2020-12-24 14:08:04 +05306673 pthread_mutex_unlock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006674 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08006675 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006676 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006677 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006678 return 0;
6679 }
6680 return -ENOSYS;
6681}
6682
Haynes Mathew George16081042017-05-31 17:16:49 -07006683static int out_stop(const struct audio_stream_out* stream)
6684{
6685 struct stream_out *out = (struct stream_out *)stream;
6686 struct audio_device *adev = out->dev;
6687 int ret = -ENOSYS;
6688
6689 ALOGV("%s", __func__);
6690 pthread_mutex_lock(&adev->lock);
6691 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6692 out->playback_started && out->pcm != NULL) {
6693 pcm_stop(out->pcm);
6694 ret = stop_output_stream(out);
6695 out->playback_started = false;
6696 }
6697 pthread_mutex_unlock(&adev->lock);
6698 return ret;
6699}
6700
6701static int out_start(const struct audio_stream_out* stream)
6702{
6703 struct stream_out *out = (struct stream_out *)stream;
6704 struct audio_device *adev = out->dev;
6705 int ret = -ENOSYS;
6706
6707 ALOGV("%s", __func__);
6708 pthread_mutex_lock(&adev->lock);
6709 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6710 !out->playback_started && out->pcm != NULL) {
6711 ret = start_output_stream(out);
6712 if (ret == 0) {
6713 out->playback_started = true;
6714 }
6715 }
6716 pthread_mutex_unlock(&adev->lock);
6717 return ret;
6718}
6719
6720/*
6721 * Modify config->period_count based on min_size_frames
6722 */
6723static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
6724{
6725 int periodCountRequested = (min_size_frames + config->period_size - 1)
6726 / config->period_size;
6727 int periodCount = MMAP_PERIOD_COUNT_MIN;
6728
6729 ALOGV("%s original config.period_size = %d config.period_count = %d",
6730 __func__, config->period_size, config->period_count);
6731
6732 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
6733 periodCount *= 2;
6734 }
6735 config->period_count = periodCount;
6736
6737 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
6738}
6739
Phil Burkfe17efd2019-03-25 10:23:35 -07006740// Read offset for the positional timestamp from a persistent vendor property.
6741// This is to workaround apparent inaccuracies in the timing information that
6742// is used by the AAudio timing model. The inaccuracies can cause glitches.
6743static int64_t get_mmap_out_time_offset() {
6744 const int32_t kDefaultOffsetMicros = 0;
6745 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006746 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07006747 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
6748 return mmap_time_offset_micros * (int64_t)1000;
6749}
6750
Haynes Mathew George16081042017-05-31 17:16:49 -07006751static int out_create_mmap_buffer(const struct audio_stream_out *stream,
6752 int32_t min_size_frames,
6753 struct audio_mmap_buffer_info *info)
6754{
6755 struct stream_out *out = (struct stream_out *)stream;
6756 struct audio_device *adev = out->dev;
6757 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07006758 unsigned int offset1 = 0;
6759 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006760 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006761 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006762 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07006763
Arun Mirpuri5d170872019-03-26 13:21:31 -07006764 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306765 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07006766 pthread_mutex_lock(&adev->lock);
6767
Sharad Sanglec6f32552018-05-04 16:15:38 +05306768 if (CARD_STATUS_OFFLINE == out->card_status ||
6769 CARD_STATUS_OFFLINE == adev->card_status) {
6770 ALOGW("out->card_status or adev->card_status offline, try again");
6771 ret = -EIO;
6772 goto exit;
6773 }
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306774 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07006775 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
6776 ret = -EINVAL;
6777 goto exit;
6778 }
6779 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
6780 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
6781 ret = -ENOSYS;
6782 goto exit;
6783 }
6784 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
6785 if (out->pcm_device_id < 0) {
6786 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6787 __func__, out->pcm_device_id, out->usecase);
6788 ret = -EINVAL;
6789 goto exit;
6790 }
6791
6792 adjust_mmap_period_count(&out->config, min_size_frames);
6793
Arun Mirpuri5d170872019-03-26 13:21:31 -07006794 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006795 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
6796 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
6797 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306798 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306799 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6800 out->card_status = CARD_STATUS_OFFLINE;
6801 adev->card_status = CARD_STATUS_OFFLINE;
6802 ret = -EIO;
6803 goto exit;
6804 }
6805
Haynes Mathew George16081042017-05-31 17:16:49 -07006806 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
6807 step = "open";
6808 ret = -ENODEV;
6809 goto exit;
6810 }
6811 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
6812 if (ret < 0) {
6813 step = "begin";
6814 goto exit;
6815 }
juyuchen626833d2019-06-04 16:48:02 +08006816
6817 info->flags = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006818 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07006819 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07006820 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006821 ret = platform_get_mmap_data_fd(adev->platform,
6822 out->pcm_device_id, 0 /*playback*/,
6823 &info->shared_memory_fd,
6824 &mmap_size);
6825 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07006826 // Fall back to non exclusive mode
6827 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
6828 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07006829 out->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
6830 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, out->mmap_shared_memory_fd);
6831
Arun Mirpuri5d170872019-03-26 13:21:31 -07006832 if (mmap_size < buffer_size) {
6833 step = "mmap";
6834 goto exit;
6835 }
juyuchen626833d2019-06-04 16:48:02 +08006836 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006837 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006838 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006839 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07006840
6841 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
6842 if (ret < 0) {
6843 step = "commit";
6844 goto exit;
6845 }
6846
Phil Burkfe17efd2019-03-25 10:23:35 -07006847 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
6848
Haynes Mathew George16081042017-05-31 17:16:49 -07006849 out->standby = false;
6850 ret = 0;
6851
Arun Mirpuri5d170872019-03-26 13:21:31 -07006852 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006853 __func__, info->shared_memory_address, info->buffer_size_frames);
6854
6855exit:
6856 if (ret != 0) {
6857 if (out->pcm == NULL) {
6858 ALOGE("%s: %s - %d", __func__, step, ret);
6859 } else {
6860 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
6861 pcm_close(out->pcm);
6862 out->pcm = NULL;
6863 }
6864 }
6865 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306866 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07006867 return ret;
6868}
6869
6870static int out_get_mmap_position(const struct audio_stream_out *stream,
6871 struct audio_mmap_position *position)
6872{
6873 struct stream_out *out = (struct stream_out *)stream;
6874 ALOGVV("%s", __func__);
6875 if (position == NULL) {
6876 return -EINVAL;
6877 }
6878 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08006879 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006880 return -ENOSYS;
6881 }
6882 if (out->pcm == NULL) {
6883 return -ENOSYS;
6884 }
6885
6886 struct timespec ts = { 0, 0 };
6887 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
6888 if (ret < 0) {
6889 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
6890 return ret;
6891 }
Phil Burkfe17efd2019-03-25 10:23:35 -07006892 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
6893 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07006894 return 0;
6895}
6896
6897
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006898/** audio_stream_in implementation **/
6899static uint32_t in_get_sample_rate(const struct audio_stream *stream)
6900{
6901 struct stream_in *in = (struct stream_in *)stream;
6902
6903 return in->config.rate;
6904}
6905
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006906static int in_set_sample_rate(struct audio_stream *stream __unused,
6907 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006908{
6909 return -ENOSYS;
6910}
6911
6912static size_t in_get_buffer_size(const struct audio_stream *stream)
6913{
6914 struct stream_in *in = (struct stream_in *)stream;
6915
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006916 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
6917 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07006918 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
6919 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306920 else if(audio_extn_cin_attached_usecase(in))
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306921 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006922
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006923 return in->config.period_size * in->af_period_multiplier *
6924 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006925}
6926
6927static uint32_t in_get_channels(const struct audio_stream *stream)
6928{
6929 struct stream_in *in = (struct stream_in *)stream;
6930
6931 return in->channel_mask;
6932}
6933
6934static audio_format_t in_get_format(const struct audio_stream *stream)
6935{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006936 struct stream_in *in = (struct stream_in *)stream;
6937
6938 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006939}
6940
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006941static int in_set_format(struct audio_stream *stream __unused,
6942 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006943{
6944 return -ENOSYS;
6945}
6946
6947static int in_standby(struct audio_stream *stream)
6948{
6949 struct stream_in *in = (struct stream_in *)stream;
6950 struct audio_device *adev = in->dev;
6951 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306952 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
6953 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006954 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306955
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006956 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006957 if (!in->standby && in->is_st_session) {
6958 ALOGD("%s: sound trigger pcm stop lab", __func__);
6959 audio_extn_sound_trigger_stop_lab(in);
George Gao3018ede2019-10-23 13:23:00 -07006960 if (adev->num_va_sessions > 0)
6961 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006962 in->standby = 1;
6963 }
6964
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006965 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006966 if (adev->adm_deregister_stream)
6967 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
6968
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08006969 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006970 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08006971 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08006972 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08006973 voice_extn_compress_voip_close_input_stream(stream);
6974 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07006975 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6976 do_stop = in->capture_started;
6977 in->capture_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07006978 if (in->mmap_shared_memory_fd >= 0) {
6979 ALOGV("%s: closing mmap_shared_memory_fd = %d",
6980 __func__, in->mmap_shared_memory_fd);
6981 close(in->mmap_shared_memory_fd);
6982 in->mmap_shared_memory_fd = -1;
6983 }
Zhou Songa8895042016-07-05 17:54:22 +08006984 } else {
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306985 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05306986 audio_extn_cin_close_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08006987 }
6988
Arun Mirpuri5d170872019-03-26 13:21:31 -07006989 if (in->pcm) {
6990 ATRACE_BEGIN("pcm_in_close");
6991 pcm_close(in->pcm);
6992 ATRACE_END();
6993 in->pcm = NULL;
6994 }
6995
Carter Hsu2e429db2019-05-14 18:50:52 +08006996 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08006997 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006998
George Gao3018ede2019-10-23 13:23:00 -07006999 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
7000 if (adev->num_va_sessions > 0)
7001 adev->num_va_sessions--;
7002 }
Quinn Malef6050362019-01-30 15:55:40 -08007003
Eric Laurent150dbfe2013-02-27 14:31:02 -08007004 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007005 }
7006 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07007007 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007008 return status;
7009}
7010
Aalique Grahame22e49102018-12-18 14:23:57 -08007011static int in_dump(const struct audio_stream *stream,
7012 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007013{
Aalique Grahame22e49102018-12-18 14:23:57 -08007014 struct stream_in *in = (struct stream_in *)stream;
7015
7016 // We try to get the lock for consistency,
7017 // but it isn't necessary for these variables.
7018 // If we're not in standby, we may be blocked on a read.
7019 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
7020 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
7021 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
7022 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
Dechen Chai22768452021-07-30 09:29:16 +05307023#ifndef LINUX_ENABLED
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007024 char buffer[256]; // for statistics formatting
7025 if (in->start_latency_ms.n > 0) {
7026 simple_stats_to_string(&in->start_latency_ms, buffer, sizeof(buffer));
7027 dprintf(fd, " Start latency ms: %s\n", buffer);
7028 }
Dechen Chai22768452021-07-30 09:29:16 +05307029#endif
Aalique Grahame22e49102018-12-18 14:23:57 -08007030 if (locked) {
7031 pthread_mutex_unlock(&in->lock);
7032 }
Dechen Chai22768452021-07-30 09:29:16 +05307033#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -08007034 // dump error info
7035 (void)error_log_dump(
7036 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Dechen Chai22768452021-07-30 09:29:16 +05307037#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007038 return 0;
7039}
7040
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307041static void in_snd_mon_cb(void * stream, struct str_parms * parms)
7042{
7043 if (!stream || !parms)
7044 return;
7045
7046 struct stream_in *in = (struct stream_in *)stream;
7047 struct audio_device *adev = in->dev;
7048
7049 card_status_t status;
7050 int card;
7051 if (parse_snd_card_status(parms, &card, &status) < 0)
7052 return;
7053
7054 pthread_mutex_lock(&adev->lock);
7055 bool valid_cb = (card == adev->snd_card);
7056 pthread_mutex_unlock(&adev->lock);
7057
7058 if (!valid_cb)
7059 return;
7060
7061 lock_input_stream(in);
7062 if (in->card_status != status)
7063 in->card_status = status;
7064 pthread_mutex_unlock(&in->lock);
7065
7066 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
7067 use_case_table[in->usecase],
7068 status == CARD_STATUS_OFFLINE ? "offline" : "online");
7069
7070 // a better solution would be to report error back to AF and let
7071 // it put the stream to standby
7072 if (status == CARD_STATUS_OFFLINE)
7073 in_standby(&in->stream.common);
7074
7075 return;
7076}
7077
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007078int route_input_stream(struct stream_in *in,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007079 struct listnode *devices,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007080 audio_source_t source)
7081{
7082 struct audio_device *adev = in->dev;
7083 int ret = 0;
7084
7085 lock_input_stream(in);
7086 pthread_mutex_lock(&adev->lock);
7087
7088 /* no audio source uses val == 0 */
7089 if ((in->source != source) && (source != AUDIO_SOURCE_DEFAULT)) {
7090 in->source = source;
7091 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
7092 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
7093 (voice_extn_compress_voip_is_format_supported(in->format)) &&
7094 (in->config.rate == 8000 || in->config.rate == 16000 ||
7095 in->config.rate == 32000 || in->config.rate == 48000 ) &&
7096 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
7097 ret = voice_extn_compress_voip_open_input_stream(in);
7098 if (ret != 0) {
7099 ALOGE("%s: Compress voip input cannot be opened, error:%d",
7100 __func__, ret);
7101 }
7102 }
7103 }
7104
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007105 if (!compare_devices(&in->device_list, devices) && !list_empty(devices) &&
7106 is_audio_in_device_type(devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007107 // Workaround: If routing to an non existing usb device, fail gracefully
7108 // The routing request will otherwise block during 10 second
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007109 struct str_parms *usb_addr =
7110 str_parms_create_str(get_usb_device_address(devices));
7111 if (is_usb_in_device_type(devices) && usb_addr &&
Weiyin Jiangabedea32020-12-09 12:49:19 +08007112 !audio_extn_usb_connected(NULL)) {
7113 ALOGW("%s: ignoring rerouting to non existing USB", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007114 ret = -ENOSYS;
7115 } else {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007116 /* If recording is in progress, change the tx device to new device */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007117 assign_devices(&in->device_list, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007118 if (!in->standby && !in->is_st_session) {
7119 ALOGV("update input routing change");
7120 // inform adm before actual routing to prevent glitches.
7121 if (adev->adm_on_routing_change) {
7122 adev->adm_on_routing_change(adev->adm_data,
7123 in->capture_handle);
7124 ret = select_devices(adev, in->usecase);
7125 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7126 adev->adm_routing_changed = true;
7127 }
7128 }
7129 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007130 if (usb_addr)
7131 str_parms_destroy(usb_addr);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007132 }
7133 pthread_mutex_unlock(&adev->lock);
7134 pthread_mutex_unlock(&in->lock);
7135
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07007136 ALOGV("%s: exit: status(%d)", __func__, ret);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007137 return ret;
7138}
7139
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007140static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
7141{
7142 struct stream_in *in = (struct stream_in *)stream;
7143 struct audio_device *adev = in->dev;
7144 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007145 char value[32];
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307146 int err = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007147
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307148 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007149 parms = str_parms_create_str(kvpairs);
7150
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307151 if (!parms)
7152 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007153 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08007154 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007155
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307156 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
7157 if (err >= 0) {
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307158 strlcpy(in->profile, value, sizeof(in->profile));
7159 ALOGV("updating stream profile with value '%s'", in->profile);
7160 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
7161 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007162 &in->device_list, in->flags, in->format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307163 in->sample_rate, in->bit_width,
7164 in->profile, &in->app_type_cfg);
7165 }
7166
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007167 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08007168 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007169
7170 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307171error:
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307172 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007173}
7174
7175static char* in_get_parameters(const struct audio_stream *stream,
7176 const char *keys)
7177{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007178 struct stream_in *in = (struct stream_in *)stream;
7179 struct str_parms *query = str_parms_create_str(keys);
7180 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007181 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007182
7183 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08007184 if (reply) {
7185 str_parms_destroy(reply);
7186 }
7187 if (query) {
7188 str_parms_destroy(query);
7189 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007190 ALOGE("in_get_parameters: failed to create query or reply");
7191 return NULL;
7192 }
7193
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007194 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007195
7196 voice_extn_in_get_parameters(in, query, reply);
7197
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007198 stream_get_parameter_channels(query, reply,
7199 &in->supported_channel_masks[0]);
7200 stream_get_parameter_formats(query, reply,
7201 &in->supported_formats[0]);
7202 stream_get_parameter_rates(query, reply,
7203 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007204 str = str_parms_to_str(reply);
7205 str_parms_destroy(query);
7206 str_parms_destroy(reply);
7207
7208 ALOGV("%s: exit: returns - %s", __func__, str);
7209 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007210}
7211
Aalique Grahame22e49102018-12-18 14:23:57 -08007212static int in_set_gain(struct audio_stream_in *stream,
7213 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007214{
Aalique Grahame22e49102018-12-18 14:23:57 -08007215 struct stream_in *in = (struct stream_in *)stream;
7216 char mixer_ctl_name[128];
7217 struct mixer_ctl *ctl;
7218 int ctl_value;
7219
7220 ALOGV("%s: gain %f", __func__, gain);
7221
7222 if (stream == NULL)
7223 return -EINVAL;
7224
7225 /* in_set_gain() only used to silence MMAP capture for now */
7226 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
7227 return -ENOSYS;
7228
7229 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
7230
7231 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
7232 if (!ctl) {
7233 ALOGW("%s: Could not get ctl for mixer cmd - %s",
7234 __func__, mixer_ctl_name);
7235 return -ENOSYS;
7236 }
7237
7238 if (gain < RECORD_GAIN_MIN)
7239 gain = RECORD_GAIN_MIN;
7240 else if (gain > RECORD_GAIN_MAX)
7241 gain = RECORD_GAIN_MAX;
7242 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
7243
7244 mixer_ctl_set_value(ctl, 0, ctl_value);
7245
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007246 return 0;
7247}
7248
7249static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
7250 size_t bytes)
7251{
7252 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05307253
7254 if (in == NULL) {
7255 ALOGE("%s: stream_in ptr is NULL", __func__);
7256 return -EINVAL;
7257 }
7258
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007259 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05307260 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307261 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007262
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007263 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05307264
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007265 if (in->is_st_session) {
7266 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
7267 /* Read from sound trigger HAL */
7268 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08007269 if (in->standby) {
George Gao3018ede2019-10-23 13:23:00 -07007270 if (adev->num_va_sessions < UINT_MAX)
7271 adev->num_va_sessions++;
Quinn Malef6050362019-01-30 15:55:40 -08007272 in->standby = 0;
7273 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007274 pthread_mutex_unlock(&in->lock);
7275 return bytes;
7276 }
7277
Haynes Mathew George16081042017-05-31 17:16:49 -07007278 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
7279 ret = -ENOSYS;
7280 goto exit;
7281 }
7282
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007283 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
7284 !in->standby && adev->adm_routing_changed) {
7285 ret = -ENOSYS;
7286 goto exit;
7287 }
7288
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007289 if (in->standby) {
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007290 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
7291
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007292 pthread_mutex_lock(&adev->lock);
7293 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
7294 ret = voice_extn_compress_voip_start_input_stream(in);
7295 else
7296 ret = start_input_stream(in);
George Gao3018ede2019-10-23 13:23:00 -07007297 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
7298 if (adev->num_va_sessions < UINT_MAX)
7299 adev->num_va_sessions++;
7300 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007301 pthread_mutex_unlock(&adev->lock);
7302 if (ret != 0) {
7303 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007304 }
7305 in->standby = 0;
Dechen Chai22768452021-07-30 09:29:16 +05307306#ifndef LINUX_ENABLED
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007307 // log startup time in ms.
7308 simple_stats_log(
7309 &in->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Dechen Chai22768452021-07-30 09:29:16 +05307310#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007311 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007312
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05307313 /* Avoid read if capture_stopped is set */
7314 if (android_atomic_acquire_load(&(in->capture_stopped)) > 0) {
7315 ALOGD("%s: force stopped catpure session, ignoring read request", __func__);
7316 ret = -EINVAL;
7317 goto exit;
7318 }
7319
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007320 // what's the duration requested by the client?
7321 long ns = 0;
7322
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307323 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007324 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
7325 in->config.rate;
7326
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007327 ret = request_in_focus(in, ns);
7328 if (ret != 0)
7329 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007330 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007331
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307332 if (audio_extn_cin_attached_usecase(in)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307333 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
7334 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307335 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007336 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307337 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07007338 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007339 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007340 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07007341 } else if (audio_extn_ffv_get_stream() == in) {
7342 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307343 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007344 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307345 /* data from DSP comes in 24_8 format, convert it to 8_24 */
7346 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
7347 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
7348 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307349 ret = -EINVAL;
7350 goto exit;
7351 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307352 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307353 ret = -errno;
7354 }
7355 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307356 /* bytes read is always set to bytes for non compress usecases */
7357 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007358 }
7359
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007360 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007361
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007362 /*
Quinn Malef6050362019-01-30 15:55:40 -08007363 * Instead of writing zeroes here, we could trust the hardware to always
7364 * provide zeroes when muted. This is also muted with voice recognition
7365 * usecases so that other clients do not have access to voice recognition
7366 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007367 */
Quinn Malef6050362019-01-30 15:55:40 -08007368 if ((ret == 0 && voice_get_mic_mute(adev) &&
7369 !voice_is_in_call_rec_stream(in) &&
Zhou Song62ea0282020-03-22 19:53:01 +08007370 (in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY &&
7371 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY2)) ||
Quinn Malef6050362019-01-30 15:55:40 -08007372 (adev->num_va_sessions &&
7373 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
7374 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
7375 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007376 memset(buffer, 0, bytes);
7377
7378exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307379 frame_size = audio_stream_in_frame_size(stream);
7380 if (frame_size > 0)
7381 in->frames_read += bytes_read/frame_size;
7382
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007383 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307384 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007385 pthread_mutex_unlock(&in->lock);
7386
7387 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307388 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307389 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307390 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307391 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307392 in->standby = true;
7393 }
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307394 if (!audio_extn_cin_attached_usecase(in)) {
Sharad Sangled17c9122017-03-20 15:58:52 +05307395 bytes_read = bytes;
7396 memset(buffer, 0, bytes);
7397 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007398 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007399 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7400 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007401 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05307402 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05307403 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007404 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307405 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007406}
7407
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007408static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007409{
7410 return 0;
7411}
7412
Aalique Grahame22e49102018-12-18 14:23:57 -08007413static int in_get_capture_position(const struct audio_stream_in *stream,
7414 int64_t *frames, int64_t *time)
7415{
7416 if (stream == NULL || frames == NULL || time == NULL) {
7417 return -EINVAL;
7418 }
7419 struct stream_in *in = (struct stream_in *)stream;
7420 int ret = -ENOSYS;
7421
7422 lock_input_stream(in);
7423 // note: ST sessions do not close the alsa pcm driver synchronously
7424 // on standby. Therefore, we may return an error even though the
7425 // pcm stream is still opened.
7426 if (in->standby) {
7427 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
7428 "%s stream in standby but pcm not NULL for non ST session", __func__);
7429 goto exit;
7430 }
7431 if (in->pcm) {
7432 struct timespec timestamp;
7433 unsigned int avail;
7434 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
7435 *frames = in->frames_read + avail;
Robert Lee58215542019-07-15 20:55:12 +08007436 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec
George Gao9ba8a142020-07-23 14:30:03 -07007437 - platform_capture_latency(in) * 1000LL;
Kakanaboina Ramanjaneyulu8cedb092021-03-15 15:55:29 +05307438 //Adjustment accounts for A2dp decoder latency for recording usecase
7439 // Note: decoder latency is returned in ms, while platform_capture_latency in ns.
7440 if (is_a2dp_in_device_type(&in->device_list))
7441 *time -= audio_extn_a2dp_get_decoder_latency() * 1000000LL;
Aalique Grahame22e49102018-12-18 14:23:57 -08007442 ret = 0;
7443 }
7444 }
7445exit:
7446 pthread_mutex_unlock(&in->lock);
7447 return ret;
7448}
7449
Carter Hsu2e429db2019-05-14 18:50:52 +08007450static int in_update_effect_list(bool add, effect_handle_t effect,
7451 struct listnode *head)
7452{
7453 struct listnode *node;
7454 struct in_effect_list *elist = NULL;
7455 struct in_effect_list *target = NULL;
7456 int ret = 0;
7457
7458 if (!head)
7459 return ret;
7460
7461 list_for_each(node, head) {
7462 elist = node_to_item(node, struct in_effect_list, list);
7463 if (elist->handle == effect) {
7464 target = elist;
7465 break;
7466 }
7467 }
7468
7469 if (add) {
7470 if (target) {
7471 ALOGD("effect %p already exist", effect);
7472 return ret;
7473 }
7474
7475 target = (struct in_effect_list *)
7476 calloc(1, sizeof(struct in_effect_list));
7477
7478 if (!target) {
7479 ALOGE("%s:fail to allocate memory", __func__);
7480 return -ENOMEM;
7481 }
7482
7483 target->handle = effect;
7484 list_add_tail(head, &target->list);
7485 } else {
7486 if (target) {
7487 list_remove(&target->list);
7488 free(target);
7489 }
7490 }
7491
7492 return ret;
7493}
7494
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007495static int add_remove_audio_effect(const struct audio_stream *stream,
7496 effect_handle_t effect,
7497 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007498{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007499 struct stream_in *in = (struct stream_in *)stream;
7500 int status = 0;
7501 effect_descriptor_t desc;
7502
7503 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007504 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
7505
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007506 if (status != 0)
7507 return status;
7508
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007509 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007510 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08007511 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08007512 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
7513 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007514 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08007515
7516 in_update_effect_list(enable, effect, &in->aec_list);
7517 enable = !list_empty(&in->aec_list);
7518 if (enable == in->enable_aec)
7519 goto exit;
7520
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007521 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007522 ALOGD("AEC enable %d", enable);
7523
Aalique Grahame22e49102018-12-18 14:23:57 -08007524 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7525 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
7526 in->dev->enable_voicerx = enable;
7527 struct audio_usecase *usecase;
7528 struct listnode *node;
7529 list_for_each(node, &in->dev->usecase_list) {
7530 usecase = node_to_item(node, struct audio_usecase, list);
7531 if (usecase->type == PCM_PLAYBACK)
7532 select_devices(in->dev, usecase->id);
7533 }
7534 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007535 if (!in->standby) {
7536 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
7537 select_devices(in->dev, in->usecase);
7538 }
7539
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007540 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007541 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
7542
7543 in_update_effect_list(enable, effect, &in->ns_list);
7544 enable = !list_empty(&in->ns_list);
7545 if (enable == in->enable_ns)
7546 goto exit;
7547
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007548 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007549 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007550 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08007551 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Ramu Gottipatifa5be522021-12-28 19:18:21 +05307552 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
kunleizd96526c2018-04-09 11:12:32 +08007553 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007554 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
7555 select_devices(in->dev, in->usecase);
7556 } else
7557 select_devices(in->dev, in->usecase);
7558 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007559 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007560exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007561 pthread_mutex_unlock(&in->dev->lock);
7562 pthread_mutex_unlock(&in->lock);
7563
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007564 return 0;
7565}
7566
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007567static int in_add_audio_effect(const struct audio_stream *stream,
7568 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007569{
Eric Laurent994a6932013-07-17 11:51:42 -07007570 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007571 return add_remove_audio_effect(stream, effect, true);
7572}
7573
7574static int in_remove_audio_effect(const struct audio_stream *stream,
7575 effect_handle_t effect)
7576{
Eric Laurent994a6932013-07-17 11:51:42 -07007577 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007578 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007579}
7580
Haynes Mathew George16081042017-05-31 17:16:49 -07007581static int in_stop(const struct audio_stream_in* stream)
7582{
7583 struct stream_in *in = (struct stream_in *)stream;
7584 struct audio_device *adev = in->dev;
7585
7586 int ret = -ENOSYS;
7587 ALOGV("%s", __func__);
7588 pthread_mutex_lock(&adev->lock);
7589 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7590 in->capture_started && in->pcm != NULL) {
7591 pcm_stop(in->pcm);
7592 ret = stop_input_stream(in);
7593 in->capture_started = false;
7594 }
7595 pthread_mutex_unlock(&adev->lock);
7596 return ret;
7597}
7598
7599static int in_start(const struct audio_stream_in* stream)
7600{
7601 struct stream_in *in = (struct stream_in *)stream;
7602 struct audio_device *adev = in->dev;
7603 int ret = -ENOSYS;
7604
7605 ALOGV("%s in %p", __func__, in);
7606 pthread_mutex_lock(&adev->lock);
7607 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7608 !in->capture_started && in->pcm != NULL) {
7609 if (!in->capture_started) {
7610 ret = start_input_stream(in);
7611 if (ret == 0) {
7612 in->capture_started = true;
7613 }
7614 }
7615 }
7616 pthread_mutex_unlock(&adev->lock);
7617 return ret;
7618}
7619
Phil Burke0a86d12019-02-16 22:28:11 -08007620// Read offset for the positional timestamp from a persistent vendor property.
7621// This is to workaround apparent inaccuracies in the timing information that
7622// is used by the AAudio timing model. The inaccuracies can cause glitches.
7623static int64_t in_get_mmap_time_offset() {
7624 const int32_t kDefaultOffsetMicros = 0;
7625 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08007626 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08007627 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
7628 return mmap_time_offset_micros * (int64_t)1000;
7629}
7630
Haynes Mathew George16081042017-05-31 17:16:49 -07007631static int in_create_mmap_buffer(const struct audio_stream_in *stream,
7632 int32_t min_size_frames,
7633 struct audio_mmap_buffer_info *info)
7634{
7635 struct stream_in *in = (struct stream_in *)stream;
7636 struct audio_device *adev = in->dev;
7637 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07007638 unsigned int offset1 = 0;
7639 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007640 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07007641 uint32_t mmap_size = 0;
7642 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007643
7644 pthread_mutex_lock(&adev->lock);
7645 ALOGV("%s in %p", __func__, in);
7646
Sharad Sanglec6f32552018-05-04 16:15:38 +05307647 if (CARD_STATUS_OFFLINE == in->card_status||
7648 CARD_STATUS_OFFLINE == adev->card_status) {
7649 ALOGW("in->card_status or adev->card_status offline, try again");
7650 ret = -EIO;
7651 goto exit;
7652 }
7653
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307654 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07007655 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
7656 ret = -EINVAL;
7657 goto exit;
7658 }
7659 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
7660 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
7661 ALOGV("%s in %p", __func__, in);
7662 ret = -ENOSYS;
7663 goto exit;
7664 }
7665 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
7666 if (in->pcm_device_id < 0) {
7667 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
7668 __func__, in->pcm_device_id, in->usecase);
7669 ret = -EINVAL;
7670 goto exit;
7671 }
7672
7673 adjust_mmap_period_count(&in->config, min_size_frames);
7674
7675 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
7676 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
7677 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
7678 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307679 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307680 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7681 in->card_status = CARD_STATUS_OFFLINE;
7682 adev->card_status = CARD_STATUS_OFFLINE;
7683 ret = -EIO;
7684 goto exit;
7685 }
7686
Haynes Mathew George16081042017-05-31 17:16:49 -07007687 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
7688 step = "open";
7689 ret = -ENODEV;
7690 goto exit;
7691 }
7692
7693 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
7694 if (ret < 0) {
7695 step = "begin";
7696 goto exit;
7697 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007698
juyuchen626833d2019-06-04 16:48:02 +08007699 info->flags = 0;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007700 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
7701 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
7702 info->burst_size_frames = in->config.period_size;
7703 ret = platform_get_mmap_data_fd(adev->platform,
7704 in->pcm_device_id, 1 /*capture*/,
7705 &info->shared_memory_fd,
7706 &mmap_size);
7707 if (ret < 0) {
7708 // Fall back to non exclusive mode
7709 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
7710 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07007711 in->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
7712 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, in->mmap_shared_memory_fd);
7713
Arun Mirpuri5d170872019-03-26 13:21:31 -07007714 if (mmap_size < buffer_size) {
7715 step = "mmap";
7716 goto exit;
7717 }
juyuchen626833d2019-06-04 16:48:02 +08007718 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007719 }
7720
7721 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07007722
7723 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
7724 if (ret < 0) {
7725 step = "commit";
7726 goto exit;
7727 }
7728
Phil Burke0a86d12019-02-16 22:28:11 -08007729 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
7730
Haynes Mathew George16081042017-05-31 17:16:49 -07007731 in->standby = false;
7732 ret = 0;
7733
7734 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
7735 __func__, info->shared_memory_address, info->buffer_size_frames);
7736
7737exit:
7738 if (ret != 0) {
7739 if (in->pcm == NULL) {
7740 ALOGE("%s: %s - %d", __func__, step, ret);
7741 } else {
7742 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
7743 pcm_close(in->pcm);
7744 in->pcm = NULL;
7745 }
7746 }
7747 pthread_mutex_unlock(&adev->lock);
7748 return ret;
7749}
7750
7751static int in_get_mmap_position(const struct audio_stream_in *stream,
7752 struct audio_mmap_position *position)
7753{
7754 struct stream_in *in = (struct stream_in *)stream;
7755 ALOGVV("%s", __func__);
7756 if (position == NULL) {
7757 return -EINVAL;
7758 }
Gautam Manam34d1f542021-01-05 20:24:37 +05307759 lock_input_stream(in);
Haynes Mathew George16081042017-05-31 17:16:49 -07007760 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
Gautam Manam34d1f542021-01-05 20:24:37 +05307761 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07007762 return -ENOSYS;
7763 }
7764 if (in->pcm == NULL) {
Gautam Manam34d1f542021-01-05 20:24:37 +05307765 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07007766 return -ENOSYS;
7767 }
7768 struct timespec ts = { 0, 0 };
7769 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
7770 if (ret < 0) {
7771 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
Gautam Manam34d1f542021-01-05 20:24:37 +05307772 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07007773 return ret;
7774 }
Phil Burke0a86d12019-02-16 22:28:11 -08007775 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7776 + in->mmap_time_offset_nanos;
Gautam Manam34d1f542021-01-05 20:24:37 +05307777 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07007778 return 0;
7779}
7780
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307781static int in_get_active_microphones(const struct audio_stream_in *stream,
7782 struct audio_microphone_characteristic_t *mic_array,
7783 size_t *mic_count) {
7784 struct stream_in *in = (struct stream_in *)stream;
7785 struct audio_device *adev = in->dev;
7786 ALOGVV("%s", __func__);
7787
7788 lock_input_stream(in);
7789 pthread_mutex_lock(&adev->lock);
7790 int ret = platform_get_active_microphones(adev->platform,
7791 audio_channel_count_from_in_mask(in->channel_mask),
7792 in->usecase, mic_array, mic_count);
7793 pthread_mutex_unlock(&adev->lock);
7794 pthread_mutex_unlock(&in->lock);
7795
7796 return ret;
7797}
7798
7799static int adev_get_microphones(const struct audio_hw_device *dev,
7800 struct audio_microphone_characteristic_t *mic_array,
7801 size_t *mic_count) {
7802 struct audio_device *adev = (struct audio_device *)dev;
7803 ALOGVV("%s", __func__);
7804
7805 pthread_mutex_lock(&adev->lock);
7806 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
7807 pthread_mutex_unlock(&adev->lock);
7808
7809 return ret;
7810}
juyuchendb308c22019-01-21 11:57:17 -07007811
7812static void in_update_sink_metadata(struct audio_stream_in *stream,
7813 const struct sink_metadata *sink_metadata) {
7814
7815 if (stream == NULL
7816 || sink_metadata == NULL
7817 || sink_metadata->tracks == NULL) {
7818 return;
7819 }
7820
7821 int error = 0;
7822 struct stream_in *in = (struct stream_in *)stream;
7823 struct audio_device *adev = in->dev;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007824 struct listnode devices;
7825
7826 list_init(&devices);
juyuchendb308c22019-01-21 11:57:17 -07007827
7828 if (sink_metadata->track_count != 0)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007829 reassign_device_list(&devices, sink_metadata->tracks->dest_device, "");
juyuchendb308c22019-01-21 11:57:17 -07007830
7831 lock_input_stream(in);
7832 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007833 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, get_device_types(&devices));
juyuchendb308c22019-01-21 11:57:17 -07007834
Zhou Song503196b2021-07-23 17:31:05 +08007835 if ((in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY ||
7836 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2) &&
7837 !list_empty(&devices) &&
7838 adev->voice_tx_output != NULL) {
juyuchendb308c22019-01-21 11:57:17 -07007839 /* Use the rx device from afe-proxy record to route voice call because
7840 there is no routing if tx device is on primary hal and rx device
7841 is on other hal during voice call. */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007842 assign_devices(&adev->voice_tx_output->device_list, &devices);
juyuchendb308c22019-01-21 11:57:17 -07007843
7844 if (!voice_is_call_state_active(adev)) {
7845 if (adev->mode == AUDIO_MODE_IN_CALL) {
7846 adev->current_call_output = adev->voice_tx_output;
7847 error = voice_start_call(adev);
7848 if (error != 0)
7849 ALOGE("%s: start voice call failed %d", __func__, error);
7850 }
7851 } else {
7852 adev->current_call_output = adev->voice_tx_output;
7853 voice_update_devices_for_all_voice_usecases(adev);
7854 }
7855 }
7856
7857 pthread_mutex_unlock(&adev->lock);
7858 pthread_mutex_unlock(&in->lock);
7859}
7860
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307861int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07007862 audio_io_handle_t handle,
7863 audio_devices_t devices,
7864 audio_output_flags_t flags,
7865 struct audio_config *config,
7866 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04007867 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007868{
7869 struct audio_device *adev = (struct audio_device *)dev;
7870 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05307871 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007872 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007873 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05307874 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007875 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
7876 bool is_usb_dev = audio_is_usb_out_device(devices) &&
7877 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
7878 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007879 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07007880 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
7881 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007882 bool force_haptic_path =
7883 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007884 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08007885#ifdef AUDIO_GKI_ENABLED
7886 __s32 *generic_dec;
7887#endif
Weiyin Jiang906db3c2021-03-02 13:17:04 +08007888 pthread_mutexattr_t latch_attr;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007889
kunleizdff872d2018-08-20 14:40:33 +08007890 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007891 is_usb_dev = false;
7892 devices = AUDIO_DEVICE_OUT_SPEAKER;
7893 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
7894 __func__, devices);
Mingshu Pangdbd20562019-11-25 18:04:39 +08007895 if (config->format == AUDIO_FORMAT_DEFAULT)
7896 config->format = AUDIO_FORMAT_PCM_16_BIT;
7897 if (config->sample_rate == 0)
7898 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7899 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7900 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
kunleizd6a9e0c2018-07-30 15:38:52 +08007901 }
7902
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007903 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05307904
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007905 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
7906
Mingming Yin3a941d42016-02-17 18:08:05 -08007907 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04007908 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
7909 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307910
7911
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007912 if (!out) {
7913 return -ENOMEM;
7914 }
7915
Haynes Mathew George204045b2015-02-25 20:32:03 -08007916 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007917 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Weiyin Jiang906db3c2021-03-02 13:17:04 +08007918 pthread_mutexattr_init(&latch_attr);
7919 pthread_mutexattr_settype(&latch_attr, PTHREAD_MUTEX_RECURSIVE);
7920 pthread_mutex_init(&out->latch_lock, &latch_attr);
7921 pthread_mutexattr_destroy(&latch_attr);
Zhou Song48453a02018-01-10 17:50:59 +08007922 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08007923 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
7924
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007925 if (devices == AUDIO_DEVICE_NONE)
7926 devices = AUDIO_DEVICE_OUT_SPEAKER;
7927
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007928 out->flags = flags;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007929 list_init(&out->device_list);
7930 update_device_list(&out->device_list, devices, address, true /* add devices */);
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07007931 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07007932 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007933 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05307934 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05307935 if (out->channel_mask == AUDIO_CHANNEL_NONE)
7936 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
7937 else
7938 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07007939 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007940 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08007941 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307942 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307943 out->started = 0;
Zhou Songbaddf9f2020-11-20 13:57:39 +08007944 out->a2dp_muted = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007945 out->hal_output_suspend_supported = 0;
7946 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05307947 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05307948 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05307949 out->pspd_coeff_sent = false;
Phil Burkd898ba62019-06-20 12:49:01 -07007950 out->mmap_shared_memory_fd = -1; // not open
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007951
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05307952 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05307953 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07007954 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
7955
Aalique Grahame22e49102018-12-18 14:23:57 -08007956 if (direct_dev &&
7957 (audio_is_linear_pcm(out->format) ||
7958 config->format == AUDIO_FORMAT_DEFAULT) &&
7959 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
7960 audio_format_t req_format = config->format;
7961 audio_channel_mask_t req_channel_mask = config->channel_mask;
7962 uint32_t req_sample_rate = config->sample_rate;
7963
7964 pthread_mutex_lock(&adev->lock);
7965 if (is_hdmi) {
7966 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
7967 ret = read_hdmi_sink_caps(out);
7968 if (config->sample_rate == 0)
7969 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7970 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7971 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
7972 if (config->format == AUDIO_FORMAT_DEFAULT)
7973 config->format = AUDIO_FORMAT_PCM_16_BIT;
7974 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007975 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
7976 &config->format,
7977 &out->supported_formats[0],
7978 MAX_SUPPORTED_FORMATS,
7979 &config->channel_mask,
7980 &out->supported_channel_masks[0],
7981 MAX_SUPPORTED_CHANNEL_MASKS,
7982 &config->sample_rate,
7983 &out->supported_sample_rates[0],
7984 MAX_SUPPORTED_SAMPLE_RATES);
7985 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007986 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007987
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007988 pthread_mutex_unlock(&adev->lock);
7989 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007990 if (ret == -ENOSYS) {
7991 /* ignore and go with default */
7992 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007993 }
7994 // For MMAP NO IRQ, allow conversions in ADSP
7995 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
7996 goto error_open;
7997 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007998 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08007999 goto error_open;
8000 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008001
8002 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
8003 config->sample_rate = req_sample_rate;
8004 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
8005 config->channel_mask = req_channel_mask;
8006 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
8007 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08008008 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008009
8010 out->sample_rate = config->sample_rate;
8011 out->channel_mask = config->channel_mask;
8012 out->format = config->format;
8013 if (is_hdmi) {
8014 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
8015 out->config = pcm_config_hdmi_multi;
8016 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8017 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8018 out->config = pcm_config_mmap_playback;
8019 out->stream.start = out_start;
8020 out->stream.stop = out_stop;
8021 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8022 out->stream.get_mmap_position = out_get_mmap_position;
8023 } else {
8024 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
8025 out->config = pcm_config_hifi;
8026 }
8027
8028 out->config.rate = out->sample_rate;
8029 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
8030 if (is_hdmi) {
8031 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
8032 audio_bytes_per_sample(out->format));
8033 }
8034 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08008035 }
8036
Derek Chenf6318be2017-06-12 17:16:24 -04008037 /* validate bus device address */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008038 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008039 /* extract car audio stream index */
8040 out->car_audio_stream =
8041 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
8042 if (out->car_audio_stream < 0) {
8043 ALOGE("%s: invalid car audio stream %x",
8044 __func__, out->car_audio_stream);
8045 ret = -EINVAL;
8046 goto error_open;
8047 }
Derek Chen5f67a942020-02-24 23:08:13 -08008048 ALOGV("%s: car_audio_stream %x", __func__, out->car_audio_stream);
Derek Chenf6318be2017-06-12 17:16:24 -04008049 }
8050
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008051 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07008052 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008053 if (!voice_extn_is_compress_voip_supported()) {
8054 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
8055 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07008056 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
Lakshman Chaluvarajue7fc9482020-05-30 14:29:29 +05308057 config->channel_mask : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008058 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
8059 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07008060 out->volume_l = INVALID_OUT_VOLUME;
8061 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07008062
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008063 out->config = default_pcm_config_voip_copp;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008064 out->config.rate = out->sample_rate;
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07008065 uint32_t channel_count =
8066 audio_channel_count_from_out_mask(out->channel_mask);
Ramjee Singh968858a2020-08-06 16:30:48 +05308067 out->config.channels = channel_count;
8068
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07008069 uint32_t buffer_size = get_stream_buffer_size(DEFAULT_VOIP_BUF_DURATION_MS,
8070 out->sample_rate, out->format,
8071 channel_count, false);
8072 uint32_t frame_size = audio_bytes_per_sample(out->format) * channel_count;
8073 if (frame_size != 0)
8074 out->config.period_size = buffer_size / frame_size;
8075 else
8076 ALOGW("%s: frame size is 0 for format %#x", __func__, out->format);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008077 }
8078 } else {
8079 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
8080 voice_extn_compress_voip_is_active(out->dev)) &&
8081 (voice_extn_compress_voip_is_config_supported(config))) {
8082 ret = voice_extn_compress_voip_open_output_stream(out);
8083 if (ret != 0) {
8084 ALOGE("%s: Compress voip output cannot be opened, error:%d",
8085 __func__, ret);
8086 goto error_open;
8087 }
Sujin Panicker19027262019-09-16 18:28:06 +05308088 } else {
8089 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8090 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008091 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008092 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008093 } else if (audio_is_linear_pcm(out->format) &&
8094 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
8095 out->channel_mask = config->channel_mask;
8096 out->sample_rate = config->sample_rate;
8097 out->format = config->format;
8098 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
8099 // does this change?
8100 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
8101 out->config.rate = config->sample_rate;
8102 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
8103 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
8104 audio_bytes_per_sample(config->format));
8105 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07008106 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308107 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308108 pthread_mutex_lock(&adev->lock);
8109 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
8110 pthread_mutex_unlock(&adev->lock);
8111
8112 // reject offload during card offline to allow
8113 // fallback to s/w paths
8114 if (offline) {
8115 ret = -ENODEV;
8116 goto error_open;
8117 }
vivek mehta0ea887a2015-08-26 14:01:20 -07008118
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008119 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
8120 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
8121 ALOGE("%s: Unsupported Offload information", __func__);
8122 ret = -EINVAL;
8123 goto error_open;
8124 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008125
Atul Khare3fa6e542017-08-09 00:56:17 +05308126 if (config->offload_info.format == 0)
8127 config->offload_info.format = config->format;
8128 if (config->offload_info.sample_rate == 0)
8129 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008130
Mingming Yin90310102013-11-13 16:57:00 -08008131 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308132 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07008133 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008134 ret = -EINVAL;
8135 goto error_open;
8136 }
8137
Ben Romberger0f8c87b2017-05-24 17:41:11 -07008138 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
8139 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
8140 (audio_extn_passthru_is_passthrough_stream(out)) &&
8141 !((config->sample_rate == 48000) ||
8142 (config->sample_rate == 96000) ||
8143 (config->sample_rate == 192000))) {
8144 ALOGE("%s: Unsupported sample rate %d for audio format %x",
8145 __func__, config->sample_rate, config->offload_info.format);
8146 ret = -EINVAL;
8147 goto error_open;
8148 }
8149
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008150 out->compr_config.codec = (struct snd_codec *)
8151 calloc(1, sizeof(struct snd_codec));
8152
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008153 if (!out->compr_config.codec) {
8154 ret = -ENOMEM;
8155 goto error_open;
8156 }
8157
Dhananjay Kumarac341582017-02-23 23:42:25 +05308158 out->stream.pause = out_pause;
8159 out->stream.resume = out_resume;
8160 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05308161 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05308162 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07008163 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05308164 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07008165 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05308166 } else {
8167 out->usecase = get_offload_usecase(adev, false /* is_compress */);
8168 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07008169 }
vivek mehta446c3962015-09-14 10:57:35 -07008170
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308171 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8172 ALOGD("%s: Setting latency mode to true", __func__);
Meng Wang4c32fb42020-01-16 17:57:11 +08008173#ifdef AUDIO_GKI_ENABLED
8174 /* out->compr_config.codec->reserved[1] is for flags */
8175 out->compr_config.codec->reserved[1] |= audio_extn_utils_get_perf_mode_flag();
8176#else
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308177 out->compr_config.codec->flags |= audio_extn_utils_get_perf_mode_flag();
Meng Wang4c32fb42020-01-16 17:57:11 +08008178#endif
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308179 }
8180
vivek mehta446c3962015-09-14 10:57:35 -07008181 if (out->usecase == USECASE_INVALID) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008182 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Mingming Yin3a941d42016-02-17 18:08:05 -08008183 config->format == 0 && config->sample_rate == 0 &&
8184 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07008185 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08008186 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
8187 } else {
8188 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
8189 ret = -EEXIST;
8190 goto error_open;
8191 }
vivek mehta446c3962015-09-14 10:57:35 -07008192 }
8193
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008194 if (config->offload_info.channel_mask)
8195 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008196 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008197 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008198 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008199 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05308200 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008201 ret = -EINVAL;
8202 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008203 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008204
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008205 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008206 out->sample_rate = config->offload_info.sample_rate;
8207
Mingming Yin3ee55c62014-08-04 14:23:35 -07008208 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008209
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308210 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05308211 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308212 audio_extn_dolby_send_ddp_endp_params(adev);
8213 audio_extn_dolby_set_dmid(adev);
8214 }
vivek mehta0ea887a2015-08-26 14:01:20 -07008215
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008216 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08008217 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008218 out->compr_config.codec->bit_rate =
8219 config->offload_info.bit_rate;
8220 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05308221 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008222 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05308223 /* Update bit width only for non passthrough usecases.
8224 * For passthrough usecases, the output will always be opened @16 bit
8225 */
8226 if (!audio_extn_passthru_is_passthrough_stream(out))
8227 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308228
8229 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
Meng Wang4c32fb42020-01-16 17:57:11 +08008230#ifdef AUDIO_GKI_ENABLED
8231 /* out->compr_config.codec->reserved[1] is for flags */
8232 out->compr_config.codec->reserved[1] |= COMPRESSED_TIMESTAMP_FLAG;
8233 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->reserved[1]);
8234#else
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308235 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
8236 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
Meng Wang4c32fb42020-01-16 17:57:11 +08008237#endif
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308238
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008239 /*TODO: Do we need to change it for passthrough */
8240 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008241
Manish Dewangana6fc5442015-08-24 20:30:31 +05308242 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
8243 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308244 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05308245 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308246 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
8247 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308248
8249 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
8250 AUDIO_FORMAT_PCM) {
8251
8252 /*Based on platform support, configure appropriate alsa format for corresponding
8253 *hal input format.
8254 */
8255 out->compr_config.codec->format = hal_format_to_alsa(
8256 config->offload_info.format);
8257
Ashish Jain83a6cc22016-06-28 14:34:17 +05308258 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05308259 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308260 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308261
Dhananjay Kumarac341582017-02-23 23:42:25 +05308262 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05308263 *hal input format and alsa format might differ based on platform support.
8264 */
8265 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05308266 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308267
8268 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
8269
Deeraj Soman93155a62019-09-30 19:00:37 +05308270 if (property_get_bool("vendor.audio.offload.buffer.duration.enabled", false)) {
8271 if ((config->offload_info.duration_us >= MIN_OFFLOAD_BUFFER_DURATION_MS * 1000) &&
8272 (config->offload_info.duration_us <= MAX_OFFLOAD_BUFFER_DURATION_MS * 1000))
8273 out->info.duration_us = (int64_t)config->offload_info.duration_us;
8274 }
Deeraj Soman65358ab2019-02-07 15:40:49 +05308275
Ashish Jainf1eaa582016-05-23 20:54:24 +05308276 /* Check if alsa session is configured with the same format as HAL input format,
8277 * if not then derive correct fragment size needed to accomodate the
8278 * conversion of HAL input format to alsa format.
8279 */
8280 audio_extn_utils_update_direct_pcm_fragment_size(out);
8281
8282 /*if hal input and output fragment size is different this indicates HAL input format is
8283 *not same as the alsa format
8284 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308285 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05308286 /*Allocate a buffer to convert input data to the alsa configured format.
8287 *size of convert buffer is equal to the size required to hold one fragment size
8288 *worth of pcm data, this is because flinger does not write more than fragment_size
8289 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308290 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
8291 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05308292 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
8293 ret = -ENOMEM;
8294 goto error_open;
8295 }
8296 }
8297 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
8298 out->compr_config.fragment_size =
8299 audio_extn_passthru_get_buffer_size(&config->offload_info);
8300 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8301 } else {
8302 out->compr_config.fragment_size =
8303 platform_get_compress_offload_buffer_size(&config->offload_info);
8304 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8305 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008306
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308307 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8308 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
8309 }
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008310 if (config->offload_info.format == AUDIO_FORMAT_FLAC) {
8311#ifdef AUDIO_GKI_ENABLED
8312 generic_dec =
8313 &(out->compr_config.codec->options.generic.reserved[1]);
8314 ((struct snd_generic_dec_flac *)generic_dec)->sample_size =
8315 AUDIO_OUTPUT_BIT_WIDTH;
8316#else
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05308317 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008318#endif
8319 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008320
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05308321 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
8322 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
8323 }
8324
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008325 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
8326 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008327
Manish Dewangan69426c82017-01-30 17:35:36 +05308328 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
8329 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
8330 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
8331 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8332 out->render_mode = RENDER_MODE_AUDIO_MASTER;
8333 } else {
8334 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
8335 }
Alexy Josephaa54c872014-12-03 02:46:47 -08008336
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05308337 memset(&out->channel_map_param, 0,
8338 sizeof(struct audio_out_channel_map_param));
8339
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008340 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05308341 out->send_next_track_params = false;
8342 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008343 out->offload_state = OFFLOAD_STATE_IDLE;
8344 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08008345 out->writeAt.tv_sec = 0;
8346 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008347
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008348 audio_extn_dts_create_state_notifier_node(out->usecase);
8349
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008350 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
8351 __func__, config->offload_info.version,
8352 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05308353
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308354 /* Check if DSD audio format is supported in codec
8355 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308356 */
8357
8358 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308359 (!platform_check_codec_dsd_support(adev->platform) ||
8360 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308361 ret = -EINVAL;
8362 goto error_open;
8363 }
8364
Ashish Jain5106d362016-05-11 19:23:33 +05308365 /* Disable gapless if any of the following is true
8366 * passthrough playback
8367 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05308368 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05308369 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308370 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308371 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07008372 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308373 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308374 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05308375 check_and_set_gapless_mode(adev, false);
8376 } else
8377 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07008378
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308379 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07008380 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
8381 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308382 if (config->format == AUDIO_FORMAT_DSD) {
8383 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
Meng Wang4c32fb42020-01-16 17:57:11 +08008384#ifdef AUDIO_GKI_ENABLED
8385 /* out->compr_config.codec->reserved[0] is for compr_passthr */
8386 out->compr_config.codec->reserved[0] = PASSTHROUGH_DSD;
8387#else
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308388 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
Meng Wang4c32fb42020-01-16 17:57:11 +08008389#endif
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308390 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07008391
8392 create_offload_callback_thread(out);
8393
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008394 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008395 switch (config->sample_rate) {
8396 case 0:
8397 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8398 break;
8399 case 8000:
8400 case 16000:
8401 case 48000:
8402 out->sample_rate = config->sample_rate;
8403 break;
8404 default:
8405 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
8406 config->sample_rate);
8407 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8408 ret = -EINVAL;
8409 goto error_open;
8410 }
8411 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8412 switch (config->channel_mask) {
8413 case AUDIO_CHANNEL_NONE:
8414 case AUDIO_CHANNEL_OUT_STEREO:
8415 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8416 break;
8417 default:
8418 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
8419 config->channel_mask);
8420 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8421 ret = -EINVAL;
8422 goto error_open;
8423 }
8424 switch (config->format) {
8425 case AUDIO_FORMAT_DEFAULT:
8426 case AUDIO_FORMAT_PCM_16_BIT:
8427 out->format = AUDIO_FORMAT_PCM_16_BIT;
8428 break;
8429 default:
8430 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
8431 config->format);
8432 config->format = AUDIO_FORMAT_PCM_16_BIT;
8433 ret = -EINVAL;
8434 goto error_open;
8435 }
8436
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05308437 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008438 if (ret != 0) {
8439 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008440 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008441 goto error_open;
8442 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008443 } else if (is_single_device_type_equal(&out->device_list,
8444 AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08008445 switch (config->sample_rate) {
8446 case 0:
8447 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
8448 break;
8449 case 8000:
8450 case 16000:
8451 case 48000:
8452 out->sample_rate = config->sample_rate;
8453 break;
8454 default:
8455 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
8456 config->sample_rate);
8457 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8458 ret = -EINVAL;
8459 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008460 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008461 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8462 switch (config->channel_mask) {
8463 case AUDIO_CHANNEL_NONE:
8464 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8465 break;
8466 case AUDIO_CHANNEL_OUT_STEREO:
8467 out->channel_mask = config->channel_mask;
8468 break;
8469 default:
8470 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
8471 config->channel_mask);
8472 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8473 ret = -EINVAL;
8474 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008475 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008476 switch (config->format) {
8477 case AUDIO_FORMAT_DEFAULT:
8478 out->format = AUDIO_FORMAT_PCM_16_BIT;
8479 break;
8480 case AUDIO_FORMAT_PCM_16_BIT:
8481 out->format = config->format;
8482 break;
8483 default:
8484 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
8485 config->format);
8486 config->format = AUDIO_FORMAT_PCM_16_BIT;
8487 ret = -EINVAL;
8488 break;
8489 }
8490 if (ret != 0)
8491 goto error_open;
8492
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008493 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
8494 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08008495 out->config.rate = out->sample_rate;
8496 out->config.channels =
8497 audio_channel_count_from_out_mask(out->channel_mask);
8498 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008499 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008500 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05308501 unsigned int channels = 0;
8502 /*Update config params to default if not set by the caller*/
8503 if (config->sample_rate == 0)
8504 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8505 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8506 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8507 if (config->format == AUDIO_FORMAT_DEFAULT)
8508 config->format = AUDIO_FORMAT_PCM_16_BIT;
8509
8510 channels = audio_channel_count_from_out_mask(out->channel_mask);
8511
Varun Balaraje49253e2017-07-06 19:48:56 +05308512 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
8513 out->usecase = get_interactive_usecase(adev);
8514 out->config = pcm_config_low_latency;
8515 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05308516 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008517 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
8518 out->flags);
8519 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07008520 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8521 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8522 out->config = pcm_config_mmap_playback;
8523 out->stream.start = out_start;
8524 out->stream.stop = out_stop;
8525 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8526 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308527 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8528 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008529 out->hal_output_suspend_supported =
8530 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
8531 out->dynamic_pm_qos_config_supported =
8532 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
8533 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08008534 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
8535 } else {
8536 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
8537 //the mixer path will be a string similar to "low-latency-playback resume"
8538 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
8539 strlcat(out->pm_qos_mixer_path,
8540 " resume", MAX_MIXER_PATH_LEN);
8541 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
8542 out->pm_qos_mixer_path);
8543 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308544 out->config = pcm_config_low_latency;
8545 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
8546 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
8547 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05308548 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
8549 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
8550 if (out->config.period_size <= 0) {
8551 ALOGE("Invalid configuration period size is not valid");
8552 ret = -EINVAL;
8553 goto error_open;
8554 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008555 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
8556 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
8557 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008558 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
8559 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
8560 out->config = pcm_config_haptics_audio;
8561 if (force_haptic_path)
8562 adev->haptics_config = pcm_config_haptics_audio;
8563 else
8564 adev->haptics_config = pcm_config_haptics;
8565
Meng Wangd08ce322020-04-02 08:59:20 +08008566 channels =
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008567 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
8568
8569 if (force_haptic_path) {
8570 out->config.channels = 1;
8571 adev->haptics_config.channels = 1;
8572 } else
8573 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 -08008574 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008575 ret = audio_extn_auto_hal_open_output_stream(out);
8576 if (ret) {
8577 ALOGE("%s: Failed to open output stream for bus device", __func__);
8578 ret = -EINVAL;
8579 goto error_open;
8580 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308581 } else {
8582 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008583 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8584 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308585 }
8586 out->hal_ip_format = format = out->format;
8587 out->config.format = hal_format_to_pcm(out->hal_ip_format);
8588 out->hal_op_format = pcm_format_to_hal(out->config.format);
8589 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
8590 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008591 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05308592 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308593 if (out->hal_ip_format != out->hal_op_format) {
8594 uint32_t buffer_size = out->config.period_size *
8595 format_to_bitwidth_table[out->hal_op_format] *
8596 out->config.channels;
8597 out->convert_buffer = calloc(1, buffer_size);
8598 if (out->convert_buffer == NULL){
8599 ALOGE("Allocation failed for convert buffer for size %d",
8600 out->compr_config.fragment_size);
8601 ret = -ENOMEM;
8602 goto error_open;
8603 }
8604 ALOGD("Convert buffer allocated of size %d", buffer_size);
8605 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008606 }
8607
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008608 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
8609 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308610
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008611 /* TODO remove this hardcoding and check why width is zero*/
8612 if (out->bit_width == 0)
8613 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308614 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008615 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008616 &out->device_list, out->flags,
8617 out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05308618 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05308619 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08008620 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08008621 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
8622 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008623 if(adev->primary_output == NULL)
8624 adev->primary_output = out;
8625 else {
8626 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008627 ret = -EEXIST;
8628 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008629 }
8630 }
8631
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008632 /* Check if this usecase is already existing */
8633 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07008634 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
8635 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008636 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008637 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008638 ret = -EEXIST;
8639 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008640 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008641
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008642 pthread_mutex_unlock(&adev->lock);
8643
8644 out->stream.common.get_sample_rate = out_get_sample_rate;
8645 out->stream.common.set_sample_rate = out_set_sample_rate;
8646 out->stream.common.get_buffer_size = out_get_buffer_size;
8647 out->stream.common.get_channels = out_get_channels;
8648 out->stream.common.get_format = out_get_format;
8649 out->stream.common.set_format = out_set_format;
8650 out->stream.common.standby = out_standby;
8651 out->stream.common.dump = out_dump;
8652 out->stream.common.set_parameters = out_set_parameters;
8653 out->stream.common.get_parameters = out_get_parameters;
8654 out->stream.common.add_audio_effect = out_add_audio_effect;
8655 out->stream.common.remove_audio_effect = out_remove_audio_effect;
8656 out->stream.get_latency = out_get_latency;
8657 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08008658#ifdef NO_AUDIO_OUT
8659 out->stream.write = out_write_for_no_output;
8660#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008661 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08008662#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008663 out->stream.get_render_position = out_get_render_position;
8664 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008665 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008666
Haynes Mathew George16081042017-05-31 17:16:49 -07008667 if (out->realtime)
8668 out->af_period_multiplier = af_period_multiplier;
8669 else
8670 out->af_period_multiplier = 1;
8671
Andy Hunga1f48fa2019-07-01 18:14:53 -07008672 out->kernel_buffer_size = out->config.period_size * out->config.period_count;
8673
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008674 out->standby = 1;
Zhou Songbaddf9f2020-11-20 13:57:39 +08008675 out->volume_l = PLAYBACK_GAIN_MAX;
8676 out->volume_r = PLAYBACK_GAIN_MAX;
Eric Laurenta9024de2013-04-04 09:19:12 -07008677 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008678 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008679
8680 config->format = out->stream.common.get_format(&out->stream.common);
8681 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
8682 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308683 register_format(out->format, out->supported_formats);
8684 register_channel_mask(out->channel_mask, out->supported_channel_masks);
8685 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008686
Dechen Chai22768452021-07-30 09:29:16 +05308687#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -08008688 out->error_log = error_log_create(
8689 ERROR_LOG_ENTRIES,
8690 1000000000 /* aggregate consecutive identical errors within one second in ns */);
Dechen Chai22768452021-07-30 09:29:16 +05308691#endif
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308692 /*
8693 By locking output stream before registering, we allow the callback
8694 to update stream's state only after stream's initial state is set to
8695 adev state.
8696 */
8697 lock_output_stream(out);
8698 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
8699 pthread_mutex_lock(&adev->lock);
8700 out->card_status = adev->card_status;
8701 pthread_mutex_unlock(&adev->lock);
8702 pthread_mutex_unlock(&out->lock);
8703
Aalique Grahame22e49102018-12-18 14:23:57 -08008704 stream_app_type_cfg_init(&out->app_type_cfg);
8705
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008706 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308707 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07008708 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008709
8710 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
8711 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
8712 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008713 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05308714 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008715 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07008716 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05308717 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
8718 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008719 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
8720 out->usecase, PCM_PLAYBACK);
8721 hdlr_stream_cfg.flags = out->flags;
8722 hdlr_stream_cfg.type = PCM_PLAYBACK;
8723 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
8724 &hdlr_stream_cfg);
8725 if (ret) {
8726 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
8727 out->adsp_hdlr_stream_handle = NULL;
8728 }
8729 }
Gangadhar Sb0210342019-02-22 17:39:41 +05308730 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
8731 is_direct_passthough, false);
8732 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
8733 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07008734 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07008735 if (ret < 0) {
8736 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
8737 out->ip_hdlr_handle = NULL;
8738 }
8739 }
Derek Chenf939fb72018-11-13 13:34:41 -08008740
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008741 ret = io_streams_map_insert(adev, &out->stream.common,
8742 out->handle, AUDIO_PATCH_HANDLE_NONE);
8743 if (ret != 0)
8744 goto error_open;
8745
Susan Wang6dd13092021-01-25 10:27:11 -05008746 out->out_ctxt.output = out;
Derek Chenf939fb72018-11-13 13:34:41 -08008747
8748 pthread_mutex_lock(&adev->lock);
Susan Wang6dd13092021-01-25 10:27:11 -05008749 list_add_tail(&adev->active_outputs_list, &out->out_ctxt.list);
Derek Chenf939fb72018-11-13 13:34:41 -08008750 pthread_mutex_unlock(&adev->lock);
8751
Eric Laurent994a6932013-07-17 11:51:42 -07008752 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008753 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008754
8755error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05308756 if (out->convert_buffer)
8757 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008758 free(out);
8759 *stream_out = NULL;
8760 ALOGD("%s: exit: ret %d", __func__, ret);
8761 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008762}
8763
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308764void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008765 struct audio_stream_out *stream)
8766{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008767 struct stream_out *out = (struct stream_out *)stream;
8768 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008769 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008770
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008771 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308772
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008773 io_streams_map_remove(adev, out->handle);
8774
Susan Wang6dd13092021-01-25 10:27:11 -05008775 // remove out_ctxt early to prevent the stream
8776 // being opened in a race condition
8777 pthread_mutex_lock(&adev->lock);
8778 list_remove(&out->out_ctxt.list);
8779 pthread_mutex_unlock(&adev->lock);
8780
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308781 // must deregister from sndmonitor first to prevent races
8782 // between the callback and close_stream
8783 audio_extn_snd_mon_unregister_listener(out);
8784
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008785 /* close adsp hdrl session before standby */
8786 if (out->adsp_hdlr_stream_handle) {
8787 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
8788 if (ret)
8789 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
8790 out->adsp_hdlr_stream_handle = NULL;
8791 }
8792
Manish Dewangan21a850a2017-08-14 12:03:55 +05308793 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07008794 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
8795 out->ip_hdlr_handle = NULL;
8796 }
8797
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008798 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308799 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008800 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308801 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308802 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008803 if(ret != 0)
8804 ALOGE("%s: Compress voip output cannot be closed, error:%d",
8805 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008806 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008807 out_standby(&stream->common);
8808
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008809 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008810 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008811 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008812 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008813 if (out->compr_config.codec != NULL)
8814 free(out->compr_config.codec);
8815 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008816
Zhou Songbaddf9f2020-11-20 13:57:39 +08008817 out->a2dp_muted = false;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05308818
Varun Balaraje49253e2017-07-06 19:48:56 +05308819 if (is_interactive_usecase(out->usecase))
8820 free_interactive_usecase(adev, out->usecase);
8821
Ashish Jain83a6cc22016-06-28 14:34:17 +05308822 if (out->convert_buffer != NULL) {
8823 free(out->convert_buffer);
8824 out->convert_buffer = NULL;
8825 }
8826
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008827 if (adev->voice_tx_output == out)
8828 adev->voice_tx_output = NULL;
8829
Dechen Chai22768452021-07-30 09:29:16 +05308830#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -08008831 error_log_destroy(out->error_log);
8832 out->error_log = NULL;
Dechen Chai22768452021-07-30 09:29:16 +05308833#endif
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05308834 if (adev->primary_output == out)
8835 adev->primary_output = NULL;
8836
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008837 pthread_cond_destroy(&out->cond);
8838 pthread_mutex_destroy(&out->lock);
Weiyin Jiang280ea742020-09-08 20:28:22 +08008839 pthread_mutex_destroy(&out->pre_lock);
8840 pthread_mutex_destroy(&out->latch_lock);
8841 pthread_mutex_destroy(&out->position_query_lock);
Derek Chenf939fb72018-11-13 13:34:41 -08008842
8843 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008844 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08008845 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07008846 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008847}
8848
8849static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
8850{
8851 struct audio_device *adev = (struct audio_device *)dev;
8852 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008853 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008854 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008855 int ret;
8856 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08008857 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008858 struct listnode *node;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008859 int controller = -1, stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008860
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008861 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008862 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008863
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308864 if (!parms)
8865 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05308866
Derek Chen6f293672019-04-01 01:40:24 -07008867 /* notify adev and input/output streams on the snd card status */
8868 adev_snd_mon_cb((void *)adev, parms);
8869
Weiyin Jiang24f55292020-12-22 14:35:46 +08008870 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
8871 if (ret >= 0) {
8872 list_for_each(node, &adev->active_outputs_list) {
8873 streams_output_ctxt_t *out_ctxt = node_to_item(node,
8874 streams_output_ctxt_t,
8875 list);
8876 out_snd_mon_cb((void *)out_ctxt->output, parms);
8877 }
Derek Chen6f293672019-04-01 01:40:24 -07008878
Weiyin Jiang24f55292020-12-22 14:35:46 +08008879 list_for_each(node, &adev->active_inputs_list) {
8880 streams_input_ctxt_t *in_ctxt = node_to_item(node,
8881 streams_input_ctxt_t,
8882 list);
8883 in_snd_mon_cb((void *)in_ctxt->input, parms);
8884 }
Derek Chen6f293672019-04-01 01:40:24 -07008885 }
8886
Zhou Songd6d71752019-05-21 18:08:51 +08008887 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308888 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
8889 if (ret >= 0) {
8890 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08008891 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308892 adev->bt_sco_on = true;
Shalini Manjunatha3a2e06e2021-02-01 12:23:49 +05308893 /*
8894 * When ever BT_SCO=ON arrives, make sure to route
8895 * all use cases to SCO device, otherwise due to delay in
8896 * BT_SCO=ON and lack of synchronization with create audio patch
8897 * request for SCO device, some times use case not routed properly to
8898 * SCO device
8899 */
8900 struct audio_usecase *usecase;
8901 struct listnode *node;
8902 list_for_each(node, &adev->usecase_list) {
8903 usecase = node_to_item(node, struct audio_usecase, list);
Anver sadhiquef0efca32021-09-03 15:25:44 +05308904 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
Anver sadhique93f3c912021-08-11 11:19:45 +05308905 (!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 +05308906 ALOGD("BT_SCO ON, switch all in use case to it");
8907 select_devices(adev, usecase->id);
8908 }
Mingshu Pangef517202021-04-22 10:35:00 +08008909 if (usecase->stream.out && (usecase->type == PCM_PLAYBACK ||
8910 usecase->type == VOICE_CALL) &&
Anver sadhique93f3c912021-08-11 11:19:45 +05308911 (!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 +05308912 ALOGD("BT_SCO ON, switch all out use case to it");
8913 select_devices(adev, usecase->id);
8914 }
8915 }
8916 }
8917 else {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308918 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008919 audio_extn_sco_reset_configuration();
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008920 }
8921 }
8922
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008923 status = voice_set_parameters(adev, parms);
8924 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008925 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008926
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008927 status = platform_set_parameters(adev->platform, parms);
8928 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008929 goto done;
8930
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008931 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
8932 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07008933 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008934 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8935 adev->bluetooth_nrec = true;
8936 else
8937 adev->bluetooth_nrec = false;
8938 }
8939
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008940 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
8941 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008942 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8943 adev->screen_off = false;
8944 else
8945 adev->screen_off = true;
Quinn Male70f20f32019-06-26 16:50:26 -07008946 audio_extn_sound_trigger_update_screen_status(adev->screen_off);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008947 }
8948
Eric Laurent4b084132018-10-19 17:33:43 -07008949 ret = str_parms_get_int(parms, "rotation", &val);
8950 if (ret >= 0) {
8951 bool reverse_speakers = false;
8952 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8953 switch (val) {
8954 // FIXME: note that the code below assumes that the speakers are in the correct placement
8955 // relative to the user when the device is rotated 90deg from its default rotation. This
8956 // assumption is device-specific, not platform-specific like this code.
8957 case 270:
8958 reverse_speakers = true;
8959 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
8960 break;
8961 case 0:
8962 case 180:
8963 camera_rotation = CAMERA_ROTATION_PORTRAIT;
8964 break;
8965 case 90:
8966 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8967 break;
8968 default:
8969 ALOGE("%s: unexpected rotation of %d", __func__, val);
8970 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008971 }
Eric Laurent4b084132018-10-19 17:33:43 -07008972 if (status == 0) {
8973 // check and set swap
8974 // - check if orientation changed and speaker active
8975 // - set rotation and cache the rotation value
8976 adev->camera_orientation =
8977 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
8978 if (!audio_extn_is_maxx_audio_enabled())
8979 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
8980 }
8981 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008982
Mingming Yin514a8bc2014-07-29 15:22:21 -07008983 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
8984 if (ret >= 0) {
8985 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8986 adev->bt_wb_speech_enabled = true;
8987 else
8988 adev->bt_wb_speech_enabled = false;
8989 }
8990
Zhou Song12c29502019-03-16 10:37:18 +08008991 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
8992 if (ret >= 0) {
8993 val = atoi(value);
8994 adev->swb_speech_mode = val;
8995 }
8996
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008997 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
8998 if (ret >= 0) {
8999 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309000 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08009001 if (audio_is_output_device(val) &&
9002 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07009003 ALOGV("cache new ext disp type and edid");
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07009004 platform_get_controller_stream_from_params(parms, &controller, &stream);
9005 platform_set_ext_display_device_v2(adev->platform, controller, stream);
9006 ret = platform_get_ext_disp_type_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07009007 if (ret < 0) {
9008 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05309009 } else {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07009010 platform_cache_edid_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07009011 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309012 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07009013 /*
9014 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
9015 * Per AudioPolicyManager, USB device is higher priority than WFD.
9016 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
9017 * If WFD use case occupies AFE proxy, it may result unintended behavior while
9018 * starting voice call on USB
9019 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08009020 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309021 if (ret >= 0)
9022 audio_extn_usb_add_device(device, atoi(value));
9023
Zhou Song6f862822017-11-06 17:27:57 +08009024 if (!audio_extn_usb_is_tunnel_supported()) {
9025 ALOGV("detected USB connect .. disable proxy");
9026 adev->allow_afe_proxy_usage = false;
9027 }
Zhou Song503196b2021-07-23 17:31:05 +08009028 } else if (audio_is_hearing_aid_out_device(device) &&
9029 property_get_bool("persist.vendor.audio.ha_proxy.enabled", false)) {
9030 adev->ha_proxy_enable = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07009031 }
9032 }
9033
9034 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
9035 if (ret >= 0) {
9036 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309037 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07009038 /*
9039 * The HDMI / Displayport disconnect handling has been moved to
9040 * audio extension to ensure that its parameters are not
9041 * invalidated prior to updating sysfs of the disconnect event
9042 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
9043 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309044 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08009045 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05309046 if (ret >= 0)
9047 audio_extn_usb_remove_device(device, atoi(value));
9048
Zhou Song6f862822017-11-06 17:27:57 +08009049 if (!audio_extn_usb_is_tunnel_supported()) {
9050 ALOGV("detected USB disconnect .. enable proxy");
9051 adev->allow_afe_proxy_usage = true;
9052 }
Zhou Song503196b2021-07-23 17:31:05 +08009053 } else if (audio_is_hearing_aid_out_device(device)) {
9054 adev->ha_proxy_enable = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07009055 }
9056 }
9057
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009058 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08009059
9060 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08009061 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309062 struct audio_usecase *usecase;
9063 struct listnode *node;
9064 list_for_each(node, &adev->usecase_list) {
9065 usecase = node_to_item(node, struct audio_usecase, list);
Weiyin Jiangff56ff32020-05-08 14:32:21 +08009066 if ((usecase->stream.out == NULL) || (usecase->type != PCM_PLAYBACK))
9067 continue;
9068
9069 if (is_a2dp_out_device_type(&usecase->device_list)) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309070 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05309071 audio_extn_a2dp_set_handoff_mode(true);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05309072 ALOGD("Switching to speaker and muting the stream before select_devices");
9073 check_a2dp_restore_l(adev, usecase->stream.out, false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309074 //force device switch to re configure encoder
9075 select_devices(adev, usecase->id);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05309076 ALOGD("Unmuting the stream after select_devices");
Zhou Songbaddf9f2020-11-20 13:57:39 +08009077 check_a2dp_restore_l(adev, usecase->stream.out, true);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05309078 audio_extn_a2dp_set_handoff_mode(false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309079 break;
Zhou Songd01e7a22020-09-23 22:49:01 +08009080 } else if (is_offload_usecase(usecase->stream.out->usecase)) {
Weiyin Jiang280ea742020-09-08 20:28:22 +08009081 pthread_mutex_lock(&usecase->stream.out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +08009082 if (usecase->stream.out->a2dp_muted) {
Weiyin Jiang280ea742020-09-08 20:28:22 +08009083 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
9084 reassign_device_list(&usecase->stream.out->device_list,
9085 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, "");
9086 check_a2dp_restore_l(adev, usecase->stream.out, true);
9087 break;
9088 }
9089 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309090 }
9091 }
9092 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009093
9094 //handle vr audio setparam
9095 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9096 value, sizeof(value));
9097 if (ret >= 0) {
9098 ALOGI("Setting vr mode to be %s", value);
9099 if (!strncmp(value, "true", 4)) {
9100 adev->vr_audio_mode_enabled = true;
9101 ALOGI("Setting vr mode to true");
9102 } else if (!strncmp(value, "false", 5)) {
9103 adev->vr_audio_mode_enabled = false;
9104 ALOGI("Setting vr mode to false");
9105 } else {
9106 ALOGI("wrong vr mode set");
9107 }
9108 }
9109
Eric Laurent4b084132018-10-19 17:33:43 -07009110 //FIXME: to be replaced by proper video capture properties API
9111 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
9112 if (ret >= 0) {
9113 int camera_facing = CAMERA_FACING_BACK;
9114 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
9115 camera_facing = CAMERA_FACING_FRONT;
9116 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
9117 camera_facing = CAMERA_FACING_BACK;
9118 else {
9119 ALOGW("%s: invalid camera facing value: %s", __func__, value);
9120 goto done;
9121 }
9122 adev->camera_orientation =
9123 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
9124 struct audio_usecase *usecase;
9125 struct listnode *node;
9126 list_for_each(node, &adev->usecase_list) {
9127 usecase = node_to_item(node, struct audio_usecase, list);
9128 struct stream_in *in = usecase->stream.in;
9129 if (usecase->type == PCM_CAPTURE && in != NULL &&
9130 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
9131 select_devices(adev, in->usecase);
9132 }
9133 }
9134 }
9135
Naresh Tannirucd2353e2016-08-19 00:37:25 +05309136 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08009137done:
9138 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009139 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05309140error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009141 ALOGV("%s: exit with code(%d)", __func__, status);
9142 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009143}
9144
9145static char* adev_get_parameters(const struct audio_hw_device *dev,
9146 const char *keys)
9147{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05309148 ALOGD("%s:%s", __func__, keys);
9149
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009150 struct audio_device *adev = (struct audio_device *)dev;
9151 struct str_parms *reply = str_parms_create();
9152 struct str_parms *query = str_parms_create_str(keys);
9153 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05309154 char value[256] = {0};
9155 int ret = 0;
9156
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009157 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08009158 if (reply) {
9159 str_parms_destroy(reply);
9160 }
9161 if (query) {
9162 str_parms_destroy(query);
9163 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009164 ALOGE("adev_get_parameters: failed to create query or reply");
9165 return NULL;
9166 }
9167
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009168 //handle vr audio getparam
9169
9170 ret = str_parms_get_str(query,
9171 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9172 value, sizeof(value));
9173
9174 if (ret >= 0) {
9175 bool vr_audio_enabled = false;
9176 pthread_mutex_lock(&adev->lock);
9177 vr_audio_enabled = adev->vr_audio_mode_enabled;
9178 pthread_mutex_unlock(&adev->lock);
9179
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07009180 ALOGV("getting vr mode to %d", vr_audio_enabled);
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009181
9182 if (vr_audio_enabled) {
9183 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9184 "true");
9185 goto exit;
9186 } else {
9187 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9188 "false");
9189 goto exit;
9190 }
9191 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009192
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009193 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009194 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08009195 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08009196 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009197 platform_get_parameters(adev->platform, query, reply);
justinwengd5395152019-11-04 12:23:09 +08009198 audio_extn_ma_get_parameters(adev, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05309199 pthread_mutex_unlock(&adev->lock);
9200
Naresh Tannirud7205b62014-06-20 02:54:48 +05309201exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009202 str = str_parms_to_str(reply);
9203 str_parms_destroy(query);
9204 str_parms_destroy(reply);
9205
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07009206 ALOGV("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009207 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009208}
9209
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009210static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009211{
9212 return 0;
9213}
9214
9215static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
9216{
Haynes Mathew George5191a852013-09-11 14:19:36 -07009217 int ret;
9218 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08009219
9220 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
9221
Haynes Mathew George5191a852013-09-11 14:19:36 -07009222 pthread_mutex_lock(&adev->lock);
9223 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07009224 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07009225 pthread_mutex_unlock(&adev->lock);
9226 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009227}
9228
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009229static int adev_set_master_volume(struct audio_hw_device *dev __unused,
9230 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009231{
9232 return -ENOSYS;
9233}
9234
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009235static int adev_get_master_volume(struct audio_hw_device *dev __unused,
9236 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009237{
9238 return -ENOSYS;
9239}
9240
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009241static int adev_set_master_mute(struct audio_hw_device *dev __unused,
9242 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009243{
9244 return -ENOSYS;
9245}
9246
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009247static int adev_get_master_mute(struct audio_hw_device *dev __unused,
9248 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009249{
9250 return -ENOSYS;
9251}
9252
9253static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
9254{
9255 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07009256 struct listnode *node;
9257 struct audio_usecase *usecase = NULL;
9258 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08009259
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009260 pthread_mutex_lock(&adev->lock);
9261 if (adev->mode != mode) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309262 ALOGD("%s: mode %d , prev_mode %d \n", __func__, mode , adev->mode);
9263 adev->prev_mode = adev->mode; /* prev_mode is kept to handle voip concurrency*/
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009264 adev->mode = mode;
Weiyin Jiang96b96f72020-09-22 16:48:19 +08009265 if (mode == AUDIO_MODE_CALL_SCREEN) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309266 adev->current_call_output = adev->primary_output;
9267 voice_start_call(adev);
9268 } else if (voice_is_in_call_or_call_screen(adev) &&
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08009269 (mode == AUDIO_MODE_NORMAL ||
9270 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07009271 list_for_each(node, &adev->usecase_list) {
9272 usecase = node_to_item(node, struct audio_usecase, list);
9273 if (usecase->type == VOICE_CALL)
9274 break;
9275 }
9276 if (usecase &&
9277 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
9278 ret = audio_extn_usb_check_and_set_svc_int(usecase,
9279 true);
9280 if (ret != 0) {
9281 /* default service interval was successfully updated,
9282 reopen USB backend with new service interval */
9283 check_usecases_codec_backend(adev,
9284 usecase,
9285 usecase->out_snd_device);
9286 }
9287 }
9288
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009289 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07009290 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009291 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08009292 // restore device for other active usecases after stop call
9293 list_for_each(node, &adev->usecase_list) {
9294 usecase = node_to_item(node, struct audio_usecase, list);
9295 select_devices(adev, usecase->id);
9296 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009297 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009298 }
9299 pthread_mutex_unlock(&adev->lock);
9300 return 0;
9301}
9302
9303static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
9304{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009305 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08009306 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009307
9308 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08009309 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009310 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009311
Derek Chend2530072014-11-24 12:39:14 -08009312 if (adev->ext_hw_plugin)
9313 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009314
9315 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009316 pthread_mutex_unlock(&adev->lock);
9317
9318 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009319}
9320
9321static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
9322{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009323 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009324 return 0;
9325}
9326
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009327static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009328 const struct audio_config *config)
9329{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009330 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009331
Aalique Grahame22e49102018-12-18 14:23:57 -08009332 /* Don't know if USB HIFI in this context so use true to be conservative */
9333 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9334 true /*is_usb_hifi */) != 0)
9335 return 0;
9336
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009337 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
9338 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009339}
9340
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009341static bool adev_input_allow_hifi_record(struct audio_device *adev,
9342 audio_devices_t devices,
9343 audio_input_flags_t flags,
9344 audio_source_t source) {
9345 const bool allowed = true;
9346
9347 if (!audio_is_usb_in_device(devices))
9348 return !allowed;
9349
9350 switch (flags) {
9351 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009352 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07009353 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
9354 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009355 default:
9356 return !allowed;
9357 }
9358
9359 switch (source) {
9360 case AUDIO_SOURCE_DEFAULT:
9361 case AUDIO_SOURCE_MIC:
9362 case AUDIO_SOURCE_UNPROCESSED:
9363 break;
9364 default:
9365 return !allowed;
9366 }
9367
9368 switch (adev->mode) {
9369 case 0:
9370 break;
9371 default:
9372 return !allowed;
9373 }
9374
9375 return allowed;
9376}
9377
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009378static int adev_update_voice_comm_input_stream(struct stream_in *in,
9379 struct audio_config *config)
9380{
9381 bool valid_rate = (config->sample_rate == 8000 ||
9382 config->sample_rate == 16000 ||
9383 config->sample_rate == 32000 ||
9384 config->sample_rate == 48000);
9385 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
9386
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009387 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08009388 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009389 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9390 in->config = default_pcm_config_voip_copp;
9391 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
9392 DEFAULT_VOIP_BUF_DURATION_MS,
9393 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009394 } else {
9395 ALOGW("%s No valid input in voip, use defaults"
9396 "sample rate %u, channel mask 0x%X",
9397 __func__, config->sample_rate, in->channel_mask);
9398 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009399 in->config.rate = config->sample_rate;
9400 in->sample_rate = config->sample_rate;
9401 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009402 //XXX needed for voice_extn_compress_voip_open_input_stream
9403 in->config.rate = config->sample_rate;
9404 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
Shalini Manjunathaa763cc42019-08-23 15:13:46 +05309405 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009406 voice_extn_compress_voip_is_active(in->dev)) &&
9407 (voice_extn_compress_voip_is_format_supported(in->format)) &&
9408 valid_rate && valid_ch) {
9409 voice_extn_compress_voip_open_input_stream(in);
9410 // update rate entries to match config from AF
9411 in->config.rate = config->sample_rate;
9412 in->sample_rate = config->sample_rate;
9413 } else {
9414 ALOGW("%s compress voip not active, use defaults", __func__);
9415 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009416 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009417 return 0;
9418}
9419
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009420static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07009421 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009422 audio_devices_t devices,
9423 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009424 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309425 audio_input_flags_t flags,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009426 const char *address,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009427 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009428{
9429 struct audio_device *adev = (struct audio_device *)dev;
9430 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009431 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009432 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009433 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05309434 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009435 bool is_usb_dev = audio_is_usb_in_device(devices);
9436 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
9437 devices,
9438 flags,
9439 source);
Andy Hung94320602018-10-29 18:31:12 -07009440 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
9441 " sample_rate %u, channel_mask %#x, format %#x",
9442 __func__, flags, is_usb_dev, may_use_hifi_record,
9443 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309444
kunleizdff872d2018-08-20 14:40:33 +08009445 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08009446 is_usb_dev = false;
9447 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
9448 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
9449 __func__, devices);
9450 }
9451
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009452 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009453
9454 if (!(is_usb_dev && may_use_hifi_record)) {
9455 if (config->sample_rate == 0)
9456 config->sample_rate = 48000;
9457 if (config->channel_mask == AUDIO_CHANNEL_NONE)
9458 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9459 if (config->format == AUDIO_FORMAT_DEFAULT)
9460 config->format = AUDIO_FORMAT_PCM_16_BIT;
9461
9462 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
9463
Aalique Grahame22e49102018-12-18 14:23:57 -08009464 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9465 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009466 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05309467 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009468
9469 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009470
9471 if (!in) {
9472 ALOGE("failed to allocate input stream");
9473 return -ENOMEM;
9474 }
9475
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309476 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05309477 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
9478 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009479 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07009480 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009481
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009482 in->stream.common.get_sample_rate = in_get_sample_rate;
9483 in->stream.common.set_sample_rate = in_set_sample_rate;
9484 in->stream.common.get_buffer_size = in_get_buffer_size;
9485 in->stream.common.get_channels = in_get_channels;
9486 in->stream.common.get_format = in_get_format;
9487 in->stream.common.set_format = in_set_format;
9488 in->stream.common.standby = in_standby;
9489 in->stream.common.dump = in_dump;
9490 in->stream.common.set_parameters = in_set_parameters;
9491 in->stream.common.get_parameters = in_get_parameters;
9492 in->stream.common.add_audio_effect = in_add_audio_effect;
9493 in->stream.common.remove_audio_effect = in_remove_audio_effect;
9494 in->stream.set_gain = in_set_gain;
9495 in->stream.read = in_read;
9496 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08009497 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309498 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07009499 in->stream.set_microphone_direction = in_set_microphone_direction;
9500 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07009501 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009502
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009503 list_init(&in->device_list);
9504 update_device_list(&in->device_list, devices, address, true);
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009505 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009506 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009507 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009508 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009509 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07009510 in->bit_width = 16;
9511 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07009512 in->direction = MIC_DIRECTION_UNSPECIFIED;
9513 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08009514 list_init(&in->aec_list);
9515 list_init(&in->ns_list);
Phil Burkd898ba62019-06-20 12:49:01 -07009516 in->mmap_shared_memory_fd = -1; // not open
Haynes Mathew George46740472017-10-27 18:40:12 -07009517
Andy Hung94320602018-10-29 18:31:12 -07009518 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08009519 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
9520 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
9521 /* Force channel config requested to mono if incall
9522 record is being requested for only uplink/downlink */
9523 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
9524 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9525 ret = -EINVAL;
9526 goto err_open;
9527 }
9528 }
9529
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009530 if (is_usb_dev && may_use_hifi_record) {
9531 /* HiFi record selects an appropriate format, channel, rate combo
9532 depending on sink capabilities*/
9533 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
9534 &config->format,
9535 &in->supported_formats[0],
9536 MAX_SUPPORTED_FORMATS,
9537 &config->channel_mask,
9538 &in->supported_channel_masks[0],
9539 MAX_SUPPORTED_CHANNEL_MASKS,
9540 &config->sample_rate,
9541 &in->supported_sample_rates[0],
9542 MAX_SUPPORTED_SAMPLE_RATES);
9543 if (ret != 0) {
9544 ret = -EINVAL;
9545 goto err_open;
9546 }
9547 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009548 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309549 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05309550 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
9551 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
9552 in->config.format = PCM_FORMAT_S32_LE;
9553 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309554 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
9555 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
9556 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
9557 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
9558 bool ret_error = false;
9559 in->bit_width = 24;
9560 /* 24 bit is restricted to UNPROCESSED source only,also format supported
9561 from HAL is 24_packed and 8_24
9562 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
9563 24_packed return error indicating supported format is 24_packed
9564 *> In case of any other source requesting 24 bit or float return error
9565 indicating format supported is 16 bit only.
9566
9567 on error flinger will retry with supported format passed
9568 */
9569 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
9570 (source != AUDIO_SOURCE_CAMCORDER)) {
9571 config->format = AUDIO_FORMAT_PCM_16_BIT;
9572 if (config->sample_rate > 48000)
9573 config->sample_rate = 48000;
9574 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07009575 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
9576 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309577 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
9578 ret_error = true;
9579 }
9580
9581 if (ret_error) {
9582 ret = -EINVAL;
9583 goto err_open;
9584 }
9585 }
9586
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009587 in->channel_mask = config->channel_mask;
9588 in->format = config->format;
9589
9590 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309591
Huicheng Liu1404ba12020-09-11 01:03:25 -04009592 /* validate bus device address */
9593 if (compare_device_type(&in->device_list, AUDIO_DEVICE_IN_BUS)) {
9594 /* extract car audio stream index */
9595 in->car_audio_stream =
9596 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
9597 if (in->car_audio_stream < 0) {
9598 ALOGE("%s: invalid car audio stream %x",
9599 __func__, in->car_audio_stream);
9600 ret = -EINVAL;
9601 goto err_open;
9602 }
9603 ALOGV("%s: car_audio_stream 0x%x", __func__, in->car_audio_stream);
Huicheng Liuea4fd422021-01-12 18:34:50 -05009604 ret = audio_extn_auto_hal_open_input_stream(in);
9605 if (ret) {
9606 ALOGE("%s: Failed to open input stream for bus device", __func__);
9607 ret = -EINVAL;
9608 goto err_open;
9609 }
Huicheng Liu1404ba12020-09-11 01:03:25 -04009610 }
9611
Susan Wange3959562021-03-11 11:50:26 -05009612 /* reassign use case for echo reference stream on automotive platforms */
9613 if (in->source == AUDIO_SOURCE_ECHO_REFERENCE) {
9614 ret = audio_extn_auto_hal_open_echo_reference_stream(in);
9615 }
9616
Kogara Naveen Kumar379ff692022-01-31 11:56:51 +05309617 if ((in->source == AUDIO_SOURCE_FM_TUNER) || (devices == AUDIO_DEVICE_IN_FM_TUNER)) {
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309618 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
9619 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
9620 else {
9621 ret = -EINVAL;
9622 goto err_open;
9623 }
9624 }
9625
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009626 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Deeraj Somanfa377bf2019-02-06 12:57:59 +05309627 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
9628 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009629 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
9630 is_low_latency = true;
9631#if LOW_LATENCY_CAPTURE_USE_CASE
Revathi Uddarajud9f23d92020-07-27 10:55:06 +05309632 if ((flags & AUDIO_INPUT_FLAG_VOIP_TX) != 0)
9633 in->usecase = USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY;
9634 else
9635 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009636#endif
9637 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08009638 if (!in->realtime) {
9639 in->config = pcm_config_audio_capture;
9640 frame_size = audio_stream_in_frame_size(&in->stream);
9641 buffer_size = get_input_buffer_size(config->sample_rate,
9642 config->format,
9643 channel_count,
9644 is_low_latency);
9645 in->config.period_size = buffer_size / frame_size;
9646 in->config.rate = config->sample_rate;
9647 in->af_period_multiplier = 1;
9648 } else {
9649 // period size is left untouched for rt mode playback
9650 in->config = pcm_config_audio_capture_rt;
9651 in->af_period_multiplier = af_period_multiplier;
9652 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009653 }
9654
Susan Wangb803cb52021-10-14 12:03:36 -04009655 /* Additional sample rates added below must also be present
9656 in audio_policy_configuration.xml for mmap_no_irq_in */
9657 bool valid_mmap_record_rate = (config->sample_rate == 8000 ||
9658 config->sample_rate == 16000 ||
Susan Wang89da9042021-10-14 12:03:36 -04009659 config->sample_rate == 24000 ||
Susan Wangb803cb52021-10-14 12:03:36 -04009660 config->sample_rate == 32000 ||
9661 config->sample_rate == 48000);
9662 if (valid_mmap_record_rate &&
9663 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009664 in->realtime = 0;
9665 in->usecase = USECASE_AUDIO_RECORD_MMAP;
9666 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07009667 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009668 in->stream.start = in_start;
9669 in->stream.stop = in_stop;
9670 in->stream.create_mmap_buffer = in_create_mmap_buffer;
9671 in->stream.get_mmap_position = in_get_mmap_position;
Ramjee Singhbcb3b6c2021-11-17 13:19:16 +05309672 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009673 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
Haynes Mathew George46740472017-10-27 18:40:12 -07009674 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009675 in->usecase = USECASE_AUDIO_RECORD_HIFI;
9676 in->config = pcm_config_audio_capture;
9677 frame_size = audio_stream_in_frame_size(&in->stream);
9678 buffer_size = get_input_buffer_size(config->sample_rate,
9679 config->format,
9680 channel_count,
9681 false /*is_low_latency*/);
9682 in->config.period_size = buffer_size / frame_size;
9683 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009684 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07009685 switch (config->format) {
9686 case AUDIO_FORMAT_PCM_32_BIT:
9687 in->bit_width = 32;
9688 break;
9689 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
9690 case AUDIO_FORMAT_PCM_8_24_BIT:
9691 in->bit_width = 24;
9692 break;
9693 default:
9694 in->bit_width = 16;
9695 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009696 } else if (is_single_device_type_equal(&in->device_list,
9697 AUDIO_DEVICE_IN_TELEPHONY_RX) ||
9698 is_single_device_type_equal(&in->device_list,
9699 AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009700 if (config->sample_rate == 0)
9701 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9702 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
9703 config->sample_rate != 8000) {
9704 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9705 ret = -EINVAL;
9706 goto err_open;
9707 }
9708 if (config->format == AUDIO_FORMAT_DEFAULT)
9709 config->format = AUDIO_FORMAT_PCM_16_BIT;
9710 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
9711 config->format = AUDIO_FORMAT_PCM_16_BIT;
9712 ret = -EINVAL;
9713 goto err_open;
9714 }
9715
9716 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
Zhou Song62ea0282020-03-22 19:53:01 +08009717 if (adev->ha_proxy_enable &&
9718 is_single_device_type_equal(&in->device_list,
9719 AUDIO_DEVICE_IN_TELEPHONY_RX))
9720 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY2;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009721 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009722 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08009723 in->af_period_multiplier = 1;
9724 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
Shalini Manjunathaac412b32020-01-03 15:00:14 +05309725 (!voice_extn_is_compress_voip_supported()) &&
Aalique Grahame22e49102018-12-18 14:23:57 -08009726 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
9727 (config->sample_rate == 8000 ||
9728 config->sample_rate == 16000 ||
9729 config->sample_rate == 32000 ||
9730 config->sample_rate == 48000) &&
9731 channel_count == 1) {
9732 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9733 in->config = pcm_config_audio_capture;
9734 frame_size = audio_stream_in_frame_size(&in->stream);
9735 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
9736 config->sample_rate,
9737 config->format,
9738 channel_count, false /*is_low_latency*/);
9739 in->config.period_size = buffer_size / frame_size;
9740 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
9741 in->config.rate = config->sample_rate;
9742 in->af_period_multiplier = 1;
Mingshu Pangc2d65042021-01-14 16:19:10 +08009743 } else if (in->realtime) {
9744 in->config = pcm_config_audio_capture_rt;
9745 in->config.format = pcm_format_from_audio_format(config->format);
9746 in->af_period_multiplier = af_period_multiplier;
Haynes Mathew George46740472017-10-27 18:40:12 -07009747 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05309748 int ret_val;
9749 pthread_mutex_lock(&adev->lock);
9750 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
9751 in, config, &channel_mask_updated);
9752 pthread_mutex_unlock(&adev->lock);
9753
9754 if (!ret_val) {
9755 if (channel_mask_updated == true) {
9756 ALOGD("%s: return error to retry with updated channel mask (%#x)",
9757 __func__, config->channel_mask);
9758 ret = -EINVAL;
9759 goto err_open;
9760 }
9761 ALOGD("%s: created multi-channel session succesfully",__func__);
9762 } else if (audio_extn_compr_cap_enabled() &&
9763 audio_extn_compr_cap_format_supported(config->format) &&
9764 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
9765 audio_extn_compr_cap_init(in);
9766 } else if (audio_extn_cin_applicable_stream(in)) {
Deeraj Soman14230922019-01-30 16:39:30 +05309767 ret = audio_extn_cin_configure_input_stream(in, config);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309768 if (ret)
9769 goto err_open;
9770 } else {
9771 in->config = pcm_config_audio_capture;
9772 in->config.rate = config->sample_rate;
9773 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309774 in->format = config->format;
9775 frame_size = audio_stream_in_frame_size(&in->stream);
9776 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07009777 config->format,
9778 channel_count,
9779 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02009780 /* prevent division-by-zero */
9781 if (frame_size == 0) {
9782 ALOGE("%s: Error frame_size==0", __func__);
9783 ret = -EINVAL;
9784 goto err_open;
9785 }
9786
Revathi Uddarajud2634032017-12-07 14:42:34 +05309787 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08009788 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009789
Revathi Uddarajud2634032017-12-07 14:42:34 +05309790 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9791 /* optionally use VOIP usecase depending on config(s) */
9792 ret = adev_update_voice_comm_input_stream(in, config);
9793 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009794
Revathi Uddarajud2634032017-12-07 14:42:34 +05309795 if (ret) {
9796 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
9797 goto err_open;
9798 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009799 }
Jaideep Sharmad305a4a2020-02-27 14:29:04 +05309800
9801 /* assign concurrent capture usecase if record has to caried out from
9802 * actual hardware input source */
9803 if (audio_extn_is_concurrent_capture_enabled() &&
9804 !audio_is_virtual_input_source(in->source)) {
Samyak Jainc37062f2019-04-25 18:41:06 +05309805 /* Acquire lock to avoid two concurrent use cases initialized to
9806 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +08009807
Samyak Jainc37062f2019-04-25 18:41:06 +05309808 if (in->usecase == USECASE_AUDIO_RECORD) {
9809 pthread_mutex_lock(&adev->lock);
9810 if (!(adev->pcm_record_uc_state)) {
9811 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
9812 adev->pcm_record_uc_state = 1;
9813 pthread_mutex_unlock(&adev->lock);
9814 } else {
9815 pthread_mutex_unlock(&adev->lock);
9816 /* Assign compress record use case for second record */
9817 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
9818 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
9819 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
9820 if (audio_extn_cin_applicable_stream(in)) {
9821 in->sample_rate = config->sample_rate;
Deeraj Soman14230922019-01-30 16:39:30 +05309822 ret = audio_extn_cin_configure_input_stream(in, config);
Samyak Jainc37062f2019-04-25 18:41:06 +05309823 if (ret)
9824 goto err_open;
9825 }
9826 }
9827 }
kunleiz28c73e72019-03-27 17:24:04 +08009828 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009829 }
Ramjee Singh82fd0c12019-08-21 16:31:33 +05309830 if (audio_extn_ssr_get_stream() != in)
9831 in->config.channels = channel_count;
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009832
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009833 in->sample_rate = in->config.rate;
9834
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309835 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
9836 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009837 &in->device_list, flags, in->format,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009838 in->sample_rate, in->bit_width,
9839 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05309840 register_format(in->format, in->supported_formats);
9841 register_channel_mask(in->channel_mask, in->supported_channel_masks);
9842 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309843
Dechen Chai22768452021-07-30 09:29:16 +05309844#ifndef LINUX_ENABLED
Aalique Grahame22e49102018-12-18 14:23:57 -08009845 in->error_log = error_log_create(
9846 ERROR_LOG_ENTRIES,
9847 1000000000 /* aggregate consecutive identical errors within one second */);
Dechen Chai22768452021-07-30 09:29:16 +05309848#endif
Aalique Grahame22e49102018-12-18 14:23:57 -08009849
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009850 /* This stream could be for sound trigger lab,
9851 get sound trigger pcm if present */
9852 audio_extn_sound_trigger_check_and_get_session(in);
9853
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309854 lock_input_stream(in);
9855 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
9856 pthread_mutex_lock(&adev->lock);
9857 in->card_status = adev->card_status;
9858 pthread_mutex_unlock(&adev->lock);
9859 pthread_mutex_unlock(&in->lock);
9860
Aalique Grahame22e49102018-12-18 14:23:57 -08009861 stream_app_type_cfg_init(&in->app_type_cfg);
9862
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009863 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -08009864
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009865 ret = io_streams_map_insert(adev, &in->stream.common,
9866 handle, AUDIO_PATCH_HANDLE_NONE);
9867 if (ret != 0)
9868 goto err_open;
9869
Susan Wang6dd13092021-01-25 10:27:11 -05009870 in->in_ctxt.input = in;
Derek Chenf939fb72018-11-13 13:34:41 -08009871
9872 pthread_mutex_lock(&adev->lock);
Susan Wang6dd13092021-01-25 10:27:11 -05009873 list_add_tail(&adev->active_inputs_list, &in->in_ctxt.list);
Derek Chenf939fb72018-11-13 13:34:41 -08009874 pthread_mutex_unlock(&adev->lock);
9875
Eric Laurent994a6932013-07-17 11:51:42 -07009876 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009877 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009878
9879err_open:
Samyak Jainc37062f2019-04-25 18:41:06 +05309880 if (in->usecase == USECASE_AUDIO_RECORD) {
9881 pthread_mutex_lock(&adev->lock);
9882 adev->pcm_record_uc_state = 0;
9883 pthread_mutex_unlock(&adev->lock);
9884 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009885 free(in);
9886 *stream_in = NULL;
9887 return ret;
9888}
9889
9890static void adev_close_input_stream(struct audio_hw_device *dev,
9891 struct audio_stream_in *stream)
9892{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009893 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009894 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009895 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309896
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309897 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08009898
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009899 if (in == NULL) {
9900 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
9901 return;
9902 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009903 io_streams_map_remove(adev, in->capture_handle);
9904
Susan Wang6dd13092021-01-25 10:27:11 -05009905 // remove out_ctxt early to prevent the stream
9906 // being opened in a race condition
9907 pthread_mutex_lock(&adev->lock);
9908 list_remove(&in->in_ctxt.list);
9909 pthread_mutex_unlock(&adev->lock);
9910
kunleiz70e57612018-12-28 17:50:23 +08009911 /* must deregister from sndmonitor first to prevent races
9912 * between the callback and close_stream
9913 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309914 audio_extn_snd_mon_unregister_listener(stream);
9915
kunleiz70e57612018-12-28 17:50:23 +08009916 /* Disable echo reference if there are no active input, hfp call
9917 * and sound trigger while closing input stream
9918 */
Eric Laurent637e2d42018-11-15 12:24:31 -08009919 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +08009920 !audio_extn_hfp_is_active(adev) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009921 !audio_extn_sound_trigger_check_ec_ref_enable()) {
9922 struct listnode out_devices;
9923 list_init(&out_devices);
9924 platform_set_echo_reference(adev, false, &out_devices);
9925 } else
kunleiz70e57612018-12-28 17:50:23 +08009926 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05309927
Dechen Chai22768452021-07-30 09:29:16 +05309928#ifndef LINUX_ENABLED
Weiyin Jiang2995f662019-04-17 14:25:12 +08009929 error_log_destroy(in->error_log);
9930 in->error_log = NULL;
Dechen Chai22768452021-07-30 09:29:16 +05309931#endif
Pallavid7c7a272018-01-16 11:22:55 +05309932
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009933 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309934 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009935 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309936 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009937 if (ret != 0)
9938 ALOGE("%s: Compress voip input cannot be closed, error:%d",
9939 __func__, ret);
9940 } else
9941 in_standby(&stream->common);
9942
Weiyin Jiang280ea742020-09-08 20:28:22 +08009943 pthread_mutex_destroy(&in->lock);
9944 pthread_mutex_destroy(&in->pre_lock);
9945
Revathi Uddarajud2634032017-12-07 14:42:34 +05309946 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05309947 if (in->usecase == USECASE_AUDIO_RECORD) {
9948 adev->pcm_record_uc_state = 0;
9949 }
9950
Kunlei Zhang5d5d8d92020-02-26 15:00:59 +08009951 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9952 adev->enable_voicerx = false;
9953 }
9954
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07009955 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009956 audio_extn_ssr_deinit();
9957 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009958
Garmond Leunge2433c32017-09-28 21:51:22 -07009959 if (audio_extn_ffv_get_stream() == in) {
9960 audio_extn_ffv_stream_deinit();
9961 }
9962
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309963 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07009964 audio_extn_compr_cap_format_supported(in->config.format))
9965 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05309966
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05309967 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05309968 audio_extn_cin_free_input_stream_resources(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009969
Mingming Yinfd7607b2016-01-22 12:48:44 -08009970 if (in->is_st_session) {
9971 ALOGV("%s: sound trigger pcm stop lab", __func__);
9972 audio_extn_sound_trigger_stop_lab(in);
9973 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009974 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309975 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009976 return;
9977}
9978
Aalique Grahame22e49102018-12-18 14:23:57 -08009979/* verifies input and output devices and their capabilities.
9980 *
9981 * This verification is required when enabling extended bit-depth or
9982 * sampling rates, as not all qcom products support it.
9983 *
9984 * Suitable for calling only on initialization such as adev_open().
9985 * It fills the audio_device use_case_table[] array.
9986 *
9987 * Has a side-effect that it needs to configure audio routing / devices
9988 * in order to power up the devices and read the device parameters.
9989 * It does not acquire any hw device lock. Should restore the devices
9990 * back to "normal state" upon completion.
9991 */
9992static int adev_verify_devices(struct audio_device *adev)
9993{
9994 /* enumeration is a bit difficult because one really wants to pull
9995 * the use_case, device id, etc from the hidden pcm_device_table[].
9996 * In this case there are the following use cases and device ids.
9997 *
9998 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
9999 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
10000 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
10001 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
10002 * [USECASE_AUDIO_RECORD] = {0, 0},
10003 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
10004 * [USECASE_VOICE_CALL] = {2, 2},
10005 *
10006 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
10007 * USECASE_VOICE_CALL omitted, but possible for either input or output.
10008 */
10009
10010 /* should be the usecases enabled in adev_open_input_stream() */
10011 static const int test_in_usecases[] = {
10012 USECASE_AUDIO_RECORD,
10013 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
10014 };
10015 /* should be the usecases enabled in adev_open_output_stream()*/
10016 static const int test_out_usecases[] = {
10017 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
10018 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
10019 };
10020 static const usecase_type_t usecase_type_by_dir[] = {
10021 PCM_PLAYBACK,
10022 PCM_CAPTURE,
10023 };
10024 static const unsigned flags_by_dir[] = {
10025 PCM_OUT,
10026 PCM_IN,
10027 };
10028
10029 size_t i;
10030 unsigned dir;
10031 const unsigned card_id = adev->snd_card;
10032
10033 for (dir = 0; dir < 2; ++dir) {
10034 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
10035 const unsigned flags_dir = flags_by_dir[dir];
10036 const size_t testsize =
10037 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
10038 const int *testcases =
10039 dir ? test_in_usecases : test_out_usecases;
10040 const audio_devices_t audio_device =
10041 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
10042
10043 for (i = 0; i < testsize; ++i) {
10044 const audio_usecase_t audio_usecase = testcases[i];
10045 int device_id;
10046 struct pcm_params **pparams;
10047 struct stream_out out;
10048 struct stream_in in;
10049 struct audio_usecase uc_info;
10050 int retval;
10051
10052 pparams = &adev->use_case_table[audio_usecase];
10053 pcm_params_free(*pparams); /* can accept null input */
10054 *pparams = NULL;
10055
10056 /* find the device ID for the use case (signed, for error) */
10057 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
10058 if (device_id < 0)
10059 continue;
10060
10061 /* prepare structures for device probing */
10062 memset(&uc_info, 0, sizeof(uc_info));
10063 uc_info.id = audio_usecase;
10064 uc_info.type = usecase_type;
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010065 list_init(&uc_info.device_list);
Aalique Grahame22e49102018-12-18 14:23:57 -080010066 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -080010067 memset(&in, 0, sizeof(in));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010068 list_init(&in.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010069 update_device_list(&in.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -080010070 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
10071 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -080010072 }
10073 memset(&out, 0, sizeof(out));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010074 list_init(&out.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010075 update_device_list(&out.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -080010076 uc_info.stream.out = &out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010077 update_device_list(&uc_info.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -080010078 uc_info.in_snd_device = SND_DEVICE_NONE;
10079 uc_info.out_snd_device = SND_DEVICE_NONE;
10080 list_add_tail(&adev->usecase_list, &uc_info.list);
10081
10082 /* select device - similar to start_(in/out)put_stream() */
10083 retval = select_devices(adev, audio_usecase);
10084 if (retval >= 0) {
10085 *pparams = pcm_params_get(card_id, device_id, flags_dir);
10086#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -070010087 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -080010088 if (*pparams) {
10089 ALOGV("%s: (%s) card %d device %d", __func__,
10090 dir ? "input" : "output", card_id, device_id);
10091 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
10092 } else {
10093 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
10094 }
10095#endif
10096 }
10097
10098 /* deselect device - similar to stop_(in/out)put_stream() */
10099 /* 1. Get and set stream specific mixer controls */
10100 retval = disable_audio_route(adev, &uc_info);
10101 /* 2. Disable the rx device */
10102 retval = disable_snd_device(adev,
10103 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
10104 list_remove(&uc_info.list);
10105 }
10106 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010107 return 0;
10108}
10109
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010110int update_patch(unsigned int num_sources,
10111 const struct audio_port_config *sources,
10112 unsigned int num_sinks,
10113 const struct audio_port_config *sinks,
10114 audio_patch_handle_t handle,
10115 struct audio_patch_info *p_info,
10116 patch_type_t patch_type, bool new_patch)
10117{
Aniket Kumar Latad13758f2020-08-06 15:11:36 -070010118 ALOGV("%s: enter", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010119
10120 if (p_info == NULL) {
10121 ALOGE("%s: Invalid patch pointer", __func__);
10122 return -EINVAL;
10123 }
10124
10125 if (new_patch) {
10126 p_info->patch = (struct audio_patch *) calloc(1, sizeof(struct audio_patch));
10127 if (p_info->patch == NULL) {
10128 ALOGE("%s: Could not allocate patch", __func__);
10129 return -ENOMEM;
10130 }
10131 }
10132
10133 p_info->patch->id = handle;
10134 p_info->patch->num_sources = num_sources;
10135 p_info->patch->num_sinks = num_sinks;
10136
10137 for (int i = 0; i < num_sources; i++)
10138 p_info->patch->sources[i] = sources[i];
10139 for (int i = 0; i < num_sinks; i++)
10140 p_info->patch->sinks[i] = sinks[i];
10141
10142 p_info->patch_type = patch_type;
10143 return 0;
10144}
10145
10146audio_patch_handle_t generate_patch_handle()
10147{
10148 static audio_patch_handle_t patch_handle = AUDIO_PATCH_HANDLE_NONE;
10149 if (++patch_handle < 0)
10150 patch_handle = AUDIO_PATCH_HANDLE_NONE + 1;
10151 return patch_handle;
10152}
10153
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010154int adev_create_audio_patch(struct audio_hw_device *dev,
10155 unsigned int num_sources,
10156 const struct audio_port_config *sources,
10157 unsigned int num_sinks,
10158 const struct audio_port_config *sinks,
10159 audio_patch_handle_t *handle)
10160{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010161 int ret = 0;
10162 struct audio_device *adev = (struct audio_device *)dev;
10163 struct audio_patch_info *p_info = NULL;
10164 patch_type_t patch_type = PATCH_NONE;
10165 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10166 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
10167 struct audio_stream_info *s_info = NULL;
10168 struct audio_stream *stream = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010169 struct listnode devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010170 audio_devices_t device_type = AUDIO_DEVICE_NONE;
10171 bool new_patch = false;
10172 char addr[AUDIO_DEVICE_MAX_ADDRESS_LEN];
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010173
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010174 ALOGD("%s: enter: num sources %d, num_sinks %d, handle %d", __func__,
10175 num_sources, num_sinks, *handle);
10176
10177 if (num_sources == 0 || num_sources > AUDIO_PATCH_PORTS_MAX ||
10178 num_sinks == 0 || num_sinks > AUDIO_PATCH_PORTS_MAX) {
10179 ALOGE("%s: Invalid patch arguments", __func__);
10180 ret = -EINVAL;
10181 goto done;
10182 }
10183
10184 if (num_sources > 1) {
10185 ALOGE("%s: Multiple sources are not supported", __func__);
10186 ret = -EINVAL;
10187 goto done;
10188 }
10189
10190 if (sources == NULL || sinks == NULL) {
10191 ALOGE("%s: Invalid sources or sinks port config", __func__);
10192 ret = -EINVAL;
10193 goto done;
10194 }
10195
10196 ALOGV("%s: source role %d, source type %d", __func__,
10197 sources[0].type, sources[0].role);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010198 list_init(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010199
10200 // Populate source/sink information and fetch stream info
10201 switch (sources[0].type) {
10202 case AUDIO_PORT_TYPE_DEVICE: // Patch for audio capture or loopback
10203 device_type = sources[0].ext.device.type;
10204 strlcpy(&addr[0], &sources[0].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010205 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010206 if (sinks[0].type == AUDIO_PORT_TYPE_MIX) {
10207 patch_type = PATCH_CAPTURE;
10208 io_handle = sinks[0].ext.mix.handle;
10209 input_source = sinks[0].ext.mix.usecase.source;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010210 ALOGD("%s: Capture patch from device %x to mix %d",
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010211 __func__, device_type, io_handle);
10212 } else {
10213 // Device to device patch is not implemented.
10214 // This space will need changes if audio HAL
10215 // handles device to device patches in the future.
10216 patch_type = PATCH_DEVICE_LOOPBACK;
10217 }
10218 break;
10219 case AUDIO_PORT_TYPE_MIX: // Patch for audio playback
10220 io_handle = sources[0].ext.mix.handle;
10221 for (int i = 0; i < num_sinks; i++) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010222 device_type = sinks[i].ext.device.type;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010223 strlcpy(&addr[0], &sinks[i].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010224 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010225 }
10226 patch_type = PATCH_PLAYBACK;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010227 ALOGD("%s: Playback patch from mix handle %d to device %x",
10228 __func__, io_handle, get_device_types(&devices));
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010229 break;
10230 case AUDIO_PORT_TYPE_SESSION:
10231 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010232 ALOGE("%s: Unsupported source type %d", __func__, sources[0].type);
10233 ret = -EINVAL;
10234 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010235 }
10236
10237 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010238
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010239 // Generate patch info and update patch
10240 if (*handle == AUDIO_PATCH_HANDLE_NONE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010241 *handle = generate_patch_handle();
10242 p_info = (struct audio_patch_info *)
10243 calloc(1, sizeof(struct audio_patch_info));
10244 if (p_info == NULL) {
10245 ALOGE("%s: Failed to allocate memory", __func__);
10246 pthread_mutex_unlock(&adev->lock);
10247 ret = -ENOMEM;
10248 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010249 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010250 new_patch = true;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010251 } else {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010252 p_info = fetch_patch_info_l(adev, *handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010253 if (p_info == NULL) {
10254 ALOGE("%s: Unable to fetch patch for received patch handle %d",
10255 __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010256 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010257 ret = -EINVAL;
10258 goto done;
10259 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010260 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010261 update_patch(num_sources, sources, num_sinks, sinks,
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010262 *handle, p_info, patch_type, new_patch);
10263
10264 // Fetch stream info of associated mix for playback or capture patches
10265 if (p_info->patch_type == PATCH_PLAYBACK ||
10266 p_info->patch_type == PATCH_CAPTURE) {
10267 s_info = hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10268 if (s_info == NULL) {
10269 ALOGE("%s: Failed to obtain stream info", __func__);
10270 if (new_patch)
10271 free(p_info);
10272 pthread_mutex_unlock(&adev->lock);
10273 ret = -EINVAL;
10274 goto done;
10275 }
10276 ALOGV("%s: Fetched stream info with io_handle %d", __func__, io_handle);
10277 s_info->patch_handle = *handle;
10278 stream = s_info->stream;
10279 }
10280 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010281
10282 // Update routing for stream
10283 if (stream != NULL) {
Revathi Uddaraju4255a632021-12-02 05:11:13 -080010284 if (p_info->patch_type == PATCH_PLAYBACK) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010285 ret = route_output_stream((struct stream_out *) stream, &devices);
Revathi Uddaraju4255a632021-12-02 05:11:13 -080010286 clear_devices(&devices);
10287 } else if (p_info->patch_type == PATCH_CAPTURE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010288 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Revathi Uddaraju4255a632021-12-02 05:11:13 -080010289 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010290 if (ret < 0) {
10291 pthread_mutex_lock(&adev->lock);
10292 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10293 if (new_patch)
10294 free(p_info);
10295 pthread_mutex_unlock(&adev->lock);
10296 ALOGE("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10297 goto done;
10298 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010299 }
10300
10301 // Add new patch to patch map
10302 if (!ret && new_patch) {
10303 pthread_mutex_lock(&adev->lock);
10304 hashmapPut(adev->patch_map, (void *) (intptr_t) *handle, (void *) p_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010305 ALOGD("%s: Added a new patch with handle %d", __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010306 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010307 }
10308
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010309done:
10310 audio_extn_hw_loopback_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010311 num_sources,
10312 sources,
10313 num_sinks,
10314 sinks,
10315 handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010316 audio_extn_auto_hal_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010317 num_sources,
10318 sources,
10319 num_sinks,
10320 sinks,
10321 handle);
10322 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010323}
10324
10325int adev_release_audio_patch(struct audio_hw_device *dev,
10326 audio_patch_handle_t handle)
10327{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010328 struct audio_device *adev = (struct audio_device *) dev;
10329 int ret = 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010330 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010331 struct audio_stream *stream = NULL;
Derek Chenf939fb72018-11-13 13:34:41 -080010332
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010333 if (handle == AUDIO_PATCH_HANDLE_NONE) {
10334 ALOGE("%s: Invalid patch handle %d", __func__, handle);
10335 ret = -EINVAL;
10336 goto done;
10337 }
10338
10339 ALOGD("%s: Remove patch with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010340 pthread_mutex_lock(&adev->lock);
10341 struct audio_patch_info *p_info = fetch_patch_info_l(adev, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010342 if (p_info == NULL) {
10343 ALOGE("%s: Patch info not found with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010344 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010345 ret = -EINVAL;
10346 goto done;
10347 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010348 struct audio_patch *patch = p_info->patch;
10349 if (patch == NULL) {
10350 ALOGE("%s: Patch not found for handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010351 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010352 ret = -EINVAL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010353 goto done;
10354 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010355 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10356 switch (patch->sources[0].type) {
10357 case AUDIO_PORT_TYPE_MIX:
10358 io_handle = patch->sources[0].ext.mix.handle;
10359 break;
10360 case AUDIO_PORT_TYPE_DEVICE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010361 if (p_info->patch_type == PATCH_CAPTURE)
10362 io_handle = patch->sinks[0].ext.mix.handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010363 break;
10364 case AUDIO_PORT_TYPE_SESSION:
10365 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010366 pthread_mutex_unlock(&adev->lock);
10367 ret = -EINVAL;
10368 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010369 }
10370
10371 // Remove patch and reset patch handle in stream info
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010372 patch_type_t patch_type = p_info->patch_type;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010373 patch_map_remove_l(adev, handle);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010374 if (patch_type == PATCH_PLAYBACK ||
10375 patch_type == PATCH_CAPTURE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010376 struct audio_stream_info *s_info =
10377 hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10378 if (s_info == NULL) {
10379 ALOGE("%s: stream for io_handle %d is not available", __func__, io_handle);
10380 pthread_mutex_unlock(&adev->lock);
10381 goto done;
10382 }
10383 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10384 stream = s_info->stream;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010385 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010386 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010387
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010388 if (stream != NULL) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010389 struct listnode devices;
10390 list_init(&devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010391 if (patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010392 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010393 else if (patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010394 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010395 }
10396
10397 if (ret < 0)
10398 ALOGW("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10399
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010400done:
10401 audio_extn_hw_loopback_release_audio_patch(dev, handle);
10402 audio_extn_auto_hal_release_audio_patch(dev, handle);
10403
10404 ALOGV("%s: Successfully released patch %d", __func__, handle);
Derek Chenf939fb72018-11-13 13:34:41 -080010405 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010406}
10407
10408int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
10409{
Derek Chenf13dd492018-11-13 14:53:51 -080010410 int ret = 0;
10411
10412 ret = audio_extn_hw_loopback_get_audio_port(dev, config);
10413 ret |= audio_extn_auto_hal_get_audio_port(dev, config);
10414 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010415}
10416
10417int adev_set_audio_port_config(struct audio_hw_device *dev,
10418 const struct audio_port_config *config)
10419{
Derek Chenf13dd492018-11-13 14:53:51 -080010420 int ret = 0;
10421
10422 ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
10423 ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
10424 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010425}
10426
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -070010427static int adev_dump(const audio_hw_device_t *device __unused,
10428 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010429{
10430 return 0;
10431}
10432
10433static int adev_close(hw_device_t *device)
10434{
Aalique Grahame22e49102018-12-18 14:23:57 -080010435 size_t i;
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010436 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -070010437
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010438 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -070010439 return 0;
10440
10441 pthread_mutex_lock(&adev_init_lock);
10442
10443 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +053010444 if (audio_extn_spkr_prot_is_enabled())
10445 audio_extn_spkr_prot_deinit();
Jaideep Sharmaa2b49672019-09-10 20:37:03 +053010446 audio_extn_battery_properties_listener_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010447 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010448 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -080010449 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010450 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -080010451 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010452 audio_extn_utils_release_streams_cfg_lists(
10453 &adev->streams_output_cfg_list,
10454 &adev->streams_input_cfg_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010455 if (audio_extn_qap_is_enabled())
10456 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010457 if (audio_extn_qaf_is_enabled())
10458 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -070010459 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +080010460 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -070010461 free(adev->snd_dev_ref_cnt);
10462 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010463 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
10464 pcm_params_free(adev->use_case_table[i]);
10465 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010466 if (adev->adm_deinit)
10467 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010468 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010469 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010470 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010471 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010472 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010473 if (adev->device_cfg_params) {
10474 free(adev->device_cfg_params);
10475 adev->device_cfg_params = NULL;
10476 }
Derek Chend2530072014-11-24 12:39:14 -080010477 if(adev->ext_hw_plugin)
10478 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -080010479 audio_extn_auto_hal_deinit();
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010480 free_map(adev->patch_map);
10481 free_map(adev->io_streams_map);
Kiran Kandi910e1862013-10-29 13:29:42 -070010482 free(device);
10483 adev = NULL;
10484 }
10485 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +053010486 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010487 return 0;
10488}
10489
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010490/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
10491 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
10492 * just that it _might_ work.
10493 */
10494static int period_size_is_plausible_for_low_latency(int period_size)
10495{
10496 switch (period_size) {
10497 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -070010498 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010499 case 240:
10500 case 320:
10501 case 480:
10502 return 1;
10503 default:
10504 return 0;
10505 }
10506}
10507
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010508static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
10509{
10510 bool is_snd_card_status = false;
10511 bool is_ext_device_status = false;
10512 char value[32];
10513 int card = -1;
10514 card_status_t status;
10515
10516 if (cookie != adev || !parms)
10517 return;
10518
10519 if (!parse_snd_card_status(parms, &card, &status)) {
10520 is_snd_card_status = true;
10521 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
10522 is_ext_device_status = true;
10523 } else {
10524 // not a valid event
10525 return;
10526 }
10527
10528 pthread_mutex_lock(&adev->lock);
10529 if (card == adev->snd_card || is_ext_device_status) {
10530 if (is_snd_card_status && adev->card_status != status) {
Jaideep Sharmacb402512020-09-24 17:51:07 +053010531 ALOGD("%s card_status %d", __func__, status);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010532 adev->card_status = status;
10533 platform_snd_card_update(adev->platform, status);
10534 audio_extn_fm_set_parameters(adev, parms);
Derek Chend6f371d2019-03-01 13:45:58 -080010535 audio_extn_auto_hal_set_parameters(adev, parms);
Zhou Song4f43e352019-07-02 00:32:23 +080010536 if (status == CARD_STATUS_OFFLINE)
10537 audio_extn_sco_reset_configuration();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010538 } else if (is_ext_device_status) {
10539 platform_set_parameters(adev->platform, parms);
10540 }
10541 }
10542 pthread_mutex_unlock(&adev->lock);
10543 return;
10544}
10545
Weiyin Jiang280ea742020-09-08 20:28:22 +080010546/* adev lock held */
10547int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010548{
10549 struct audio_usecase *uc_info;
Zhou Song407e5aa2020-12-27 19:13:04 +080010550 struct audio_usecase *usecase;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010551 struct listnode devices;
Zhou Song407e5aa2020-12-27 19:13:04 +080010552 struct listnode *node;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010553
10554 uc_info = get_usecase_from_list(adev, out->usecase);
10555 if (uc_info == NULL) {
10556 ALOGE("%s: Could not find the usecase (%d) in the list",
10557 __func__, out->usecase);
10558 return -EINVAL;
10559 }
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010560 list_init(&devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010561
Zhou Songbaddf9f2020-11-20 13:57:39 +080010562 ALOGD("%s: enter: usecase(%d: %s), a2dp muted %d", __func__,
10563 out->usecase, use_case_table[out->usecase], out->a2dp_muted);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010564
10565 if (restore) {
Weiyin Jiang280ea742020-09-08 20:28:22 +080010566 pthread_mutex_lock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010567 // restore A2DP device for active usecases and unmute if required
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010568 if (is_a2dp_out_device_type(&out->device_list)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010569 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
Zhou Songe5225132019-09-26 15:33:36 +080010570 if (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)
10571 select_devices(adev, uc_info->id);
Zhou Songbaddf9f2020-11-20 13:57:39 +080010572
10573 if (is_offload_usecase(out->usecase)) {
10574 if (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)
Weiyin Jiang280ea742020-09-08 20:28:22 +080010575 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
Zhou Songbaddf9f2020-11-20 13:57:39 +080010576 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
10577 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
10578 } else {
10579 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010580 }
Zhou Songbaddf9f2020-11-20 13:57:39 +080010581 out->a2dp_muted = false;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010582 }
Weiyin Jiang280ea742020-09-08 20:28:22 +080010583 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010584 } else {
Weiyin Jiang280ea742020-09-08 20:28:22 +080010585 pthread_mutex_lock(&out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +080010586 // mute stream and switch to speaker if suspended
10587 if (!out->a2dp_muted && !out->standby) {
Zhou Songbaddf9f2020-11-20 13:57:39 +080010588 assign_devices(&devices, &out->device_list);
10589 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Zhou Song407e5aa2020-12-27 19:13:04 +080010590 list_for_each(node, &adev->usecase_list) {
10591 usecase = node_to_item(node, struct audio_usecase, list);
Zhou Songe63b6fe2021-04-15 13:54:46 +080010592 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
10593 !is_a2dp_out_device_type(&usecase->stream.out->device_list) &&
Zhou Songcf77af02021-05-14 18:21:14 +080010594 !is_sco_out_device_type(&usecase->stream.out->device_list) &&
Zhou Songe63b6fe2021-04-15 13:54:46 +080010595 platform_check_backends_match(SND_DEVICE_OUT_SPEAKER,
10596 usecase->out_snd_device)) {
Zhou Song407e5aa2020-12-27 19:13:04 +080010597 assign_devices(&out->device_list, &usecase->stream.out->device_list);
10598 break;
10599 }
10600 }
Zhou Songcf77af02021-05-14 18:21:14 +080010601 if ((is_a2dp_out_device_type(&devices) && list_length(&devices) == 1) ||
10602 (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)) {
Zhou Song8edbbdb2021-01-14 16:48:03 +080010603 out->a2dp_muted = true;
10604 if (is_offload_usecase(out->usecase)) {
10605 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10606 compress_pause(out->compr);
10607 out_set_compr_volume(&out->stream, (float)0, (float)0);
Zhou Song8edbbdb2021-01-14 16:48:03 +080010608 } else {
Weiyin Jiang906db3c2021-03-02 13:17:04 +080010609 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
10610 out_set_voip_volume(&out->stream, (float)0, (float)0);
10611 else
10612 out_set_pcm_volume(&out->stream, (float)0, (float)0);
10613
Zhou Song8edbbdb2021-01-14 16:48:03 +080010614 /* wait for stale pcm drained before switching to speaker */
10615 uint32_t latency =
10616 (out->config.period_count * out->config.period_size * 1000) /
10617 (out->config.rate);
10618 usleep(latency * 1000);
10619 }
Zhou Songbaddf9f2020-11-20 13:57:39 +080010620 }
10621 select_devices(adev, out->usecase);
Zhou Song8edbbdb2021-01-14 16:48:03 +080010622 ALOGD("%s: switched to device:%s and stream muted:%d", __func__,
10623 platform_get_snd_device_name(uc_info->out_snd_device), out->a2dp_muted);
Zhou Songbaddf9f2020-11-20 13:57:39 +080010624 if (is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010625 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10626 compress_resume(out->compr);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010627 }
Zhou Songbaddf9f2020-11-20 13:57:39 +080010628 assign_devices(&out->device_list, &devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010629 }
Weiyin Jiang280ea742020-09-08 20:28:22 +080010630 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010631 }
10632 ALOGV("%s: exit", __func__);
10633 return 0;
10634}
10635
Haynes Mathew George01156f92018-04-13 15:29:54 -070010636void adev_on_battery_status_changed(bool charging)
10637{
10638 pthread_mutex_lock(&adev->lock);
10639 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
10640 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +080010641 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -070010642 pthread_mutex_unlock(&adev->lock);
10643}
10644
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010645static int adev_open(const hw_module_t *module, const char *name,
10646 hw_device_t **device)
10647{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010648 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -080010649 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010650 char mixer_ctl_name[128] = {0};
10651 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010652
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080010653 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010654 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
10655
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010656 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -070010657 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010658 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -070010659 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010660 ALOGD("%s: returning existing instance of adev", __func__);
10661 ALOGD("%s: exit", __func__);
10662 pthread_mutex_unlock(&adev_init_lock);
10663 return 0;
10664 }
10665
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010666 adev = calloc(1, sizeof(struct audio_device));
10667
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -070010668 if (!adev) {
10669 pthread_mutex_unlock(&adev_init_lock);
10670 return -ENOMEM;
10671 }
10672
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -070010673 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
10674
Weiyin Jiange6ce6312019-01-28 18:28:22 +080010675 // register audio ext hidl at the earliest
10676 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053010677#ifdef DYNAMIC_LOG_ENABLED
10678 register_for_dynamic_logging("hal");
10679#endif
10680
Derek Chenf939fb72018-11-13 13:34:41 -080010681 /* default audio HAL major version */
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010682 uint32_t maj_version = 3;
Derek Chenf939fb72018-11-13 13:34:41 -080010683 if(property_get("vendor.audio.hal.maj.version", value, NULL))
10684 maj_version = atoi(value);
10685
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010686 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -080010687 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010688 adev->device.common.module = (struct hw_module_t *)module;
10689 adev->device.common.close = adev_close;
10690
10691 adev->device.init_check = adev_init_check;
10692 adev->device.set_voice_volume = adev_set_voice_volume;
10693 adev->device.set_master_volume = adev_set_master_volume;
10694 adev->device.get_master_volume = adev_get_master_volume;
10695 adev->device.set_master_mute = adev_set_master_mute;
10696 adev->device.get_master_mute = adev_get_master_mute;
10697 adev->device.set_mode = adev_set_mode;
10698 adev->device.set_mic_mute = adev_set_mic_mute;
10699 adev->device.get_mic_mute = adev_get_mic_mute;
10700 adev->device.set_parameters = adev_set_parameters;
10701 adev->device.get_parameters = adev_get_parameters;
10702 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
10703 adev->device.open_output_stream = adev_open_output_stream;
10704 adev->device.close_output_stream = adev_close_output_stream;
10705 adev->device.open_input_stream = adev_open_input_stream;
10706 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010707 adev->device.create_audio_patch = adev_create_audio_patch;
10708 adev->device.release_audio_patch = adev_release_audio_patch;
10709 adev->device.get_audio_port = adev_get_audio_port;
10710 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010711 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +053010712 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010713
10714 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010715 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -080010716 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010717 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010718 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -080010719 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -070010720 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +053010721 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -070010722 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -070010723 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -070010724 /* Init audio and voice feature */
10725 audio_extn_feature_init();
10726 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070010727 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -080010728 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -080010729 list_init(&adev->active_inputs_list);
10730 list_init(&adev->active_outputs_list);
Rahul Sharma99770982019-03-06 17:05:26 +053010731 list_init(&adev->audio_patch_record_list);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010732 adev->io_streams_map = hashmapCreate(AUDIO_IO_PORTS_MAX, audio_extn_utils_hash_fn,
10733 audio_extn_utils_hash_eq);
10734 if (!adev->io_streams_map) {
10735 ALOGE("%s: Could not create io streams map", __func__);
10736 ret = -ENOMEM;
10737 goto adev_open_err;
10738 }
10739 adev->patch_map = hashmapCreate(AUDIO_PATCH_PORTS_MAX, audio_extn_utils_hash_fn,
10740 audio_extn_utils_hash_eq);
10741 if (!adev->patch_map) {
10742 ALOGE("%s: Could not create audio patch map", __func__);
10743 ret = -ENOMEM;
10744 goto adev_open_err;
10745 }
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -080010746 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -070010747 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +053010748 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +053010749 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +053010750 adev->perf_lock_opts[0] = 0x101;
10751 adev->perf_lock_opts[1] = 0x20E;
10752 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010753 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -070010754 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010755 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010756 adev->adm_routing_changed = false;
Revathi Uddarajub26e3932020-06-10 14:51:02 +053010757 adev->a2dp_started = false;
Zhou Song503196b2021-07-23 17:31:05 +080010758 adev->ha_proxy_enable = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +053010759
Zhou Song68ebc352019-12-05 17:11:15 +080010760 audio_extn_perf_lock_init();
10761
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010762 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -070010763 adev->platform = platform_init(adev);
10764 if (!adev->platform) {
Eric Laurentb23d5282013-05-14 15:27:20 -070010765 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010766 ret = -EINVAL;
10767 goto adev_open_err;
Eric Laurentb23d5282013-05-14 15:27:20 -070010768 }
Eric Laurentc4aef752013-09-12 17:45:53 -070010769
Aalique Grahame22e49102018-12-18 14:23:57 -080010770 adev->extspk = audio_extn_extspk_init(adev);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010771 if (audio_extn_qap_is_enabled()) {
10772 ret = audio_extn_qap_init(adev);
10773 if (ret < 0) {
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010774 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010775 goto adev_open_err;
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010776 }
10777 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
10778 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
10779 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010780
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010781 if (audio_extn_qaf_is_enabled()) {
10782 ret = audio_extn_qaf_init(adev);
10783 if (ret < 0) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010784 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010785 goto adev_open_err;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010786 }
10787
10788 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
10789 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
10790 }
10791
Derek Chenae7b0342019-02-08 15:17:04 -080010792 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -080010793 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
10794
Eric Laurentc4aef752013-09-12 17:45:53 -070010795 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
10796 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
10797 if (adev->visualizer_lib == NULL) {
10798 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
10799 } else {
10800 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
10801 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010802 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010803 "visualizer_hal_start_output");
10804 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010805 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010806 "visualizer_hal_stop_output");
10807 }
10808 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +053010809 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010810 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -080010811 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +080010812 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010813 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010814 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -070010815
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010816 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
10817 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
10818 if (adev->offload_effects_lib == NULL) {
10819 ALOGE("%s: DLOPEN failed for %s", __func__,
10820 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10821 } else {
10822 ALOGV("%s: DLOPEN successful for %s", __func__,
10823 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10824 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +053010825 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010826 "offload_effects_bundle_hal_start_output");
10827 adev->offload_effects_stop_output =
10828 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
10829 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080010830 adev->offload_effects_set_hpx_state =
10831 (int (*)(bool))dlsym(adev->offload_effects_lib,
10832 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +053010833 adev->offload_effects_get_parameters =
10834 (void (*)(struct str_parms *, struct str_parms *))
10835 dlsym(adev->offload_effects_lib,
10836 "offload_effects_bundle_get_parameters");
10837 adev->offload_effects_set_parameters =
10838 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
10839 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010840 }
10841 }
10842
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010843 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
10844 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
10845 if (adev->adm_lib == NULL) {
10846 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
10847 } else {
10848 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
10849 adev->adm_init = (adm_init_t)
10850 dlsym(adev->adm_lib, "adm_init");
10851 adev->adm_deinit = (adm_deinit_t)
10852 dlsym(adev->adm_lib, "adm_deinit");
10853 adev->adm_register_input_stream = (adm_register_input_stream_t)
10854 dlsym(adev->adm_lib, "adm_register_input_stream");
10855 adev->adm_register_output_stream = (adm_register_output_stream_t)
10856 dlsym(adev->adm_lib, "adm_register_output_stream");
10857 adev->adm_deregister_stream = (adm_deregister_stream_t)
10858 dlsym(adev->adm_lib, "adm_deregister_stream");
10859 adev->adm_request_focus = (adm_request_focus_t)
10860 dlsym(adev->adm_lib, "adm_request_focus");
10861 adev->adm_abandon_focus = (adm_abandon_focus_t)
10862 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010863 adev->adm_set_config = (adm_set_config_t)
10864 dlsym(adev->adm_lib, "adm_set_config");
10865 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
10866 dlsym(adev->adm_lib, "adm_request_focus_v2");
10867 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
10868 dlsym(adev->adm_lib, "adm_is_noirq_avail");
10869 adev->adm_on_routing_change = (adm_on_routing_change_t)
10870 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010871 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
10872 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010873 }
10874 }
10875
Aalique Grahame22e49102018-12-18 14:23:57 -080010876 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010877 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +080010878 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Kunlei Zhanga3c4cb02021-03-05 16:03:54 +080010879 adev->fluence_nn_usecase_id = USECASE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -080010880 //initialize this to false for now,
10881 //this will be set to true through set param
10882 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010883
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -070010884 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010885 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -080010886
10887 if (k_enable_extended_precision)
10888 adev_verify_devices(adev);
10889
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010890 adev->dsp_bit_width_enforce_mode =
10891 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010892
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010893 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
10894 &adev->streams_output_cfg_list,
10895 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070010896
Kiran Kandi910e1862013-10-29 13:29:42 -070010897 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010898
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010899 int trial;
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010900 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010901 trial = atoi(value);
10902 if (period_size_is_plausible_for_low_latency(trial)) {
10903 pcm_config_low_latency.period_size = trial;
10904 pcm_config_low_latency.start_threshold = trial / 4;
10905 pcm_config_low_latency.avail_min = trial / 4;
10906 configured_low_latency_capture_period_size = trial;
10907 }
10908 }
ronghuiz93177262021-04-21 19:58:13 +080010909 if (property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010910 trial = atoi(value);
10911 if (period_size_is_plausible_for_low_latency(trial)) {
10912 configured_low_latency_capture_period_size = trial;
10913 }
10914 }
10915
Vignesh Kulothungan7d374312018-02-21 17:12:00 -080010916 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
10917
Eric Laurent4b084132018-10-19 17:33:43 -070010918 adev->camera_orientation = CAMERA_DEFAULT;
10919
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010920 if (property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010921 af_period_multiplier = atoi(value);
10922 if (af_period_multiplier < 0)
10923 af_period_multiplier = 2;
10924 else if (af_period_multiplier > 4)
10925 af_period_multiplier = 4;
10926
10927 ALOGV("new period_multiplier = %d", af_period_multiplier);
10928 }
10929
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010930 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010931
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -070010932 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010933 pthread_mutex_unlock(&adev_init_lock);
10934
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010935 if (adev->adm_init)
10936 adev->adm_data = adev->adm_init();
10937
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010938 qahwi_init(*device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010939 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010940
10941 audio_extn_snd_mon_init();
10942 pthread_mutex_lock(&adev->lock);
10943 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
10944 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -070010945 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
10946 /*
10947 * if the battery state callback happens before charging can be queried,
10948 * it will be guarded with the adev->lock held in the cb function and so
10949 * the callback value will reflect the latest state
10950 */
10951 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010952 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +080010953 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -070010954 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +080010955 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010956 /* Allocate memory for Device config params */
10957 adev->device_cfg_params = (struct audio_device_config_param*)
10958 calloc(platform_get_max_codec_backend(),
10959 sizeof(struct audio_device_config_param));
10960 if (adev->device_cfg_params == NULL)
10961 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010962
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010963 /*
10964 * Check if new PSPD matrix mixer control is supported. If not
10965 * supported, then set flag so that old mixer ctrl is sent while
10966 * sending pspd coefficients on older kernel version. Query mixer
10967 * control for default pcm id and channel value one.
10968 */
10969 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
10970 "AudStr %d ChMixer Weight Ch %d", 0, 1);
10971
10972 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
10973 if (!ctl) {
10974 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
10975 __func__, mixer_ctl_name);
10976 adev->use_old_pspd_mix_ctrl = true;
10977 }
10978
Jaideep Sharma0fa53812020-09-17 09:00:11 +053010979 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010980 return 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010981
10982adev_open_err:
10983 free_map(adev->patch_map);
10984 free_map(adev->io_streams_map);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010985 free(adev->snd_dev_ref_cnt);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010986 pthread_mutex_destroy(&adev->lock);
10987 free(adev);
10988 adev = NULL;
10989 *device = NULL;
10990 pthread_mutex_unlock(&adev_init_lock);
10991 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010992}
10993
10994static struct hw_module_methods_t hal_module_methods = {
10995 .open = adev_open,
10996};
10997
10998struct audio_module HAL_MODULE_INFO_SYM = {
10999 .common = {
11000 .tag = HARDWARE_MODULE_TAG,
11001 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
11002 .hal_api_version = HARDWARE_HAL_API_VERSION,
11003 .id = AUDIO_HARDWARE_MODULE_ID,
11004 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -080011005 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080011006 .methods = &hal_module_methods,
11007 },
11008};