blob: 9d9cb7be9da0f110cf49f770d1e0d929438c8223 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07002 * Copyright (c) 2013-2020, 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
Aalique Grahame22e49102018-12-18 14:23:57 -0800105#define RECORD_GAIN_MIN 0.0f
106#define RECORD_GAIN_MAX 1.0f
107#define RECORD_VOLUME_CTL_MAX 0x2000
108
109/* treat as unsigned Q1.13 */
110#define APP_TYPE_GAIN_DEFAULT 0x2000
111
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700112#define PROXY_OPEN_RETRY_COUNT 100
113#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800114
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800115#define GET_USECASE_AUDIO_PLAYBACK_PRIMARY(db) \
116 (db)? USECASE_AUDIO_PLAYBACK_DEEP_BUFFER : \
117 USECASE_AUDIO_PLAYBACK_LOW_LATENCY
118#define GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(db) \
119 (db)? pcm_config_deep_buffer : pcm_config_low_latency
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800120
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700121#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700122#define DEFAULT_VOIP_BUF_DURATION_MS 20
123#define DEFAULT_VOIP_BIT_DEPTH_BYTE sizeof(int16_t)
124#define DEFAULT_VOIP_SAMP_RATE 48000
125
126#define VOIP_IO_BUF_SIZE(SR, DURATION_MS, BIT_DEPTH) (SR)/1000 * DURATION_MS * BIT_DEPTH
127
128struct pcm_config default_pcm_config_voip_copp = {
129 .channels = 1,
130 .rate = DEFAULT_VOIP_SAMP_RATE, /* changed when the stream is opened */
131 .period_size = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
132 .period_count = 2,
133 .format = PCM_FORMAT_S16_LE,
kunleiz95b597a2017-10-23 17:07:33 +0800134 .avail_min = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
135 .stop_threshold = INT_MAX,
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700136};
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700137
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700138#define MIN_CHANNEL_COUNT 1
139#define DEFAULT_CHANNEL_COUNT 2
140#define MAX_HIFI_CHANNEL_COUNT 8
141
Aalique Grahame22e49102018-12-18 14:23:57 -0800142#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
143#define MAX_CHANNEL_COUNT 1
144#else
145#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
146#define XSTR(x) STR(x)
147#define STR(x) #x
148#endif
149
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700150static unsigned int configured_low_latency_capture_period_size =
151 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
152
Haynes Mathew George16081042017-05-31 17:16:49 -0700153#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
154#define MMAP_PERIOD_COUNT_MIN 32
155#define MMAP_PERIOD_COUNT_MAX 512
156#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
157
Aalique Grahame22e49102018-12-18 14:23:57 -0800158/* This constant enables extended precision handling.
159 * TODO The flag is off until more testing is done.
160 */
161static const bool k_enable_extended_precision = false;
Arun Mirpurie008ed22019-03-21 11:21:04 -0700162extern int AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Aalique Grahame22e49102018-12-18 14:23:57 -0800163
Eric Laurentb23d5282013-05-14 15:27:20 -0700164struct pcm_config pcm_config_deep_buffer = {
165 .channels = 2,
166 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
167 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
168 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
169 .format = PCM_FORMAT_S16_LE,
170 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
171 .stop_threshold = INT_MAX,
172 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
173};
174
175struct pcm_config pcm_config_low_latency = {
176 .channels = 2,
177 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
178 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
179 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
180 .format = PCM_FORMAT_S16_LE,
181 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
182 .stop_threshold = INT_MAX,
183 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
184};
185
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800186struct pcm_config pcm_config_haptics_audio = {
187 .channels = 1,
188 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
189 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
190 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
191 .format = PCM_FORMAT_S16_LE,
192 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
193 .stop_threshold = INT_MAX,
194 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
195};
196
197struct pcm_config pcm_config_haptics = {
198 .channels = 1,
199 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
200 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
201 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
202 .format = PCM_FORMAT_S16_LE,
203 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
204 .stop_threshold = INT_MAX,
205 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
206};
207
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700208static int af_period_multiplier = 4;
209struct pcm_config pcm_config_rt = {
210 .channels = 2,
211 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
212 .period_size = ULL_PERIOD_SIZE, //1 ms
213 .period_count = 512, //=> buffer size is 512ms
214 .format = PCM_FORMAT_S16_LE,
215 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
216 .stop_threshold = INT_MAX,
217 .silence_threshold = 0,
218 .silence_size = 0,
219 .avail_min = ULL_PERIOD_SIZE, //1 ms
220};
221
Eric Laurentb23d5282013-05-14 15:27:20 -0700222struct pcm_config pcm_config_hdmi_multi = {
223 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
224 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
225 .period_size = HDMI_MULTI_PERIOD_SIZE,
226 .period_count = HDMI_MULTI_PERIOD_COUNT,
227 .format = PCM_FORMAT_S16_LE,
228 .start_threshold = 0,
229 .stop_threshold = INT_MAX,
230 .avail_min = 0,
231};
232
Haynes Mathew George16081042017-05-31 17:16:49 -0700233struct pcm_config pcm_config_mmap_playback = {
234 .channels = 2,
235 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
236 .period_size = MMAP_PERIOD_SIZE,
237 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
238 .format = PCM_FORMAT_S16_LE,
239 .start_threshold = MMAP_PERIOD_SIZE*8,
240 .stop_threshold = INT32_MAX,
241 .silence_threshold = 0,
242 .silence_size = 0,
243 .avail_min = MMAP_PERIOD_SIZE, //1 ms
244};
245
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700246struct pcm_config pcm_config_hifi = {
247 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
248 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
249 .period_size = HIFI_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
250 .period_count = HIFI_BUFFER_OUTPUT_PERIOD_COUNT,
251 .format = PCM_FORMAT_S24_3LE,
252 .start_threshold = 0,
253 .stop_threshold = INT_MAX,
254 .avail_min = 0,
255};
256
Eric Laurentb23d5282013-05-14 15:27:20 -0700257struct pcm_config pcm_config_audio_capture = {
258 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700259 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
260 .format = PCM_FORMAT_S16_LE,
261};
262
Haynes Mathew George16081042017-05-31 17:16:49 -0700263struct pcm_config pcm_config_mmap_capture = {
264 .channels = 2,
265 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
266 .period_size = MMAP_PERIOD_SIZE,
267 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
268 .format = PCM_FORMAT_S16_LE,
269 .start_threshold = 0,
270 .stop_threshold = INT_MAX,
271 .silence_threshold = 0,
272 .silence_size = 0,
273 .avail_min = MMAP_PERIOD_SIZE, //1 ms
274};
275
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700276#define AFE_PROXY_CHANNEL_COUNT 2
277#define AFE_PROXY_SAMPLING_RATE 48000
278
279#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
280#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
281
282struct pcm_config pcm_config_afe_proxy_playback = {
283 .channels = AFE_PROXY_CHANNEL_COUNT,
284 .rate = AFE_PROXY_SAMPLING_RATE,
285 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
286 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
287 .format = PCM_FORMAT_S16_LE,
288 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
289 .stop_threshold = INT_MAX,
290 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
291};
292
293#define AFE_PROXY_RECORD_PERIOD_SIZE 768
294#define AFE_PROXY_RECORD_PERIOD_COUNT 4
295
Aalique Grahame22e49102018-12-18 14:23:57 -0800296struct pcm_config pcm_config_audio_capture_rt = {
297 .channels = 2,
298 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
299 .period_size = ULL_PERIOD_SIZE,
300 .period_count = 512,
301 .format = PCM_FORMAT_S16_LE,
302 .start_threshold = 0,
303 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
304 .silence_threshold = 0,
305 .silence_size = 0,
306 .avail_min = ULL_PERIOD_SIZE, //1 ms
307};
308
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700309struct pcm_config pcm_config_afe_proxy_record = {
310 .channels = AFE_PROXY_CHANNEL_COUNT,
311 .rate = AFE_PROXY_SAMPLING_RATE,
312 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
313 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
314 .format = PCM_FORMAT_S16_LE,
315 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
316 .stop_threshold = INT_MAX,
317 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
318};
319
Ashish Jainf1eaa582016-05-23 20:54:24 +0530320#define AUDIO_MAX_PCM_FORMATS 7
321
322const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
323 [AUDIO_FORMAT_DEFAULT] = 0,
324 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
325 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
326 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
327 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
328 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
329 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
330};
331
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800332const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700333 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
334 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800335 [USECASE_AUDIO_PLAYBACK_WITH_HAPTICS] = "audio-with-haptics-playback",
Meng Wang51d8c2a2020-04-27 15:23:21 +0800336 [USECASE_AUDIO_PLAYBACK_HAPTICS] = "haptics-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700337 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
338 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700339 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700340 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700341 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
342 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
343 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
344 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
345 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
346 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
347 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
348 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
Haynes Mathew George16081042017-05-31 17:16:49 -0700349 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
350 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700351 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Aalique Grahame22e49102018-12-18 14:23:57 -0800352 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
vivek mehta0ea887a2015-08-26 14:01:20 -0700353
Eric Laurentb23d5282013-05-14 15:27:20 -0700354 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700355 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530356 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
357 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
358 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Dhananjay Kumar376e38b2017-09-28 22:26:23 +0530359 [USECASE_AUDIO_RECORD_COMPRESS5] = "audio-record-compress5",
360 [USECASE_AUDIO_RECORD_COMPRESS6] = "audio-record-compress6",
Eric Laurentb23d5282013-05-14 15:27:20 -0700361 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700362 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700363 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700364 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700365
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800366 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800367 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Derek Chenf7092792017-05-23 12:23:53 -0400368 [USECASE_AUDIO_HFP_SCO_DOWNLINK] = "hfp-sco-downlink",
369 [USECASE_AUDIO_HFP_SCO_WB_DOWNLINK] = "hfp-sco-wb-downlink",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700370
Derek Chenf7092792017-05-23 12:23:53 -0400371 [USECASE_VOICE_CALL] = "voice-call",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700372 [USECASE_VOICE2_CALL] = "voice2-call",
373 [USECASE_VOLTE_CALL] = "volte-call",
374 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800375 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800376 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
377 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800378 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700379 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
380 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
381 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800382 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
383 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
384 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
385
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700386 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
387 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700388 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
389 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700390
391 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
392 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Zhou Song62ea0282020-03-22 19:53:01 +0800393 [USECASE_AUDIO_RECORD_AFE_PROXY2] = "afe-proxy-record2",
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +0530394 [USECASE_AUDIO_PLAYBACK_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700395
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530396 /* Transcode loopback cases */
Surendar Karka93cd25a2018-08-28 14:21:37 +0530397 [USECASE_AUDIO_TRANSCODE_LOOPBACK_RX] = "audio-transcode-loopback-rx",
398 [USECASE_AUDIO_TRANSCODE_LOOPBACK_TX] = "audio-transcode-loopback-tx",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700399
400 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
401 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Revathi Uddarajud9f23d92020-07-27 10:55:06 +0530402 [USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY] = "audio-record-voip-low-latency",
Varun Balaraje49253e2017-07-06 19:48:56 +0530403 /* For Interactive Audio Streams */
404 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
405 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
406 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
407 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
408 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
409 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
410 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
411 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700412
Aniket Kumar Lata7fd86e12018-02-20 19:26:10 -0800413 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture",
414
Derek Chenf6318be2017-06-12 17:16:24 -0400415 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
416
417 [USECASE_AUDIO_PLAYBACK_MEDIA] = "media-playback",
418 [USECASE_AUDIO_PLAYBACK_SYS_NOTIFICATION] = "sys-notification-playback",
419 [USECASE_AUDIO_PLAYBACK_NAV_GUIDANCE] = "nav-guidance-playback",
420 [USECASE_AUDIO_PLAYBACK_PHONE] = "phone-playback",
Derek Chen1bcdc6b2020-02-06 22:44:53 -0800421 [USECASE_AUDIO_PLAYBACK_FRONT_PASSENGER] = "front-passenger-playback",
Derek Chendf05eea2019-08-01 13:57:49 -0700422 [USECASE_AUDIO_PLAYBACK_REAR_SEAT] = "rear-seat-playback",
Rahul Sharma99770982019-03-06 17:05:26 +0530423 [USECASE_AUDIO_FM_TUNER_EXT] = "fm-tuner-ext",
Eric Laurentb23d5282013-05-14 15:27:20 -0700424};
425
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700426static const audio_usecase_t offload_usecases[] = {
427 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700428 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
429 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
430 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
431 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
432 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
433 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
434 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
435 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700436};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800437
Varun Balaraje49253e2017-07-06 19:48:56 +0530438static const audio_usecase_t interactive_usecases[] = {
439 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
440 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
441 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
442 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
443 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
444 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
445 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
446 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
447};
448
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800449#define STRING_TO_ENUM(string) { #string, string }
450
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800451struct string_to_enum {
452 const char *name;
453 uint32_t value;
454};
455
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700456static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800457 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800458 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
459 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
460 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700461 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800462 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
463 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800464 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700465 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
466 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
467 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
468 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
469 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
470 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
471 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
472 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
473 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
474 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
475 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800476};
477
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700478static const struct string_to_enum formats_name_to_enum_table[] = {
479 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
480 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
481 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700482 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
483 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
484 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700485 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800486 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
487 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700488 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800489};
490
491//list of all supported sample rates by HDMI specification.
492static const int out_hdmi_sample_rates[] = {
493 32000, 44100, 48000, 88200, 96000, 176400, 192000,
494};
495
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700496static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800497 STRING_TO_ENUM(32000),
498 STRING_TO_ENUM(44100),
499 STRING_TO_ENUM(48000),
500 STRING_TO_ENUM(88200),
501 STRING_TO_ENUM(96000),
502 STRING_TO_ENUM(176400),
503 STRING_TO_ENUM(192000),
Mingshu pange8aedf12019-10-25 15:38:27 +0800504 STRING_TO_ENUM(352800),
505 STRING_TO_ENUM(384000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700506};
507
Carter Hsu2e429db2019-05-14 18:50:52 +0800508struct in_effect_list {
509 struct listnode list;
510 effect_handle_t handle;
511};
512
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700513static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700514static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700515static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700516//cache last MBDRC cal step level
517static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700518
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530519static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
520static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Arun Mirpuri5d170872019-03-26 13:21:31 -0700521static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800522static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530523static int out_set_pcm_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530524
Derek Chen6f293672019-04-01 01:40:24 -0700525static void adev_snd_mon_cb(void *cookie, struct str_parms *parms);
526static void in_snd_mon_cb(void * stream, struct str_parms * parms);
527static void out_snd_mon_cb(void * stream, struct str_parms * parms);
528
Zhou Song331c8e52019-08-26 14:16:12 +0800529static int configure_btsco_sample_rate(snd_device_t snd_device);
530
Vatsal Buchac09ae062018-11-14 13:25:08 +0530531#ifdef AUDIO_FEATURE_ENABLED_GCOV
532extern void __gcov_flush();
533static void enable_gcov()
534{
535 __gcov_flush();
536}
537#else
538static void enable_gcov()
539{
540}
541#endif
542
justinweng20fb6d82019-02-21 18:49:00 -0700543static int in_set_microphone_direction(const struct audio_stream_in *stream,
544 audio_microphone_direction_t dir);
545static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom);
546
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700547static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
548 int flags __unused)
549{
550 int dir = 0;
551 switch (uc_id) {
552 case USECASE_AUDIO_RECORD_LOW_LATENCY:
Revathi Uddarajud9f23d92020-07-27 10:55:06 +0530553 case USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY:
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700554 dir = 1;
555 case USECASE_AUDIO_PLAYBACK_ULL:
556 break;
557 default:
558 return false;
559 }
560
561 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
562 PCM_PLAYBACK : PCM_CAPTURE);
563 if (adev->adm_is_noirq_avail)
564 return adev->adm_is_noirq_avail(adev->adm_data,
565 adev->snd_card, dev_id, dir);
566 return false;
567}
568
569static void register_out_stream(struct stream_out *out)
570{
571 struct audio_device *adev = out->dev;
572 if (is_offload_usecase(out->usecase) ||
573 !adev->adm_register_output_stream)
574 return;
575
576 // register stream first for backward compatibility
577 adev->adm_register_output_stream(adev->adm_data,
578 out->handle,
579 out->flags);
580
581 if (!adev->adm_set_config)
582 return;
583
584 if (out->realtime)
585 adev->adm_set_config(adev->adm_data,
586 out->handle,
587 out->pcm, &out->config);
588}
589
590static void register_in_stream(struct stream_in *in)
591{
592 struct audio_device *adev = in->dev;
593 if (!adev->adm_register_input_stream)
594 return;
595
596 adev->adm_register_input_stream(adev->adm_data,
597 in->capture_handle,
598 in->flags);
599
600 if (!adev->adm_set_config)
601 return;
602
603 if (in->realtime)
604 adev->adm_set_config(adev->adm_data,
605 in->capture_handle,
606 in->pcm,
607 &in->config);
608}
609
610static void request_out_focus(struct stream_out *out, long ns)
611{
612 struct audio_device *adev = out->dev;
613
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700614 if (adev->adm_request_focus_v2)
615 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
616 else if (adev->adm_request_focus)
617 adev->adm_request_focus(adev->adm_data, out->handle);
618}
619
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700620static int request_in_focus(struct stream_in *in, long ns)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700621{
622 struct audio_device *adev = in->dev;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700623 int ret = 0;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700624
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700625 if (adev->adm_request_focus_v2_1)
626 ret = adev->adm_request_focus_v2_1(adev->adm_data, in->capture_handle, ns);
627 else if (adev->adm_request_focus_v2)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700628 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
629 else if (adev->adm_request_focus)
630 adev->adm_request_focus(adev->adm_data, in->capture_handle);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700631
632 return ret;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700633}
634
635static void release_out_focus(struct stream_out *out)
636{
637 struct audio_device *adev = out->dev;
638
639 if (adev->adm_abandon_focus)
640 adev->adm_abandon_focus(adev->adm_data, out->handle);
641}
642
643static void release_in_focus(struct stream_in *in)
644{
645 struct audio_device *adev = in->dev;
646 if (adev->adm_abandon_focus)
647 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
648}
649
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530650static int parse_snd_card_status(struct str_parms *parms, int *card,
651 card_status_t *status)
652{
653 char value[32]={0};
654 char state[32]={0};
655
656 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
657 if (ret < 0)
658 return -1;
659
660 // sscanf should be okay as value is of max length 32.
661 // same as sizeof state.
662 if (sscanf(value, "%d,%s", card, state) < 2)
663 return -1;
664
665 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
666 CARD_STATUS_OFFLINE;
667 return 0;
668}
669
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700670static inline void adjust_frames_for_device_delay(struct stream_out *out,
671 uint32_t *dsp_frames) {
672 // Adjustment accounts for A2dp encoder latency with offload usecases
673 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -0800674 if (is_a2dp_out_device_type(&out->device_list)) {
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700675 unsigned long offset =
676 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
677 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
678 }
679}
680
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700681static inline bool free_entry(void *key __unused,
682 void *value, void *context __unused)
683{
684 free(value);
685 return true;
686}
687
688static inline void free_map(Hashmap *map)
689{
690 if (map) {
691 hashmapForEach(map, free_entry, (void *) NULL);
692 hashmapFree(map);
693 }
694}
695
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800696static inline void patch_map_remove_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700697 audio_patch_handle_t patch_handle)
698{
699 if (patch_handle == AUDIO_PATCH_HANDLE_NONE)
700 return;
701
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700702 struct audio_patch_info *p_info =
703 hashmapGet(adev->patch_map, (void *) (intptr_t) patch_handle);
704 if (p_info) {
705 ALOGV("%s: Remove patch %d", __func__, patch_handle);
706 hashmapRemove(adev->patch_map, (void *) (intptr_t) patch_handle);
707 free(p_info->patch);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700708 free(p_info);
709 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700710}
711
712static inline int io_streams_map_insert(struct audio_device *adev,
713 struct audio_stream *stream,
714 audio_io_handle_t handle,
715 audio_patch_handle_t patch_handle)
716{
717 struct audio_stream_info *s_info =
718 (struct audio_stream_info *) calloc(1, sizeof(struct audio_stream_info));
719
720 if (s_info == NULL) {
721 ALOGE("%s: Could not allocate stream info", __func__);
722 return -ENOMEM;
723 }
724 s_info->stream = stream;
725 s_info->patch_handle = patch_handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700726
727 pthread_mutex_lock(&adev->lock);
728 struct audio_stream_info *stream_info =
729 hashmapPut(adev->io_streams_map, (void *) (intptr_t) handle, (void *) s_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700730 if (stream_info != NULL)
731 free(stream_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800732 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Latad13758f2020-08-06 15:11:36 -0700733 ALOGV("%s: Added stream in io_streams_map with handle %d", __func__, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700734 return 0;
735}
736
737static inline void io_streams_map_remove(struct audio_device *adev,
738 audio_io_handle_t handle)
739{
740 pthread_mutex_lock(&adev->lock);
741 struct audio_stream_info *s_info =
742 hashmapRemove(adev->io_streams_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700743 if (s_info == NULL)
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800744 goto done;
Aniket Kumar Latad13758f2020-08-06 15:11:36 -0700745 ALOGV("%s: Removed stream with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800746 patch_map_remove_l(adev, s_info->patch_handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700747 free(s_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800748done:
749 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700750 return;
751}
752
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800753static struct audio_patch_info* fetch_patch_info_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700754 audio_patch_handle_t handle)
755{
756 struct audio_patch_info *p_info = NULL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700757 p_info = (struct audio_patch_info *)
758 hashmapGet(adev->patch_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700759 return p_info;
760}
761
vivek mehtaa76401a2015-04-24 14:12:15 -0700762__attribute__ ((visibility ("default")))
763bool audio_hw_send_gain_dep_calibration(int level) {
764 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700765 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700766
767 pthread_mutex_lock(&adev_init_lock);
768
769 if (adev != NULL && adev->platform != NULL) {
770 pthread_mutex_lock(&adev->lock);
771 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700772
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530773 // cache level info for any of the use case which
774 // was not started.
775 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700776
vivek mehtaa76401a2015-04-24 14:12:15 -0700777 pthread_mutex_unlock(&adev->lock);
778 } else {
779 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
780 }
781
782 pthread_mutex_unlock(&adev_init_lock);
783
784 return ret_val;
785}
786
Ashish Jain5106d362016-05-11 19:23:33 +0530787static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
788{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800789 bool gapless_enabled = false;
790 const char *mixer_ctl_name = "Compress Gapless Playback";
791 struct mixer_ctl *ctl;
792
793 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700794 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530795
796 /*Disable gapless if its AV playback*/
797 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800798
799 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
800 if (!ctl) {
801 ALOGE("%s: Could not get ctl for mixer cmd - %s",
802 __func__, mixer_ctl_name);
803 return -EINVAL;
804 }
805
806 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
807 ALOGE("%s: Could not set gapless mode %d",
808 __func__, gapless_enabled);
809 return -EINVAL;
810 }
811 return 0;
812}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700813
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700814__attribute__ ((visibility ("default")))
815int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
816 int table_size) {
817 int ret_val = 0;
818 ALOGV("%s: enter ... ", __func__);
819
820 pthread_mutex_lock(&adev_init_lock);
821 if (adev == NULL) {
822 ALOGW("%s: adev is NULL .... ", __func__);
823 goto done;
824 }
825
826 pthread_mutex_lock(&adev->lock);
827 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
828 pthread_mutex_unlock(&adev->lock);
829done:
830 pthread_mutex_unlock(&adev_init_lock);
831 ALOGV("%s: exit ... ", __func__);
832 return ret_val;
833}
834
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800835bool audio_hw_send_qdsp_parameter(int stream_type, float vol, bool active)
Aalique Grahame22e49102018-12-18 14:23:57 -0800836{
837 bool ret = false;
838 ALOGV("%s: enter ...", __func__);
839
840 pthread_mutex_lock(&adev_init_lock);
841
842 if (adev != NULL && adev->platform != NULL) {
843 pthread_mutex_lock(&adev->lock);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800844 ret = audio_extn_qdsp_set_state(adev, stream_type, vol, active);
Aalique Grahame22e49102018-12-18 14:23:57 -0800845 pthread_mutex_unlock(&adev->lock);
846 }
847
848 pthread_mutex_unlock(&adev_init_lock);
849
850 ALOGV("%s: exit with ret %d", __func__, ret);
851 return ret;
852}
Aalique Grahame22e49102018-12-18 14:23:57 -0800853
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700854static bool is_supported_format(audio_format_t format)
855{
Eric Laurent86e17132013-09-12 17:49:30 -0700856 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530857 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530858 format == AUDIO_FORMAT_AAC_LC ||
859 format == AUDIO_FORMAT_AAC_HE_V1 ||
860 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530861 format == AUDIO_FORMAT_AAC_ADTS_LC ||
862 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
863 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530864 format == AUDIO_FORMAT_AAC_LATM_LC ||
865 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
866 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530867 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
868 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530869 format == AUDIO_FORMAT_PCM_FLOAT ||
870 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700871 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530872 format == AUDIO_FORMAT_AC3 ||
873 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700874 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530875 format == AUDIO_FORMAT_DTS ||
876 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800877 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530878 format == AUDIO_FORMAT_ALAC ||
879 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530880 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530881 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800882 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530883 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700884 format == AUDIO_FORMAT_APTX ||
885 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800886 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700887
888 return false;
889}
890
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700891static inline bool is_mmap_usecase(audio_usecase_t uc_id)
892{
893 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
Zhou Song62ea0282020-03-22 19:53:01 +0800894 (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY2) ||
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700895 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
896}
897
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700898static inline bool is_valid_volume(float left, float right)
899{
900 return ((left >= 0.0f && right >= 0.0f) ? true : false);
901}
902
Avinash Vaish71a8b972014-07-24 15:36:33 +0530903static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
904 struct audio_usecase *uc_info)
905{
906 struct listnode *node;
907 struct audio_usecase *usecase;
908
909 if (uc_info == NULL)
910 return -EINVAL;
911
912 /* Re-route all voice usecases on the shared backend other than the
913 specified usecase to new snd devices */
914 list_for_each(node, &adev->usecase_list) {
915 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800916 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530917 enable_audio_route(adev, usecase);
918 }
919 return 0;
920}
921
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530922static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530923{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530924 ALOGV("%s", __func__);
925 audio_route_apply_and_update_path(adev->audio_route,
926 "asrc-mode");
927 adev->asrc_mode_enabled = true;
928}
929
930static void disable_asrc_mode(struct audio_device *adev)
931{
932 ALOGV("%s", __func__);
933 audio_route_reset_and_update_path(adev->audio_route,
934 "asrc-mode");
935 adev->asrc_mode_enabled = false;
936}
937
938/*
939 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
940 * 44.1 or Native DSD backends are enabled for any of current use case.
941 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
942 * - Disable current mix path use case(Headphone backend) and re-enable it with
943 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
944 * e.g. Naitve DSD or Headphone 44.1 -> + 48
945 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530946static void check_and_set_asrc_mode(struct audio_device *adev,
947 struct audio_usecase *uc_info,
948 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530949{
950 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530951 int i, num_new_devices = 0;
952 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
953 /*
954 *Split snd device for new combo use case
955 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
956 */
957 if (platform_split_snd_device(adev->platform,
958 snd_device,
959 &num_new_devices,
960 split_new_snd_devices) == 0) {
961 for (i = 0; i < num_new_devices; i++)
962 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
963 } else {
964 int new_backend_idx = platform_get_backend_index(snd_device);
965 if (((new_backend_idx == HEADPHONE_BACKEND) ||
966 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
967 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
968 !adev->asrc_mode_enabled) {
969 struct listnode *node = NULL;
970 struct audio_usecase *uc = NULL;
971 struct stream_out *curr_out = NULL;
972 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
973 int i, num_devices, ret = 0;
974 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530975
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530976 list_for_each(node, &adev->usecase_list) {
977 uc = node_to_item(node, struct audio_usecase, list);
978 curr_out = (struct stream_out*) uc->stream.out;
979 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
980 /*
981 *Split snd device for existing combo use case
982 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
983 */
984 ret = platform_split_snd_device(adev->platform,
985 uc->out_snd_device,
986 &num_devices,
987 split_snd_devices);
988 if (ret < 0 || num_devices == 0) {
989 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
990 split_snd_devices[0] = uc->out_snd_device;
991 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800992 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530993 for (i = 0; i < num_devices; i++) {
994 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
995 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
996 if((new_backend_idx == HEADPHONE_BACKEND) &&
997 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
998 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
Aniket Kumar Latad13758f2020-08-06 15:11:36 -0700999 ALOGV("%s:DSD or native stream detected enabling asrcmode in hardware",
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301000 __func__);
1001 enable_asrc_mode(adev);
1002 break;
1003 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
1004 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
1005 (usecase_backend_idx == HEADPHONE_BACKEND)) {
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07001006 ALOGV("%s: 48K stream detected, disabling and enabling it \
1007 with asrcmode in hardware", __func__);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301008 disable_audio_route(adev, uc);
1009 disable_snd_device(adev, uc->out_snd_device);
1010 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
1011 if (new_backend_idx == DSD_NATIVE_BACKEND)
1012 audio_route_apply_and_update_path(adev->audio_route,
1013 "hph-true-highquality-mode");
1014 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
1015 (curr_out->bit_width >= 24))
1016 audio_route_apply_and_update_path(adev->audio_route,
1017 "hph-highquality-mode");
1018 enable_asrc_mode(adev);
1019 enable_snd_device(adev, uc->out_snd_device);
1020 enable_audio_route(adev, uc);
1021 break;
1022 }
1023 }
1024 // reset split devices count
1025 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -08001026 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301027 if (adev->asrc_mode_enabled)
1028 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301029 }
1030 }
1031 }
1032}
1033
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001034static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
1035 struct audio_effect_config effect_config,
1036 unsigned int param_value)
1037{
1038 char mixer_ctl_name[] = "Audio Effect";
1039 struct mixer_ctl *ctl;
1040 long set_values[6];
Eric Laurent637e2d42018-11-15 12:24:31 -08001041 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001042
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001043 if (in == NULL) {
1044 ALOGE("%s: active input stream is NULL", __func__);
1045 return -EINVAL;
1046 }
1047
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001048 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1049 if (!ctl) {
1050 ALOGE("%s: Could not get mixer ctl - %s",
1051 __func__, mixer_ctl_name);
1052 return -EINVAL;
1053 }
1054
1055 set_values[0] = 1; //0:Rx 1:Tx
1056 set_values[1] = in->app_type_cfg.app_type;
1057 set_values[2] = (long)effect_config.module_id;
1058 set_values[3] = (long)effect_config.instance_id;
1059 set_values[4] = (long)effect_config.param_id;
1060 set_values[5] = param_value;
1061
1062 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
1063
1064 return 0;
1065
1066}
1067
1068static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
1069 int effect_type, unsigned int *param_value)
1070{
1071 int ret = 0;
1072 struct audio_effect_config other_effect_config;
1073 struct audio_usecase *usecase = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08001074 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001075
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001076 if (in == NULL) {
1077 ALOGE("%s: active input stream is NULL", __func__);
1078 return -EINVAL;
1079 }
1080
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001081 usecase = get_usecase_from_list(adev, in->usecase);
1082 if (!usecase)
1083 return -EINVAL;
1084
1085 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
1086 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
1087 if (ret < 0) {
1088 ALOGE("%s Failed to get effect params %d", __func__, ret);
1089 return ret;
1090 }
1091
1092 if (module_id == other_effect_config.module_id) {
1093 //Same module id for AEC/NS. Values need to be combined
1094 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
1095 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
1096 *param_value |= other_effect_config.param_value;
1097 }
1098 }
1099
1100 return ret;
1101}
1102
1103static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
Gangadhar Sb0210342019-02-22 17:39:41 +05301104{
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001105 struct audio_effect_config effect_config;
1106 struct audio_usecase *usecase = NULL;
1107 int ret = 0;
1108 unsigned int param_value = 0;
Eric Laurent637e2d42018-11-15 12:24:31 -08001109 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001110
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001111 if(!voice_extn_is_dynamic_ecns_enabled())
1112 return ENOSYS;
1113
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001114 if (!in) {
1115 ALOGE("%s: Invalid input stream", __func__);
1116 return -EINVAL;
1117 }
1118
1119 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
1120
1121 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +08001122 if (usecase == NULL) {
1123 ALOGE("%s: Could not find the usecase (%d) in the list",
1124 __func__, in->usecase);
1125 return -EINVAL;
1126 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001127
1128 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
1129 if (ret < 0) {
1130 ALOGE("%s Failed to get module id %d", __func__, ret);
1131 return ret;
1132 }
1133 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
1134 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
1135
1136 if(enable)
1137 param_value = effect_config.param_value;
1138
1139 /*Special handling for AEC & NS effects Param values need to be
1140 updated if module ids are same*/
1141
1142 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
1143 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
1144 if (ret < 0)
1145 return ret;
1146 }
1147
1148 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
1149
1150 return ret;
1151}
1152
1153static void check_and_enable_effect(struct audio_device *adev)
1154{
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001155 if(!voice_extn_is_dynamic_ecns_enabled())
1156 return;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001157
Eric Laurent637e2d42018-11-15 12:24:31 -08001158 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001159
Eric Laurent637e2d42018-11-15 12:24:31 -08001160 if (in != NULL && !in->standby) {
1161 if (in->enable_aec)
1162 enable_disable_effect(adev, EFFECT_AEC, true);
1163
1164 if (in->enable_ns &&
1165 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1166 enable_disable_effect(adev, EFFECT_NS, true);
1167 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001168 }
1169}
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001170
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001171int pcm_ioctl(struct pcm *pcm, int request, ...)
1172{
1173 va_list ap;
1174 void * arg;
1175 int pcm_fd = *(int*)pcm;
1176
1177 va_start(ap, request);
1178 arg = va_arg(ap, void *);
1179 va_end(ap);
1180
1181 return ioctl(pcm_fd, request, arg);
1182}
1183
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001184int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001185 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001186{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001187 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001188 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +05301189 struct stream_out *out = NULL;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301190 struct stream_in *in = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001191 struct listnode out_devices;
Soumya Managoli6993b762018-06-28 16:04:57 +05301192 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001193
1194 if (usecase == NULL)
1195 return -EINVAL;
1196
1197 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
1198
Carter Hsu2e429db2019-05-14 18:50:52 +08001199 if (usecase->type == PCM_CAPTURE) {
1200 struct stream_in *in = usecase->stream.in;
1201 struct audio_usecase *uinfo;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001202 snd_device = usecase->in_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001203
1204 if (in) {
1205 if (in->enable_aec || in->enable_ec_port) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001206 list_init(&out_devices);
1207 update_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "", true);
Carter Hsu2e429db2019-05-14 18:50:52 +08001208 struct listnode *node;
1209 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1210 USECASE_AUDIO_PLAYBACK_VOIP);
1211 if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001212 assign_devices(&out_devices,
1213 &voip_usecase->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001214 } else if (adev->primary_output &&
1215 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001216 assign_devices(&out_devices,
1217 &adev->primary_output->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001218 } else {
1219 list_for_each(node, &adev->usecase_list) {
1220 uinfo = node_to_item(node, struct audio_usecase, list);
1221 if (uinfo->type != PCM_CAPTURE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001222 assign_devices(&out_devices,
1223 &uinfo->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001224 break;
1225 }
1226 }
1227 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001228
1229 platform_set_echo_reference(adev, true, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001230 in->ec_opened = true;
1231 }
1232 }
Guodong Huf5e614d2019-06-24 18:42:03 +08001233 } else if ((usecase->type == TRANSCODE_LOOPBACK_TX) || ((usecase->type == PCM_HFP_CALL) &&
1234 ((usecase->id == USECASE_AUDIO_HFP_SCO) || (usecase->id == USECASE_AUDIO_HFP_SCO_WB)) &&
1235 (usecase->in_snd_device == SND_DEVICE_IN_VOICE_SPEAKER_MIC_HFP_MMSECNS))) {
Carter Hsu2e429db2019-05-14 18:50:52 +08001236 snd_device = usecase->in_snd_device;
1237 } else {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001238 snd_device = usecase->out_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001239 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001240
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001241#ifdef DS1_DOLBY_DAP_ENABLED
1242 audio_extn_dolby_set_dmid(adev);
1243 audio_extn_dolby_set_endpoint(adev);
1244#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001245 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001246 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301247 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001248 audio_extn_utils_send_app_type_cfg(adev, usecase);
Jasmine Cha4dcc1092019-03-04 18:12:47 +08001249 if (audio_extn_is_maxx_audio_enabled())
1250 audio_extn_ma_set_device(usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301251 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +05301252 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1253 out = usecase->stream.out;
1254 if (out && out->compr)
1255 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1256 }
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301257
1258 if (usecase->type == PCM_CAPTURE) {
1259 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001260 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301261 ALOGD("%s: set custom mtmx params v1", __func__);
1262 audio_extn_set_custom_mtmx_params_v1(adev, usecase, true);
1263 }
1264 } else {
1265 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
1266 }
Manish Dewangan58229382017-02-02 15:48:41 +05301267
Andy Hung756ecc12018-10-19 17:47:12 -07001268 // we shouldn't truncate mixer_path
1269 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1270 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1271 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001272 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001273 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301274 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1275 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1276 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1277 if (parms) {
1278 audio_extn_fm_set_parameters(adev, parms);
1279 str_parms_destroy(parms);
1280 }
1281 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001282 ALOGV("%s: exit", __func__);
1283 return 0;
1284}
1285
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001286int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001287 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001288{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001289 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001290 char mixer_path[MIXER_PATH_MAX_LENGTH];
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301291 struct stream_in *in = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001292
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301293 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001294 return -EINVAL;
1295
1296 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301297 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001298 snd_device = usecase->in_snd_device;
1299 else
1300 snd_device = usecase->out_snd_device;
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001301
1302 /* disable island and power mode on supported device for voice call */
1303 if (usecase->type == VOICE_CALL) {
1304 if (usecase->in_snd_device != SND_DEVICE_NONE) {
1305 if (platform_get_island_cfg_on_device(adev->platform, usecase->in_snd_device) &&
1306 platform_get_power_mode_on_device(adev->platform, usecase->in_snd_device)) {
1307 platform_set_island_cfg_on_device(adev, usecase->in_snd_device, false);
1308 platform_set_power_mode_on_device(adev, usecase->in_snd_device, false);
1309 platform_reset_island_power_status(adev->platform, usecase->in_snd_device);
Kunlei Zhang91c4b332020-07-20 17:53:14 +08001310 if (voice_is_lte_call_active(adev))
1311 platform_set_tx_lpi_mode(adev->platform, false);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001312 ALOGD("%s: disable island cfg and power mode in voice tx path",
1313 __func__);
1314 }
1315 }
1316 if (usecase->out_snd_device != SND_DEVICE_NONE) {
1317 if (platform_get_island_cfg_on_device(adev->platform, usecase->out_snd_device) &&
1318 platform_get_power_mode_on_device(adev->platform, usecase->out_snd_device)) {
1319 platform_set_island_cfg_on_device(adev, usecase->out_snd_device, false);
1320 platform_set_power_mode_on_device(adev, usecase->out_snd_device, false);
1321 platform_reset_island_power_status(adev->platform, usecase->out_snd_device);
1322 ALOGD("%s: disable island cfg and power mode in voice rx path",
1323 __func__);
1324 }
1325 }
1326 }
1327
Andy Hung756ecc12018-10-19 17:47:12 -07001328 // we shouldn't truncate mixer_path
1329 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1330 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1331 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001332 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001333 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001334 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Carter Hsu2e429db2019-05-14 18:50:52 +08001335 if (usecase->type == PCM_CAPTURE) {
1336 struct stream_in *in = usecase->stream.in;
1337 if (in && in->ec_opened) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001338 struct listnode out_devices;
1339 list_init(&out_devices);
1340 platform_set_echo_reference(in->dev, false, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001341 in->ec_opened = false;
1342 }
1343 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001344 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301345 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301346
1347 if (usecase->type == PCM_CAPTURE) {
1348 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001349 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301350 ALOGD("%s: reset custom mtmx params v1", __func__);
1351 audio_extn_set_custom_mtmx_params_v1(adev, usecase, false);
1352 }
1353 } else {
1354 audio_extn_set_custom_mtmx_params_v2(adev, usecase, false);
1355 }
1356
Weiyin Jiang298ffd92019-06-03 14:29:30 +08001357 if ((usecase->type == PCM_PLAYBACK) &&
1358 (usecase->stream.out != NULL))
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05301359 usecase->stream.out->pspd_coeff_sent = false;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301360
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001361 ALOGV("%s: exit", __func__);
1362 return 0;
1363}
1364
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001365int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001366 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001367{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301368 int i, num_devices = 0;
1369 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001370 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1371
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001372 if (snd_device < SND_DEVICE_MIN ||
1373 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001374 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001375 return -EINVAL;
1376 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001377
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001378 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001379 ALOGE("%s: Invalid sound device returned", __func__);
1380 return -EINVAL;
1381 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001382
1383 adev->snd_dev_ref_cnt[snd_device]++;
1384
1385 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1386 (platform_split_snd_device(adev->platform,
1387 snd_device,
1388 &num_devices,
1389 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001390 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001391 __func__, snd_device, device_name);
Aniket Kumar Lata990de552019-07-11 14:20:23 -07001392 /* Set backend config for A2DP to ensure slimbus configuration
1393 is correct if A2DP is already active and backend is closed
1394 and re-opened */
1395 if (snd_device == SND_DEVICE_OUT_BT_A2DP)
1396 audio_extn_a2dp_set_source_backend_cfg();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001397 return 0;
1398 }
1399
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001400 if (audio_extn_spkr_prot_is_enabled())
1401 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001402
Aalique Grahame22e49102018-12-18 14:23:57 -08001403 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1404
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001405 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1406 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001407 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1408 goto err;
1409 }
1410 audio_extn_dev_arbi_acquire(snd_device);
1411 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001412 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001413 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001414 goto err;
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001415 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001416 } else if (platform_split_snd_device(adev->platform,
1417 snd_device,
1418 &num_devices,
1419 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301420 for (i = 0; i < num_devices; i++) {
1421 enable_snd_device(adev, new_snd_devices[i]);
1422 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001423 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001424 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001425 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301426
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001427 /* enable island and power mode on supported device */
1428 if (platform_get_island_cfg_on_device(adev->platform, snd_device) &&
1429 platform_get_power_mode_on_device(adev->platform, snd_device)) {
1430 platform_set_island_cfg_on_device(adev, snd_device, true);
1431 platform_set_power_mode_on_device(adev, snd_device, true);
Kunlei Zhang91c4b332020-07-20 17:53:14 +08001432 if (voice_is_lte_call_active(adev) &&
1433 (snd_device >= SND_DEVICE_IN_BEGIN &&
1434 snd_device < SND_DEVICE_IN_END))
1435 platform_set_tx_lpi_mode(adev->platform, true);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001436 ALOGD("%s: enable island cfg and power mode on: %s",
1437 __func__, device_name);
1438 }
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301439
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301440 if (SND_DEVICE_OUT_BT_A2DP == snd_device) {
1441 if (audio_extn_a2dp_start_playback() < 0) {
1442 ALOGE(" fail to configure A2dp Source control path ");
1443 goto err;
1444 } else {
1445 adev->a2dp_started = true;
1446 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001447 }
Florian Pfister1a84f312018-07-19 14:38:18 +02001448
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001449 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1450 (audio_extn_a2dp_start_capture() < 0)) {
1451 ALOGE(" fail to configure A2dp Sink control path ");
1452 goto err;
1453 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301454
Mingshu Pang7be5b1d2020-03-04 15:24:38 +08001455 if ((SND_DEVICE_OUT_BT_SCO_SWB == snd_device) ||
1456 (SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC == snd_device) ||
1457 (SND_DEVICE_IN_BT_SCO_MIC_SWB == snd_device)) {
1458 if (!adev->bt_sco_on || (audio_extn_sco_start_configuration() < 0)) {
1459 ALOGE(" fail to configure sco control path ");
1460 goto err;
1461 }
Zhou Song12c29502019-03-16 10:37:18 +08001462 }
1463
Zhou Song331c8e52019-08-26 14:16:12 +08001464 configure_btsco_sample_rate(snd_device);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001465 /* due to the possibility of calibration overwrite between listen
1466 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001467 audio_extn_sound_trigger_update_device_status(snd_device,
1468 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301469 audio_extn_listen_update_device_status(snd_device,
1470 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001471 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001472 audio_extn_sound_trigger_update_device_status(snd_device,
1473 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301474 audio_extn_listen_update_device_status(snd_device,
1475 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001476 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001477 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001478 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001479 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301480
1481 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1482 !adev->native_playback_enabled &&
1483 audio_is_true_native_stream_active(adev)) {
1484 ALOGD("%s: %d: napb: enabling native mode in hardware",
1485 __func__, __LINE__);
1486 audio_route_apply_and_update_path(adev->audio_route,
1487 "true-native-mode");
1488 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301489 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301490 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1491 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001492 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001493 ALOGD("%s: init ec ref loopback", __func__);
1494 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1495 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001496 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001497 return 0;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001498err:
1499 adev->snd_dev_ref_cnt[snd_device]--;
1500 return -EINVAL;;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001501}
1502
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001503int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001504 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001505{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301506 int i, num_devices = 0;
1507 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001508 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1509
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001510 if (snd_device < SND_DEVICE_MIN ||
1511 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001512 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001513 return -EINVAL;
1514 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001515
1516 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1517 ALOGE("%s: Invalid sound device returned", __func__);
1518 return -EINVAL;
1519 }
1520
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001521 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1522 ALOGE("%s: device ref cnt is already 0", __func__);
1523 return -EINVAL;
1524 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001525
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001526 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001527
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001528
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001529 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001530 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301531
Aalique Grahame22e49102018-12-18 14:23:57 -08001532 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1533
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001534 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1535 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001536 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001537
1538 // when speaker device is disabled, reset swap.
1539 // will be renabled on usecase start
1540 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001541 } else if (platform_split_snd_device(adev->platform,
1542 snd_device,
1543 &num_devices,
1544 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301545 for (i = 0; i < num_devices; i++) {
1546 disable_snd_device(adev, new_snd_devices[i]);
1547 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001548 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001549 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001550 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001551 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001552
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301553 if (snd_device == SND_DEVICE_OUT_BT_A2DP) {
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301554 audio_extn_a2dp_stop_playback();
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301555 adev->a2dp_started = false;
1556 } else if (snd_device == SND_DEVICE_IN_BT_A2DP)
Florian Pfister1a84f312018-07-19 14:38:18 +02001557 audio_extn_a2dp_stop_capture();
Zhou Songd6d71752019-05-21 18:08:51 +08001558 else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001559 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
Ashish Jain81eb2a82015-05-13 10:52:34 +05301560 adev->is_channel_status_set = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001561 else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301562 adev->native_playback_enabled) {
1563 ALOGD("%s: %d: napb: disabling native mode in hardware",
1564 __func__, __LINE__);
1565 audio_route_reset_and_update_path(adev->audio_route,
1566 "true-native-mode");
1567 adev->native_playback_enabled = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001568 } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301569 adev->asrc_mode_enabled) {
1570 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301571 disable_asrc_mode(adev);
1572 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001573 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301574 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001575 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001576 ALOGD("%s: deinit ec ref loopback", __func__);
1577 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1578 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001579
1580 audio_extn_utils_release_snd_device(snd_device);
1581 } else {
1582 if (platform_split_snd_device(adev->platform,
1583 snd_device,
1584 &num_devices,
1585 new_snd_devices) == 0) {
1586 for (i = 0; i < num_devices; i++) {
1587 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1588 }
1589 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001590 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001591
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001592 return 0;
1593}
1594
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001595/*
1596 legend:
1597 uc - existing usecase
1598 new_uc - new usecase
1599 d1, d11, d2 - SND_DEVICE enums
1600 a1, a2 - corresponding ANDROID device enums
1601 B1, B2 - backend strings
1602
1603case 1
1604 uc->dev d1 (a1) B1
1605 new_uc->dev d1 (a1), d2 (a2) B1, B2
1606
1607 resolution: disable and enable uc->dev on d1
1608
1609case 2
1610 uc->dev d1 (a1) B1
1611 new_uc->dev d11 (a1) B1
1612
1613 resolution: need to switch uc since d1 and d11 are related
1614 (e.g. speaker and voice-speaker)
1615 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1616
1617case 3
1618 uc->dev d1 (a1) B1
1619 new_uc->dev d2 (a2) B2
1620
1621 resolution: no need to switch uc
1622
1623case 4
1624 uc->dev d1 (a1) B1
1625 new_uc->dev d2 (a2) B1
1626
1627 resolution: disable enable uc-dev on d2 since backends match
1628 we cannot enable two streams on two different devices if they
1629 share the same backend. e.g. if offload is on speaker device using
1630 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1631 using the same backend, offload must also be switched to voice-handset.
1632
1633case 5
1634 uc->dev d1 (a1) B1
1635 new_uc->dev d1 (a1), d2 (a2) B1
1636
1637 resolution: disable enable uc-dev on d2 since backends match
1638 we cannot enable two streams on two different devices if they
1639 share the same backend.
1640
1641case 6
1642 uc->dev d1 (a1) B1
1643 new_uc->dev d2 (a1) B2
1644
1645 resolution: no need to switch
1646
1647case 7
1648 uc->dev d1 (a1), d2 (a2) B1, B2
1649 new_uc->dev d1 (a1) B1
1650
1651 resolution: no need to switch
1652
Zhou Song4ba65882018-07-09 14:48:07 +08001653case 8
1654 uc->dev d1 (a1) B1
1655 new_uc->dev d11 (a1), d2 (a2) B1, B2
1656 resolution: compared to case 1, for this case, d1 and d11 are related
1657 then need to do the same as case 2 to siwtch to new uc
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301658
1659case 9
1660 uc->dev d1 (a1), d2(a2) B1 B2
1661 new_uc->dev d1 (a1), d22 (a2) B1, B2
1662 resolution: disable enable uc-dev on d2 since backends match
1663 we cannot enable two streams on two different devices if they
1664 share the same backend. This is special case for combo use case
1665 with a2dp and sco devices which uses same backend.
1666 e.g. speaker-a2dp and speaker-btsco
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001667*/
1668static snd_device_t derive_playback_snd_device(void * platform,
1669 struct audio_usecase *uc,
1670 struct audio_usecase *new_uc,
1671 snd_device_t new_snd_device)
1672{
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001673 struct listnode a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001674
1675 snd_device_t d1 = uc->out_snd_device;
1676 snd_device_t d2 = new_snd_device;
1677
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001678 list_init(&a1);
1679 list_init(&a2);
1680
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301681 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301682 case TRANSCODE_LOOPBACK_RX :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001683 assign_devices(&a1, &uc->stream.inout->out_config.device_list);
1684 assign_devices(&a2, &new_uc->stream.inout->out_config.device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301685 break;
1686 default :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001687 assign_devices(&a1, &uc->stream.out->device_list);
1688 assign_devices(&a2, &new_uc->stream.out->device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301689 break;
1690 }
1691
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001692 // Treat as a special case when a1 and a2 are not disjoint
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001693 if (!compare_devices(&a1, &a2) &&
1694 compare_devices_for_any_match(&a1 ,&a2)) {
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001695 snd_device_t d3[2];
1696 int num_devices = 0;
1697 int ret = platform_split_snd_device(platform,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001698 list_length(&a1) > 1 ? d1 : d2,
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001699 &num_devices,
1700 d3);
1701 if (ret < 0) {
1702 if (ret != -ENOSYS) {
1703 ALOGW("%s failed to split snd_device %d",
1704 __func__,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001705 list_length(&a1) > 1 ? d1 : d2);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001706 }
1707 goto end;
1708 }
1709
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001710 if (platform_check_backends_match(d3[0], d3[1])) {
1711 return d2; // case 5
1712 } else {
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301713 if ((list_length(&a1) > 1) && (list_length(&a2) > 1) &&
1714 platform_check_backends_match(d1, d2))
1715 return d2; //case 9
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001716 if (list_length(&a1) > 1)
Samyak Jaind826b502019-07-17 16:16:42 +05301717 return d1; //case 7
Garmond Leungb9eeba42018-09-18 11:10:41 -07001718 // check if d1 is related to any of d3's
1719 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001720 return d1; // case 1
1721 else
1722 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001723 }
1724 } else {
1725 if (platform_check_backends_match(d1, d2)) {
1726 return d2; // case 2, 4
1727 } else {
1728 return d1; // case 6, 3
1729 }
1730 }
1731
1732end:
1733 return d2; // return whatever was calculated before.
1734}
1735
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001736static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301737 struct audio_usecase *uc_info,
1738 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001739{
1740 struct listnode *node;
1741 struct audio_usecase *usecase;
1742 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301743 snd_device_t uc_derive_snd_device;
1744 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001745 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1746 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001747 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301748 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001749 /*
1750 * This function is to make sure that all the usecases that are active on
1751 * the hardware codec backend are always routed to any one device that is
1752 * handled by the hardware codec.
1753 * For example, if low-latency and deep-buffer usecases are currently active
1754 * on speaker and out_set_parameters(headset) is received on low-latency
1755 * output, then we have to make sure deep-buffer is also switched to headset,
1756 * because of the limitation that both the devices cannot be enabled
1757 * at the same time as they share the same backend.
1758 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001759 /*
1760 * This call is to check if we need to force routing for a particular stream
1761 * If there is a backend configuration change for the device when a
1762 * new stream starts, then ADM needs to be closed and re-opened with the new
1763 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001764 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001765 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001766 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1767 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301768 /* For a2dp device reconfigure all active sessions
1769 * with new AFE encoder format based on a2dp state
1770 */
1771 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301772 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device ||
1773 SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP == snd_device) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301774 audio_extn_a2dp_is_force_device_switch()) {
1775 force_routing = true;
1776 force_restart_session = true;
1777 }
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001778
1779 /*
1780 * Island cfg and power mode config needs to set before AFE port start.
1781 * Set force routing in case of voice device was enable before.
1782 */
1783 if (uc_info->type == VOICE_CALL &&
1784 voice_extn_is_voice_power_mode_supported() &&
1785 platform_check_and_update_island_power_status(adev->platform,
1786 uc_info,
1787 snd_device)) {
1788 force_routing = true;
1789 ALOGD("%s:becf: force routing %d for power mode supported device",
1790 __func__, force_routing);
1791 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301792 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1793
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001794 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001795 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001796 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001797 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1798 switch_device[i] = false;
1799
1800 list_for_each(node, &adev->usecase_list) {
1801 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001802
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301803 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1804 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301805 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301806 platform_get_snd_device_name(usecase->out_snd_device),
1807 platform_check_backends_match(snd_device, usecase->out_snd_device));
Rahul Sharma99770982019-03-06 17:05:26 +05301808 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
1809 (usecase->type != PCM_PASSTHROUGH)) {
Ashish Jain6a65b352017-03-21 17:24:40 +05301810 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1811 usecase, uc_info, snd_device);
1812 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001813 (is_codec_backend_out_device_type(&usecase->device_list) ||
1814 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1815 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_DEVICE) ||
1816 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_HEADSET) ||
1817 is_a2dp_out_device_type(&usecase->device_list) ||
1818 is_sco_out_device_type(&usecase->device_list)) &&
Ashish Jain6a65b352017-03-21 17:24:40 +05301819 ((force_restart_session) ||
1820 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301821 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1822 __func__, use_case_table[usecase->id],
1823 platform_get_snd_device_name(usecase->out_snd_device));
1824 disable_audio_route(adev, usecase);
1825 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301826 /* Enable existing usecase on derived playback device */
1827 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301828 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301829 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001830 }
1831 }
1832
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301833 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1834 num_uc_to_switch);
1835
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001836 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001837 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001838
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301839 /* Make sure the previous devices to be disabled first and then enable the
1840 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001841 list_for_each(node, &adev->usecase_list) {
1842 usecase = node_to_item(node, struct audio_usecase, list);
1843 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001844 /* Check if output sound device to be switched can be split and if any
1845 of the split devices match with derived sound device */
1846 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1847 &num_devices, split_snd_devices) == 0) {
1848 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
1849 for (i = 0; i < num_devices; i++) {
1850 /* Disable devices that do not match with derived sound device */
1851 if (split_snd_devices[i] != derive_snd_device[usecase->id])
1852 disable_snd_device(adev, split_snd_devices[i]);
1853 }
1854 } else {
1855 disable_snd_device(adev, usecase->out_snd_device);
1856 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001857 }
1858 }
1859
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001860 list_for_each(node, &adev->usecase_list) {
1861 usecase = node_to_item(node, struct audio_usecase, list);
1862 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001863 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1864 &num_devices, split_snd_devices) == 0) {
1865 /* Enable derived sound device only if it does not match with
1866 one of the split sound devices. This is because the matching
1867 sound device was not disabled */
1868 bool should_enable = true;
1869 for (i = 0; i < num_devices; i++) {
1870 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
1871 should_enable = false;
1872 break;
1873 }
1874 }
1875 if (should_enable)
1876 enable_snd_device(adev, derive_snd_device[usecase->id]);
1877 } else {
1878 enable_snd_device(adev, derive_snd_device[usecase->id]);
1879 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001880 }
1881 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001882
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001883 /* Re-route all the usecases on the shared backend other than the
1884 specified usecase to new snd devices */
1885 list_for_each(node, &adev->usecase_list) {
1886 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301887 /* Update the out_snd_device only before enabling the audio route */
1888 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301889 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301890 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301891 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301892 use_case_table[usecase->id],
1893 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001894 /* Update voc calibration before enabling VoIP route */
1895 if (usecase->type == VOIP_CALL)
1896 status = platform_switch_voice_call_device_post(adev->platform,
Eric Laurent637e2d42018-11-15 12:24:31 -08001897 usecase->out_snd_device,
1898 platform_get_input_snd_device(
1899 adev->platform, NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05301900 &uc_info->device_list,
1901 usecase->type));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301902 enable_audio_route(adev, usecase);
Sujin Panicker390724d2019-04-26 10:43:36 +05301903 if (usecase->stream.out && usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
kunleiz46c47dd2018-03-19 16:28:09 +08001904 out_set_voip_volume(&usecase->stream.out->stream,
1905 usecase->stream.out->volume_l,
1906 usecase->stream.out->volume_r);
1907 }
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301908 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001909 }
1910 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001911 }
1912}
1913
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301914static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001915 struct audio_usecase *uc_info,
1916 snd_device_t snd_device)
1917{
1918 struct listnode *node;
1919 struct audio_usecase *usecase;
1920 bool switch_device[AUDIO_USECASE_MAX];
1921 int i, num_uc_to_switch = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001922 int backend_check_cond = is_codec_backend_out_device_type(&uc_info->device_list);
kunleiz5cd52b82016-11-07 17:22:52 +08001923 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001924
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301925 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1926 snd_device);
1927 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301928
1929 /*
1930 * Make sure out devices is checked against out codec backend device and
1931 * also in devices against in codec backend. Checking out device against in
1932 * codec backend or vice versa causes issues.
1933 */
1934 if (uc_info->type == PCM_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001935 backend_check_cond = is_codec_backend_in_device_type(&uc_info->device_list);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001936
1937 /*
1938 * Island cfg and power mode config needs to set before AFE port start.
1939 * Set force routing in case of voice device was enable before.
1940 */
1941
1942 if (uc_info->type == VOICE_CALL &&
1943 voice_extn_is_voice_power_mode_supported() &&
1944 platform_check_and_update_island_power_status(adev->platform,
1945 uc_info,
1946 snd_device)) {
1947 force_routing = true;
1948 ALOGD("%s:becf: force routing %d for power mode supported device",
1949 __func__, force_routing);
1950 }
1951
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001952 /*
1953 * This function is to make sure that all the active capture usecases
1954 * are always routed to the same input sound device.
1955 * For example, if audio-record and voice-call usecases are currently
1956 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1957 * is received for voice call then we have to make sure that audio-record
1958 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1959 * because of the limitation that two devices cannot be enabled
1960 * at the same time if they share the same backend.
1961 */
1962 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1963 switch_device[i] = false;
1964
1965 list_for_each(node, &adev->usecase_list) {
1966 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301967 /*
1968 * TODO: Enhance below condition to handle BT sco/USB multi recording
1969 */
Jaideep Sharma477917f2020-03-13 18:13:33 +05301970
1971 bool capture_uc_needs_routing = usecase->type != PCM_PLAYBACK && (usecase != uc_info &&
1972 (usecase->in_snd_device != snd_device || force_routing));
1973 bool call_proxy_snd_device = platform_is_call_proxy_snd_device(snd_device) ||
1974 platform_is_call_proxy_snd_device(usecase->in_snd_device);
1975 if (capture_uc_needs_routing && !call_proxy_snd_device &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001976 ((backend_check_cond &&
1977 (is_codec_backend_in_device_type(&usecase->device_list) ||
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08001978 (usecase->type == VOIP_CALL))) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08001979 ((uc_info->type == VOICE_CALL &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001980 is_single_device_type_equal(&usecase->device_list,
1981 AUDIO_DEVICE_IN_VOICE_CALL)) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08001982 platform_check_backends_match(snd_device,\
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001983 usecase->in_snd_device))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001984 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05301985 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..",
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001986 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001987 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001988 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001989 switch_device[usecase->id] = true;
1990 num_uc_to_switch++;
1991 }
1992 }
1993
1994 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001995 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001996
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301997 /* Make sure the previous devices to be disabled first and then enable the
1998 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001999 list_for_each(node, &adev->usecase_list) {
2000 usecase = node_to_item(node, struct audio_usecase, list);
2001 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002002 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08002003 }
2004 }
2005
2006 list_for_each(node, &adev->usecase_list) {
2007 usecase = node_to_item(node, struct audio_usecase, list);
2008 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002009 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002010 }
2011 }
2012
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002013 /* Re-route all the usecases on the shared backend other than the
2014 specified usecase to new snd devices */
2015 list_for_each(node, &adev->usecase_list) {
2016 usecase = node_to_item(node, struct audio_usecase, list);
2017 /* Update the in_snd_device only before enabling the audio route */
2018 if (switch_device[usecase->id] ) {
2019 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08002020 if (usecase->type != VOICE_CALL) {
2021 /* Update voc calibration before enabling VoIP route */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302022 if (usecase->type == VOIP_CALL) {
2023 snd_device_t voip_snd_device;
2024 voip_snd_device = platform_get_output_snd_device(adev->platform,
2025 uc_info->stream.out,
2026 usecase->type);
kunleiz5cd52b82016-11-07 17:22:52 +08002027 status = platform_switch_voice_call_device_post(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302028 voip_snd_device,
kunleiz5cd52b82016-11-07 17:22:52 +08002029 usecase->in_snd_device);
Jaideep Sharma477917f2020-03-13 18:13:33 +05302030 }
Avinash Vaish71a8b972014-07-24 15:36:33 +05302031 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08002032 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002033 }
2034 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002035 }
2036}
2037
Mingming Yin3a941d42016-02-17 18:08:05 -08002038static void reset_hdmi_sink_caps(struct stream_out *out) {
2039 int i = 0;
2040
2041 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
2042 out->supported_channel_masks[i] = 0;
2043 }
2044 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
2045 out->supported_formats[i] = 0;
2046 }
2047 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
2048 out->supported_sample_rates[i] = 0;
2049 }
2050}
2051
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002052/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08002053static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002054{
Mingming Yin3a941d42016-02-17 18:08:05 -08002055 int ret = 0, i = 0, j = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002056 int channels = platform_edid_get_max_channels_v2(out->dev->platform,
2057 out->extconn.cs.controller,
2058 out->extconn.cs.stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002059
Mingming Yin3a941d42016-02-17 18:08:05 -08002060 reset_hdmi_sink_caps(out);
2061
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002062 /* Cache ext disp type */
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002063 ret = platform_get_ext_disp_type_v2(adev->platform,
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002064 out->extconn.cs.controller,
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002065 out->extconn.cs.stream);
2066 if(ret < 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002067 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07002068 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002069 }
2070
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002071 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002072 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08002073 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002074 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08002075 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
2076 case 6:
2077 ALOGV("%s: HDMI supports 5.1 channels", __func__);
2078 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
2079 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
2080 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
2081 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
2082 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002083 break;
2084 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08002085 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002086 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002087 break;
2088 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002089
2090 // check channel format caps
2091 i = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002092 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_AC3,
2093 out->extconn.cs.controller,
2094 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002095 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
2096 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
2097 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
2098 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
2099 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
2100 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
2101 }
2102
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002103 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD,
2104 out->extconn.cs.controller,
2105 out->extconn.cs.stream)) {
Ben Romberger1aaaf862017-04-06 17:49:46 -07002106 ALOGV(":%s HDMI supports TRUE HD format", __func__);
2107 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
2108 }
2109
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002110 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS,
2111 out->extconn.cs.controller,
2112 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002113 ALOGV(":%s HDMI supports DTS format", __func__);
2114 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
2115 }
2116
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002117 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS_HD,
2118 out->extconn.cs.controller,
2119 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002120 ALOGV(":%s HDMI supports DTS HD format", __func__);
2121 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
2122 }
2123
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002124 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_IEC61937,
2125 out->extconn.cs.controller,
2126 out->extconn.cs.stream)) {
Naresh Tanniru928f0862017-04-07 16:44:23 -07002127 ALOGV(":%s HDMI supports IEC61937 format", __func__);
2128 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
2129 }
2130
Mingming Yin3a941d42016-02-17 18:08:05 -08002131
2132 // check sample rate caps
2133 i = 0;
2134 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002135 if (platform_is_edid_supported_sample_rate_v2(out->dev->platform, out_hdmi_sample_rates[j],
2136 out->extconn.cs.controller,
2137 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002138 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
2139 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
2140 }
2141 }
2142
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002143 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002144}
2145
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002146static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
2147 uint32_t *supported_sample_rates __unused,
2148 uint32_t max_rates __unused)
2149{
2150 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
2151 supported_sample_rates,
2152 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05302153 ssize_t i = 0;
2154
2155 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002156 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
2157 supported_sample_rates[i]);
2158 }
2159 return count;
2160}
2161
2162static inline int read_usb_sup_channel_masks(bool is_playback,
2163 audio_channel_mask_t *supported_channel_masks,
2164 uint32_t max_masks)
2165{
2166 int channels = audio_extn_usb_get_max_channels(is_playback);
2167 int channel_count;
2168 uint32_t num_masks = 0;
2169 if (channels > MAX_HIFI_CHANNEL_COUNT)
2170 channels = MAX_HIFI_CHANNEL_COUNT;
2171
2172 if (is_playback) {
Eric Laurent68a87112019-05-01 18:07:29 -07002173 // start from 2 channels as framework currently doesn't support mono.
2174 if (channels >= FCC_2) {
2175 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(FCC_2);
2176 }
2177 for (channel_count = FCC_2;
2178 channel_count <= channels && num_masks < max_masks;
2179 ++channel_count) {
2180 supported_channel_masks[num_masks++] =
2181 audio_channel_mask_for_index_assignment_from_count(channel_count);
2182 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002183 } else {
vincenttewf51c94e2019-05-07 10:28:53 +08002184 // For capture we report all supported channel masks from 1 channel up.
2185 channel_count = MIN_CHANNEL_COUNT;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002186 // audio_channel_in_mask_from_count() does the right conversion to either positional or
2187 // indexed mask
Eric Laurent68a87112019-05-01 18:07:29 -07002188 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
2189 audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
2190 if (channel_count <= FCC_2) {
2191 mask = audio_channel_in_mask_from_count(channel_count);
2192 supported_channel_masks[num_masks++] = mask;
2193 }
2194 const audio_channel_mask_t index_mask =
2195 audio_channel_mask_for_index_assignment_from_count(channel_count);
2196 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
2197 supported_channel_masks[num_masks++] = index_mask;
2198 }
2199 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002200 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302201
vincenttewf51c94e2019-05-07 10:28:53 +08002202 for (size_t i = 0; i < num_masks; ++i) {
2203 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
2204 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302205 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002206 return num_masks;
2207}
2208
2209static inline int read_usb_sup_formats(bool is_playback __unused,
2210 audio_format_t *supported_formats,
2211 uint32_t max_formats __unused)
2212{
2213 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
2214 switch (bitwidth) {
2215 case 24:
2216 // XXX : usb.c returns 24 for s24 and s24_le?
2217 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
2218 break;
2219 case 32:
2220 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
2221 break;
2222 case 16:
2223 default :
2224 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
2225 break;
2226 }
2227 ALOGV("%s: %s supported format %d", __func__,
2228 is_playback ? "P" : "C", bitwidth);
2229 return 1;
2230}
2231
2232static inline int read_usb_sup_params_and_compare(bool is_playback,
2233 audio_format_t *format,
2234 audio_format_t *supported_formats,
2235 uint32_t max_formats,
2236 audio_channel_mask_t *mask,
2237 audio_channel_mask_t *supported_channel_masks,
2238 uint32_t max_masks,
2239 uint32_t *rate,
2240 uint32_t *supported_sample_rates,
2241 uint32_t max_rates) {
2242 int ret = 0;
2243 int num_formats;
2244 int num_masks;
2245 int num_rates;
2246 int i;
2247
2248 num_formats = read_usb_sup_formats(is_playback, supported_formats,
2249 max_formats);
2250 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
2251 max_masks);
2252
2253 num_rates = read_usb_sup_sample_rates(is_playback,
2254 supported_sample_rates, max_rates);
2255
2256#define LUT(table, len, what, dflt) \
2257 for (i=0; i<len && (table[i] != what); i++); \
2258 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
2259
2260 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
2261 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
2262 LUT(supported_sample_rates, num_rates, *rate, 0);
2263
2264#undef LUT
2265 return ret < 0 ? -EINVAL : 0; // HACK TBD
2266}
2267
Alexy Josephb1379942016-01-29 15:49:38 -08002268audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002269 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002270{
2271 struct audio_usecase *usecase;
2272 struct listnode *node;
2273
2274 list_for_each(node, &adev->usecase_list) {
2275 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002276 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002277 ALOGV("%s: usecase id %d", __func__, usecase->id);
2278 return usecase->id;
2279 }
2280 }
2281 return USECASE_INVALID;
2282}
2283
Alexy Josephb1379942016-01-29 15:49:38 -08002284struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002285 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002286{
2287 struct audio_usecase *usecase;
2288 struct listnode *node;
2289
2290 list_for_each(node, &adev->usecase_list) {
2291 usecase = node_to_item(node, struct audio_usecase, list);
2292 if (usecase->id == uc_id)
2293 return usecase;
2294 }
2295 return NULL;
2296}
2297
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302298/*
2299 * is a true native playback active
2300 */
2301bool audio_is_true_native_stream_active(struct audio_device *adev)
2302{
2303 bool active = false;
2304 int i = 0;
2305 struct listnode *node;
2306
2307 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
2308 ALOGV("%s:napb: not in true mode or non hdphones device",
2309 __func__);
2310 active = false;
2311 goto exit;
2312 }
2313
2314 list_for_each(node, &adev->usecase_list) {
2315 struct audio_usecase *uc;
2316 uc = node_to_item(node, struct audio_usecase, list);
2317 struct stream_out *curr_out =
2318 (struct stream_out*) uc->stream.out;
2319
2320 if (curr_out && PCM_PLAYBACK == uc->type) {
2321 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
2322 "(%d) device %s", __func__, i++, use_case_table[uc->id],
2323 uc->id, curr_out->sample_rate,
2324 curr_out->bit_width,
2325 platform_get_snd_device_name(uc->out_snd_device));
2326
2327 if (is_offload_usecase(uc->id) &&
2328 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
2329 active = true;
2330 ALOGD("%s:napb:native stream detected", __func__);
2331 }
2332 }
2333 }
2334exit:
2335 return active;
2336}
2337
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002338uint32_t adev_get_dsp_bit_width_enforce_mode()
2339{
2340 if (adev == NULL) {
2341 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
2342 return 0;
2343 }
2344 return adev->dsp_bit_width_enforce_mode;
2345}
2346
2347static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
2348{
2349 char value[PROPERTY_VALUE_MAX];
2350 int trial;
2351 uint32_t dsp_bit_width_enforce_mode = 0;
2352
2353 if (!mixer) {
2354 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
2355 __func__);
2356 return 0;
2357 }
2358
2359 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
2360 value, NULL) > 0) {
2361 trial = atoi(value);
2362 switch (trial) {
2363 case 16:
2364 dsp_bit_width_enforce_mode = 16;
2365 break;
2366 case 24:
2367 dsp_bit_width_enforce_mode = 24;
2368 break;
2369 case 32:
2370 dsp_bit_width_enforce_mode = 32;
2371 break;
2372 default:
2373 dsp_bit_width_enforce_mode = 0;
2374 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
2375 break;
2376 }
2377 }
2378
2379 return dsp_bit_width_enforce_mode;
2380}
2381
2382static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
2383 uint32_t enforce_mode,
2384 bool enable)
2385{
2386 struct mixer_ctl *ctl = NULL;
2387 const char *mixer_ctl_name = "ASM Bit Width";
2388 uint32_t asm_bit_width_mode = 0;
2389
2390 if (enforce_mode == 0) {
2391 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
2392 return;
2393 }
2394
2395 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
2396 if (!ctl) {
2397 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2398 __func__, mixer_ctl_name);
2399 return;
2400 }
2401
2402 if (enable)
2403 asm_bit_width_mode = enforce_mode;
2404 else
2405 asm_bit_width_mode = 0;
2406
2407 ALOGV("%s DSP bit width feature status is %d width=%d",
2408 __func__, enable, asm_bit_width_mode);
2409 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2410 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2411 asm_bit_width_mode);
2412
2413 return;
2414}
2415
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302416/*
2417 * if native DSD playback active
2418 */
2419bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2420{
2421 bool active = false;
2422 struct listnode *node = NULL;
2423 struct audio_usecase *uc = NULL;
2424 struct stream_out *curr_out = NULL;
2425
2426 list_for_each(node, &adev->usecase_list) {
2427 uc = node_to_item(node, struct audio_usecase, list);
2428 curr_out = (struct stream_out*) uc->stream.out;
2429
2430 if (curr_out && PCM_PLAYBACK == uc->type &&
2431 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2432 active = true;
2433 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302434 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302435 }
2436 }
2437 return active;
2438}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302439
2440static bool force_device_switch(struct audio_usecase *usecase)
2441{
2442 bool ret = false;
2443 bool is_it_true_mode = false;
2444
Zhou Song30f2c3e2018-02-08 14:02:15 +08002445 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302446 usecase->type == TRANSCODE_LOOPBACK_RX ||
2447 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002448 return false;
2449 }
2450
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002451 if(usecase->stream.out == NULL) {
2452 ALOGE("%s: stream.out is NULL", __func__);
2453 return false;
2454 }
2455
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302456 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002457 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002458 (compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADSET) ||
2459 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADPHONE))) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302460 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2461 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2462 (!is_it_true_mode && adev->native_playback_enabled)){
2463 ret = true;
2464 ALOGD("napb: time to toggle native mode");
2465 }
2466 }
2467
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302468 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302469 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2470 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002471 if(is_a2dp_out_device_type(&usecase->stream.out->device_list) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302472 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302473 ALOGD("Force a2dp device switch to update new encoder config");
2474 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002475 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302476
Florian Pfister1a84f312018-07-19 14:38:18 +02002477 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302478 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2479 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002480 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302481 return ret;
2482}
2483
Aalique Grahame22e49102018-12-18 14:23:57 -08002484static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2485{
2486 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2487}
2488
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302489bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2490{
2491 bool ret=false;
2492 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
Zhou Song5657f492019-08-07 11:30:39 +08002493 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
2494 out_snd_device == SND_DEVICE_OUT_BT_SCO_SWB) ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302495 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2496 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
Zhou Song5657f492019-08-07 11:30:39 +08002497 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302498 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
Mingshu Pang16093502020-04-20 11:21:16 +08002499 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC ||
2500 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC)
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302501 ret = true;
2502
2503 return ret;
2504}
2505
2506bool is_a2dp_device(snd_device_t out_snd_device)
2507{
2508 bool ret=false;
2509 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2510 ret = true;
2511
2512 return ret;
2513}
2514
2515bool is_bt_soc_on(struct audio_device *adev)
2516{
2517 struct mixer_ctl *ctl;
2518 char *mixer_ctl_name = "BT SOC status";
2519 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2520 bool bt_soc_status = true;
2521 if (!ctl) {
2522 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2523 __func__, mixer_ctl_name);
2524 /*This is to ensure we dont break targets which dont have the kernel change*/
2525 return true;
2526 }
2527 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2528 ALOGD("BT SOC status: %d",bt_soc_status);
2529 return bt_soc_status;
2530}
2531
Zhou Song331c8e52019-08-26 14:16:12 +08002532static int configure_btsco_sample_rate(snd_device_t snd_device)
2533{
2534 struct mixer_ctl *ctl = NULL;
2535 struct mixer_ctl *ctl_sr_rx = NULL, *ctl_sr_tx = NULL, *ctl_sr = NULL;
2536 char *rate_str = NULL;
2537 bool is_rx_dev = true;
2538
2539 if (is_btsco_device(snd_device, snd_device)) {
2540 ctl_sr_tx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate TX");
2541 ctl_sr_rx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate RX");
2542 if (!ctl_sr_tx || !ctl_sr_rx) {
2543 ctl_sr = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate");
2544 if (!ctl_sr)
2545 return -ENOSYS;
2546 }
2547
2548 switch (snd_device) {
2549 case SND_DEVICE_OUT_BT_SCO:
2550 rate_str = "KHZ_8";
2551 break;
2552 case SND_DEVICE_IN_BT_SCO_MIC_NREC:
2553 case SND_DEVICE_IN_BT_SCO_MIC:
2554 rate_str = "KHZ_8";
2555 is_rx_dev = false;
2556 break;
2557 case SND_DEVICE_OUT_BT_SCO_WB:
2558 rate_str = "KHZ_16";
2559 break;
2560 case SND_DEVICE_IN_BT_SCO_MIC_WB_NREC:
2561 case SND_DEVICE_IN_BT_SCO_MIC_WB:
2562 rate_str = "KHZ_16";
2563 is_rx_dev = false;
2564 break;
2565 default:
2566 return 0;
2567 }
2568
2569 ctl = (ctl_sr == NULL) ? (is_rx_dev ? ctl_sr_rx : ctl_sr_tx) : ctl_sr;
2570 if (mixer_ctl_set_enum_by_string(ctl, rate_str) != 0)
2571 return -ENOSYS;
2572 }
2573 return 0;
2574}
2575
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302576int out_standby_l(struct audio_stream *stream);
2577
Eric Laurent637e2d42018-11-15 12:24:31 -08002578struct stream_in *adev_get_active_input(const struct audio_device *adev)
2579{
2580 struct listnode *node;
2581 struct stream_in *last_active_in = NULL;
2582
2583 /* Get last added active input.
2584 * TODO: We may use a priority mechanism to pick highest priority active source */
2585 list_for_each(node, &adev->usecase_list)
2586 {
2587 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2588 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL)
2589 last_active_in = usecase->stream.in;
2590 }
2591
2592 return last_active_in;
2593}
2594
2595struct stream_in *get_voice_communication_input(const struct audio_device *adev)
2596{
2597 struct listnode *node;
2598
2599 /* First check active inputs with voice communication source and then
2600 * any input if audio mode is in communication */
2601 list_for_each(node, &adev->usecase_list)
2602 {
2603 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2604 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
2605 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
2606 return usecase->stream.in;
2607 }
2608 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION)
2609 return adev_get_active_input(adev);
2610
2611 return NULL;
2612}
2613
Carter Hsu2e429db2019-05-14 18:50:52 +08002614/*
2615 * Aligned with policy.h
2616 */
2617static inline int source_priority(int inputSource)
2618{
2619 switch (inputSource) {
2620 case AUDIO_SOURCE_VOICE_COMMUNICATION:
2621 return 9;
2622 case AUDIO_SOURCE_CAMCORDER:
2623 return 8;
2624 case AUDIO_SOURCE_VOICE_PERFORMANCE:
2625 return 7;
2626 case AUDIO_SOURCE_UNPROCESSED:
2627 return 6;
2628 case AUDIO_SOURCE_MIC:
2629 return 5;
2630 case AUDIO_SOURCE_ECHO_REFERENCE:
2631 return 4;
2632 case AUDIO_SOURCE_FM_TUNER:
2633 return 3;
2634 case AUDIO_SOURCE_VOICE_RECOGNITION:
2635 return 2;
2636 case AUDIO_SOURCE_HOTWORD:
2637 return 1;
2638 default:
2639 break;
2640 }
2641 return 0;
2642}
2643
2644static struct stream_in *get_priority_input(struct audio_device *adev)
2645{
2646 struct listnode *node;
2647 struct audio_usecase *usecase;
2648 int last_priority = 0, priority;
2649 struct stream_in *priority_in = NULL;
2650 struct stream_in *in;
2651
2652 list_for_each(node, &adev->usecase_list) {
2653 usecase = node_to_item(node, struct audio_usecase, list);
2654 if (usecase->type == PCM_CAPTURE) {
2655 in = usecase->stream.in;
2656 if (!in)
2657 continue;
2658 priority = source_priority(in->source);
2659
2660 if (priority > last_priority) {
2661 last_priority = priority;
2662 priority_in = in;
2663 }
2664 }
2665 }
2666 return priority_in;
2667}
2668
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002669int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002670{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002671 snd_device_t out_snd_device = SND_DEVICE_NONE;
2672 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002673 struct audio_usecase *usecase = NULL;
2674 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002675 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002676 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302677 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002678 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002679 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002680
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302681 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2682
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002683 usecase = get_usecase_from_list(adev, uc_id);
2684 if (usecase == NULL) {
2685 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2686 return -EINVAL;
2687 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002688
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002689 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002690 (usecase->type == VOIP_CALL) ||
2691 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302692 if(usecase->stream.out == NULL) {
2693 ALOGE("%s: stream.out is NULL", __func__);
2694 return -EINVAL;
2695 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002696 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS)) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002697 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev,
2698 uc_id);
2699 in_snd_device = audio_extn_auto_hal_get_input_snd_device(adev,
2700 uc_id);
2701 } else {
2702 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302703 usecase->stream.out, usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002704 in_snd_device = platform_get_input_snd_device(adev->platform,
2705 NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302706 &usecase->stream.out->device_list,
2707 usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002708 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002709 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302710 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302711 if (usecase->stream.inout == NULL) {
2712 ALOGE("%s: stream.inout is NULL", __func__);
2713 return -EINVAL;
2714 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002715 assign_devices(&stream_out.device_list, &usecase->stream.inout->out_config.device_list);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302716 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2717 stream_out.format = usecase->stream.inout->out_config.format;
2718 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
Jaideep Sharma477917f2020-03-13 18:13:33 +05302719 out_snd_device = platform_get_output_snd_device(adev->platform, &stream_out, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002720 assign_devices(&usecase->device_list,
2721 &usecase->stream.inout->out_config.device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302722 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2723 if (usecase->stream.inout == NULL) {
2724 ALOGE("%s: stream.inout is NULL", __func__);
2725 return -EINVAL;
2726 }
Manisha Agarwal03297972020-04-17 15:36:55 +05302727 struct listnode out_devices;
2728 list_init(&out_devices);
2729 in_snd_device = platform_get_input_snd_device(adev->platform, NULL,
2730 &out_devices, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002731 assign_devices(&usecase->device_list,
2732 &usecase->stream.inout->in_config.device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002733 } else {
2734 /*
2735 * If the voice call is active, use the sound devices of voice call usecase
2736 * so that it would not result any device switch. All the usecases will
2737 * be switched to new device when select_devices() is called for voice call
2738 * usecase. This is to avoid switching devices for voice call when
2739 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002740 * choose voice call device only if the use case device is
2741 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002742 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002743 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002744 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002745 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002746 if ((vc_usecase) && ((is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2747 is_codec_backend_out_device_type(&usecase->device_list)) ||
2748 (is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2749 is_codec_backend_in_device_type(&usecase->device_list)) ||
2750 is_single_device_type_equal(&vc_usecase->device_list,
2751 AUDIO_DEVICE_OUT_HEARING_AID) ||
2752 is_single_device_type_equal(&usecase->device_list,
Robert Lee8a6aaf32019-09-20 16:40:19 +08002753 AUDIO_DEVICE_IN_VOICE_CALL) ||
2754 (is_single_device_type_equal(&usecase->device_list,
2755 AUDIO_DEVICE_IN_USB_HEADSET) &&
2756 is_single_device_type_equal(&vc_usecase->device_list,
2757 AUDIO_DEVICE_OUT_USB_HEADSET)))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002758 in_snd_device = vc_usecase->in_snd_device;
2759 out_snd_device = vc_usecase->out_snd_device;
2760 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002761 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002762 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002763 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002764 if ((voip_usecase != NULL) &&
2765 (usecase->type == PCM_PLAYBACK) &&
2766 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002767 out_snd_device_backend_match = platform_check_backends_match(
2768 voip_usecase->out_snd_device,
2769 platform_get_output_snd_device(
2770 adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302771 usecase->stream.out, usecase->type));
yidongh02ef86f2017-04-21 15:36:04 +08002772 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002773 if ((voip_usecase) && (is_codec_backend_out_device_type(&voip_usecase->device_list) &&
2774 (is_codec_backend_out_device_type(&usecase->device_list) ||
2775 is_codec_backend_in_device_type(&usecase->device_list)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002776 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002777 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002778 in_snd_device = voip_usecase->in_snd_device;
2779 out_snd_device = voip_usecase->out_snd_device;
2780 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002781 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002782 hfp_ucid = audio_extn_hfp_get_usecase();
2783 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002784 if ((hfp_usecase) && is_codec_backend_out_device_type(&hfp_usecase->device_list)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002785 in_snd_device = hfp_usecase->in_snd_device;
2786 out_snd_device = hfp_usecase->out_snd_device;
2787 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002788 }
2789 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302790 if (usecase->stream.out == NULL) {
2791 ALOGE("%s: stream.out is NULL", __func__);
2792 return -EINVAL;
2793 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002794 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002795 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002796 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002797 struct stream_out *voip_out = adev->primary_output;
2798 struct stream_in *voip_in = get_voice_communication_input(adev);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002799 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS))
Guodong Hu267bdf82019-08-12 19:22:32 +08002800 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev, uc_id);
2801 else
2802 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302803 usecase->stream.out,
2804 usecase->type);
kunleizdcf967a2018-08-07 17:09:11 +08002805 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizdcf967a2018-08-07 17:09:11 +08002806
Eric Laurent637e2d42018-11-15 12:24:31 -08002807 if (voip_usecase)
2808 voip_out = voip_usecase->stream.out;
2809
2810 if (usecase->stream.out == voip_out && voip_in != NULL)
2811 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002812 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002813 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302814 if (usecase->stream.in == NULL) {
2815 ALOGE("%s: stream.in is NULL", __func__);
2816 return -EINVAL;
2817 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002818 assign_devices(&usecase->device_list, &usecase->stream.in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002819 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002820 if (in_snd_device == SND_DEVICE_NONE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002821 struct listnode out_devices;
Eric Laurent637e2d42018-11-15 12:24:31 -08002822 struct stream_in *voip_in = get_voice_communication_input(adev);
Carter Hsu2e429db2019-05-14 18:50:52 +08002823 struct stream_in *priority_in = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08002824
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002825 list_init(&out_devices);
Eric Laurent637e2d42018-11-15 12:24:31 -08002826 if (voip_in != NULL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002827 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
2828 USECASE_AUDIO_PLAYBACK_VOIP);
2829
Carter Hsu2e429db2019-05-14 18:50:52 +08002830 usecase->stream.in->enable_ec_port = false;
2831
Zhou Song62ea0282020-03-22 19:53:01 +08002832 bool is_ha_usecase = adev->ha_proxy_enable ?
2833 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY2 :
2834 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY;
2835 if (is_ha_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002836 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_TELEPHONY_TX, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002837 } else if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002838 assign_devices(&out_devices, &voip_usecase->stream.out->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002839 } else if (adev->primary_output &&
2840 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002841 assign_devices(&out_devices, &adev->primary_output->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002842 } else {
2843 /* forcing speaker o/p device to get matching i/p pair
2844 in case o/p is not routed from same primary HAL */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002845 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002846 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002847 priority_in = voip_in;
2848 } else {
2849 /* get the input with the highest priority source*/
2850 priority_in = get_priority_input(adev);
2851
2852 if (!priority_in)
2853 priority_in = usecase->stream.in;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002854 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002855
Eric Laurent637e2d42018-11-15 12:24:31 -08002856 in_snd_device = platform_get_input_snd_device(adev->platform,
Carter Hsu2e429db2019-05-14 18:50:52 +08002857 priority_in,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302858 &out_devices,
2859 usecase->type);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002860 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002861 }
2862 }
2863
2864 if (out_snd_device == usecase->out_snd_device &&
2865 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302866
2867 if (!force_device_switch(usecase))
2868 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002869 }
2870
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002871 if (!compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS) &&
Guodong Hu267bdf82019-08-12 19:22:32 +08002872 ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002873 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready()))) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002874 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2875 return 0;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302876 }
2877
Aalique Grahame22e49102018-12-18 14:23:57 -08002878 if (out_snd_device != SND_DEVICE_NONE &&
2879 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
2880 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2881 __func__,
2882 use_case_table[uc_id],
2883 adev->last_logged_snd_device[uc_id][0],
2884 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
2885 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
2886 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
2887 -1,
2888 out_snd_device,
2889 platform_get_snd_device_name(out_snd_device),
2890 platform_get_snd_device_acdb_id(out_snd_device));
2891 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
2892 }
2893 if (in_snd_device != SND_DEVICE_NONE &&
2894 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
2895 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2896 __func__,
2897 use_case_table[uc_id],
2898 adev->last_logged_snd_device[uc_id][1],
2899 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
2900 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
2901 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
2902 -1,
2903 in_snd_device,
2904 platform_get_snd_device_name(in_snd_device),
2905 platform_get_snd_device_acdb_id(in_snd_device));
2906 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
2907 }
2908
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002909
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002910 /*
2911 * Limitation: While in call, to do a device switch we need to disable
2912 * and enable both RX and TX devices though one of them is same as current
2913 * device.
2914 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002915 if ((usecase->type == VOICE_CALL) &&
2916 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2917 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002918 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002919 }
2920
2921 if (((usecase->type == VOICE_CALL) ||
2922 (usecase->type == VOIP_CALL)) &&
2923 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2924 /* Disable sidetone only if voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302925 if (voice_is_call_state_active_in_call(adev) ||
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002926 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002927 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002928
2929 /* Disable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302930 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002931 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002932 }
2933
Aalique Grahame22e49102018-12-18 14:23:57 -08002934 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
2935 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02002936 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302937 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08002938 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
2939 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
2940 else
2941 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302942 }
2943
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002944 /* Disable current sound devices */
2945 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002946 disable_audio_route(adev, usecase);
2947 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002948 }
2949
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002950 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002951 disable_audio_route(adev, usecase);
2952 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002953 }
2954
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002955 /* Applicable only on the targets that has external modem.
2956 * New device information should be sent to modem before enabling
2957 * the devices to reduce in-call device switch time.
2958 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002959 if ((usecase->type == VOICE_CALL) &&
2960 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2961 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002962 status = platform_switch_voice_call_enable_device_config(adev->platform,
2963 out_snd_device,
2964 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002965 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002966
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002967 /* Enable new sound devices */
2968 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002969 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302970 if (platform_check_codec_asrc_support(adev->platform))
2971 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002972 enable_snd_device(adev, out_snd_device);
Zhou Songd9bd9302020-08-04 16:34:45 +08002973 /* Enable haptics device for haptic usecase */
2974 if (usecase->id == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
2975 enable_snd_device(adev, SND_DEVICE_OUT_HAPTICS);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002976 }
2977
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002978 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302979 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002980 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002981 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002982
Avinash Vaish71a8b972014-07-24 15:36:33 +05302983 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002984 status = platform_switch_voice_call_device_post(adev->platform,
2985 out_snd_device,
2986 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05302987 enable_audio_route_for_voice_usecases(adev, usecase);
2988 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002989
sangwoo170731f2013-06-08 15:36:36 +09002990 usecase->in_snd_device = in_snd_device;
2991 usecase->out_snd_device = out_snd_device;
2992
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302993 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2994 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302995 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002996 if ((24 == usecase->stream.out->bit_width) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002997 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_SPEAKER)) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002998 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2999 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
3000 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
3001 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
3002 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
3003 /*
3004 * To best utlize DSP, check if the stream sample rate is supported/multiple of
3005 * configured device sample rate, if not update the COPP rate to be equal to the
3006 * device sample rate, else open COPP at stream sample rate
3007 */
3008 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
3009 usecase->stream.out->sample_rate,
3010 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05303011 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
Preetam Singh Ranawat590d0432019-09-30 14:39:47 +05303012 out_snd_device != SND_DEVICE_OUT_HEADPHONES &&
3013 out_snd_device != SND_DEVICE_OUT_HEADPHONES_HIFI_FILTER &&
Ashish Jain4826f6c2017-02-06 13:33:20 +05303014 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003015 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
3016 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
3017 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3018 }
Weiyin Jiangcdece202019-07-08 16:13:16 +08003019 }
3020 enable_audio_route(adev, usecase);
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003021
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08003022 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08003023
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003024 /* If input stream is already running then effect needs to be
3025 applied on the new input device that's being enabled here. */
Eric Laurent637e2d42018-11-15 12:24:31 -08003026 if (in_snd_device != SND_DEVICE_NONE)
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003027 check_and_enable_effect(adev);
3028
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003029 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003030 /* Enable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303031 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003032 voice_check_and_update_aanc_path(adev, out_snd_device, true);
3033
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003034 /* Enable sidetone only if other voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303035 if (voice_is_call_state_active_in_call(adev) ||
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003036 voice_extn_compress_voip_is_started(adev))
3037 voice_set_sidetone(adev, out_snd_device, true);
3038 }
3039
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003040 /* Applicable only on the targets that has external modem.
3041 * Enable device command should be sent to modem only after
3042 * enabling voice call mixer controls
3043 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07003044 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003045 status = platform_switch_voice_call_usecase_route_post(adev->platform,
3046 out_snd_device,
3047 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303048
3049 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003050 struct stream_in *in = adev_get_active_input(adev);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303051 if (usecase->type == VOIP_CALL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003052 if (in != NULL && !in->standby) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303053 if (is_bt_soc_on(adev) == false){
3054 ALOGD("BT SCO MIC disconnected while in connection");
Eric Laurent637e2d42018-11-15 12:24:31 -08003055 if (in->pcm != NULL)
3056 pcm_stop(in->pcm);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303057 }
3058 }
3059 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
3060 && usecase->stream.out->started) {
3061 if (is_bt_soc_on(adev) == false) {
3062 ALOGD("BT SCO/A2DP disconnected while in connection");
3063 out_standby_l(&usecase->stream.out->stream.common);
3064 }
3065 }
3066 } else if ((usecase->stream.out != NULL) &&
3067 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05303068 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
3069 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Weiyin Jiang0d373242019-07-25 13:18:17 +08003070 (usecase->type != PCM_CAPTURE) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303071 usecase->stream.out->started) {
3072 if (is_bt_soc_on(adev) == false) {
3073 ALOGD("BT SCO/A2dp disconnected while in connection");
3074 out_standby_l(&usecase->stream.out->stream.common);
3075 }
3076 }
3077 }
3078
Yung Ti Su70cb8242018-06-22 17:38:47 +08003079 if (usecase->type != PCM_CAPTURE && usecase == voip_usecase) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003080 struct stream_out *voip_out = voip_usecase->stream.out;
3081 audio_extn_utils_send_app_type_gain(adev,
3082 voip_out->app_type_cfg.app_type,
3083 &voip_out->app_type_cfg.gain[0]);
3084 }
3085
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07003086 ALOGV("%s: done",__func__);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303087
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003088 return status;
3089}
3090
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003091static int stop_input_stream(struct stream_in *in)
3092{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303093 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003094 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05303095
3096 if (in == NULL) {
3097 ALOGE("%s: stream_in ptr is NULL", __func__);
3098 return -EINVAL;
3099 }
3100
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003101 struct audio_device *adev = in->dev;
Carter Hsu2e429db2019-05-14 18:50:52 +08003102 struct stream_in *priority_in = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003103
Eric Laurent994a6932013-07-17 11:51:42 -07003104 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003105 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003106 uc_info = get_usecase_from_list(adev, in->usecase);
3107 if (uc_info == NULL) {
3108 ALOGE("%s: Could not find the usecase (%d) in the list",
3109 __func__, in->usecase);
3110 return -EINVAL;
3111 }
3112
Carter Hsu2e429db2019-05-14 18:50:52 +08003113 priority_in = get_priority_input(adev);
3114
Derek Chenea197282019-01-07 17:35:01 -08003115 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3116 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003117
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003118 /* Close in-call recording streams */
3119 voice_check_and_stop_incall_rec_usecase(adev, in);
3120
Eric Laurent150dbfe2013-02-27 14:31:02 -08003121 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003122 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003123
3124 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003125 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003126
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003127 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303128 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_PRIMARY);
3129
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003130 list_remove(&uc_info->list);
3131 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003132
Carter Hsu2e429db2019-05-14 18:50:52 +08003133 if (priority_in == in) {
3134 priority_in = get_priority_input(adev);
3135 if (priority_in)
3136 select_devices(adev, priority_in->usecase);
3137 }
3138
Vatsal Buchac09ae062018-11-14 13:25:08 +05303139 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07003140 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003141 return ret;
3142}
3143
3144int start_input_stream(struct stream_in *in)
3145{
3146 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08003147 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003148 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05303149
3150 if (in == NULL) {
3151 ALOGE("%s: stream_in ptr is NULL", __func__);
3152 return -EINVAL;
3153 }
3154
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003155 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07003156 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07003157 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003158
Mingming Yin2664a5b2015-09-03 10:53:11 -07003159 if (get_usecase_from_list(adev, usecase) == NULL)
3160 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303161 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
3162 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003163
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303164 if (CARD_STATUS_OFFLINE == in->card_status||
3165 CARD_STATUS_OFFLINE == adev->card_status) {
3166 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303167 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303168 goto error_config;
3169 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303170
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003171 if (is_sco_in_device_type(&in->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303172 if (!adev->bt_sco_on) {
3173 ALOGE("%s: SCO profile is not ready, return error", __func__);
3174 ret = -EIO;
3175 goto error_config;
3176 }
3177 }
3178
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003179 /* Check if source matches incall recording usecase criteria */
3180 ret = voice_check_and_set_incall_rec_usecase(adev, in);
3181 if (ret)
3182 goto error_config;
3183 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07003184 ALOGV("%s: usecase(%d)", __func__, in->usecase);
3185
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303186 if (audio_extn_cin_attached_usecase(in))
3187 audio_extn_cin_acquire_usecase(in);
3188
Mingming Yin2664a5b2015-09-03 10:53:11 -07003189 if (get_usecase_from_list(adev, in->usecase) != NULL) {
3190 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
3191 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Weiyin Jiang38c0e612020-09-10 16:10:51 +08003192 ret = -EINVAL;
3193 goto error_config;
Mingming Yin2664a5b2015-09-03 10:53:11 -07003194 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003195
Eric Laurentb23d5282013-05-14 15:27:20 -07003196 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003197 if (in->pcm_device_id < 0) {
3198 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
3199 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08003200 ret = -EINVAL;
3201 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003202 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003203
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003204 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003205
3206 if (!uc_info) {
3207 ret = -ENOMEM;
3208 goto error_config;
3209 }
3210
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003211 uc_info->id = in->usecase;
3212 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003213 uc_info->stream.in = in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003214 list_init(&uc_info->device_list);
3215 assign_devices(&uc_info->device_list, &in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003216 uc_info->in_snd_device = SND_DEVICE_NONE;
3217 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003218
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003219 list_add_tail(&adev->usecase_list, &uc_info->list);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003220 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303221 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3222 adev->perf_lock_opts,
3223 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003224 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003225
Derek Chenea197282019-01-07 17:35:01 -08003226 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3227 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003228
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05303229 android_atomic_acquire_cas(true, false, &(in->capture_stopped));
3230
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303231 if (audio_extn_cin_attached_usecase(in)) {
Manish Dewangan46e07982018-12-13 18:18:59 +05303232 ret = audio_extn_cin_open_input_stream(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303233 if (ret)
3234 goto error_open;
3235 else
3236 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003237 }
3238
Haynes Mathew George16081042017-05-31 17:16:49 -07003239 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003240 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003241 ALOGE("%s: pcm stream not ready", __func__);
3242 goto error_open;
3243 }
3244 ret = pcm_start(in->pcm);
3245 if (ret < 0) {
3246 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3247 goto error_open;
3248 }
3249 } else {
3250 unsigned int flags = PCM_IN | PCM_MONOTONIC;
3251 unsigned int pcm_open_retry_count = 0;
3252
Zhou Song62ea0282020-03-22 19:53:01 +08003253 if ((in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) ||
3254 (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003255 flags |= PCM_MMAP | PCM_NOIRQ;
3256 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
3257 } else if (in->realtime) {
3258 flags |= PCM_MMAP | PCM_NOIRQ;
3259 }
3260
Garmond Leunge2433c32017-09-28 21:51:22 -07003261 if (audio_extn_ffv_get_stream() == in) {
3262 ALOGD("%s: ffv stream, update pcm config", __func__);
3263 audio_extn_ffv_update_pcm_config(&config);
3264 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003265 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3266 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3267
3268 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003269 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07003270 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07003271 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003272 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303273 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303274 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3275 adev->card_status = CARD_STATUS_OFFLINE;
3276 in->card_status = CARD_STATUS_OFFLINE;
3277 ret = -EIO;
3278 goto error_open;
3279 }
3280
Haynes Mathew George16081042017-05-31 17:16:49 -07003281 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3282 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3283 if (in->pcm != NULL) {
3284 pcm_close(in->pcm);
3285 in->pcm = NULL;
3286 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003287 if (pcm_open_retry_count == 0) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003288 ret = -EIO;
3289 goto error_open;
3290 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003291 pcm_open_retry_count--;
Haynes Mathew George16081042017-05-31 17:16:49 -07003292 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3293 continue;
3294 }
3295 break;
3296 }
3297
3298 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003299 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07003300 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003301 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003302 if (ret < 0) {
3303 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3304 pcm_close(in->pcm);
3305 in->pcm = NULL;
3306 goto error_open;
3307 }
3308 register_in_stream(in);
3309 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003310 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07003311 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003312 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003313 if (ret < 0) {
3314 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003315 pcm_close(in->pcm);
3316 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003317 goto error_open;
3318 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003319 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003320 }
3321
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003322 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07003323 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
3324 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003325
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003326 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303327 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
3328
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303329done_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003330 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303331 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07003332 ALOGV("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303333 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003334 return ret;
3335
3336error_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003337 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303338 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003339 stop_input_stream(in);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003340
Eric Laurentc8400632013-02-14 19:04:54 -08003341error_config:
Weiyin Jiang38c0e612020-09-10 16:10:51 +08003342 if (audio_extn_cin_attached_usecase(in))
3343 audio_extn_cin_close_input_stream(in);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303344 /*
3345 * sleep 50ms to allow sufficient time for kernel
3346 * drivers to recover incases like SSR.
3347 */
3348 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003349 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303350 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003351 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003352}
3353
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003354void lock_input_stream(struct stream_in *in)
3355{
3356 pthread_mutex_lock(&in->pre_lock);
3357 pthread_mutex_lock(&in->lock);
3358 pthread_mutex_unlock(&in->pre_lock);
3359}
3360
3361void lock_output_stream(struct stream_out *out)
3362{
3363 pthread_mutex_lock(&out->pre_lock);
3364 pthread_mutex_lock(&out->lock);
3365 pthread_mutex_unlock(&out->pre_lock);
3366}
3367
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003368/* must be called with out->lock locked */
3369static int send_offload_cmd_l(struct stream_out* out, int command)
3370{
3371 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
3372
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003373 if (!cmd) {
3374 ALOGE("failed to allocate mem for command 0x%x", command);
3375 return -ENOMEM;
3376 }
3377
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003378 ALOGVV("%s %d", __func__, command);
3379
3380 cmd->cmd = command;
3381 list_add_tail(&out->offload_cmd_list, &cmd->node);
3382 pthread_cond_signal(&out->offload_cond);
3383 return 0;
3384}
3385
3386/* must be called iwth out->lock locked */
3387static void stop_compressed_output_l(struct stream_out *out)
3388{
3389 out->offload_state = OFFLOAD_STATE_IDLE;
3390 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003391 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003392 if (out->compr != NULL) {
3393 compress_stop(out->compr);
3394 while (out->offload_thread_blocked) {
3395 pthread_cond_wait(&out->cond, &out->lock);
3396 }
3397 }
3398}
3399
Varun Balaraje49253e2017-07-06 19:48:56 +05303400bool is_interactive_usecase(audio_usecase_t uc_id)
3401{
3402 unsigned int i;
3403 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
3404 if (uc_id == interactive_usecases[i])
3405 return true;
3406 }
3407 return false;
3408}
3409
3410static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
3411{
3412 audio_usecase_t ret_uc = USECASE_INVALID;
3413 unsigned int intract_uc_index;
3414 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3415
3416 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
3417 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
3418 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
3419 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
3420 ret_uc = interactive_usecases[intract_uc_index];
3421 break;
3422 }
3423 }
3424
3425 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
3426 return ret_uc;
3427}
3428
3429static void free_interactive_usecase(struct audio_device *adev,
3430 audio_usecase_t uc_id)
3431{
3432 unsigned int interact_uc_index;
3433 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3434
3435 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
3436 if (interactive_usecases[interact_uc_index] == uc_id) {
3437 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
3438 break;
3439 }
3440 }
3441 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
3442}
3443
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003444bool is_offload_usecase(audio_usecase_t uc_id)
3445{
3446 unsigned int i;
3447 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
3448 if (uc_id == offload_usecases[i])
3449 return true;
3450 }
3451 return false;
3452}
3453
Dhananjay Kumarac341582017-02-23 23:42:25 +05303454static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003455{
vivek mehta446c3962015-09-14 10:57:35 -07003456 audio_usecase_t ret_uc = USECASE_INVALID;
3457 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003458 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003459 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05303460 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07003461 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
3462 else
3463 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003464
vivek mehta446c3962015-09-14 10:57:35 -07003465 pthread_mutex_lock(&adev->lock);
3466 if (get_usecase_from_list(adev, ret_uc) != NULL)
3467 ret_uc = USECASE_INVALID;
3468 pthread_mutex_unlock(&adev->lock);
3469
3470 return ret_uc;
3471 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003472
3473 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003474 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3475 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3476 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3477 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003478 break;
3479 }
3480 }
vivek mehta446c3962015-09-14 10:57:35 -07003481
3482 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3483 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003484}
3485
3486static void free_offload_usecase(struct audio_device *adev,
3487 audio_usecase_t uc_id)
3488{
vivek mehta446c3962015-09-14 10:57:35 -07003489 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003490 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003491
3492 if (!adev->multi_offload_enable)
3493 return;
3494
3495 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3496 if (offload_usecases[offload_uc_index] == uc_id) {
3497 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003498 break;
3499 }
3500 }
3501 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3502}
3503
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003504static void *offload_thread_loop(void *context)
3505{
3506 struct stream_out *out = (struct stream_out *) context;
3507 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003508 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003509
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003510 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08003511 set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003512 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3513
3514 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003515 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003516 out->offload_state = OFFLOAD_STATE_IDLE;
3517 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003518 for (;;) {
3519 struct offload_cmd *cmd = NULL;
3520 stream_callback_event_t event;
3521 bool send_callback = false;
3522
3523 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3524 __func__, list_empty(&out->offload_cmd_list),
3525 out->offload_state);
3526 if (list_empty(&out->offload_cmd_list)) {
3527 ALOGV("%s SLEEPING", __func__);
3528 pthread_cond_wait(&out->offload_cond, &out->lock);
3529 ALOGV("%s RUNNING", __func__);
3530 continue;
3531 }
3532
3533 item = list_head(&out->offload_cmd_list);
3534 cmd = node_to_item(item, struct offload_cmd, node);
3535 list_remove(item);
3536
3537 ALOGVV("%s STATE %d CMD %d out->compr %p",
3538 __func__, out->offload_state, cmd->cmd, out->compr);
3539
3540 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3541 free(cmd);
3542 break;
3543 }
3544
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003545 // allow OFFLOAD_CMD_ERROR reporting during standby
3546 // this is needed to handle failures during compress_open
3547 // Note however that on a pause timeout, the stream is closed
3548 // and no offload usecase will be active. Therefore this
3549 // special case is needed for compress_open failures alone
3550 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3551 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003552 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003553 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003554 pthread_cond_signal(&out->cond);
3555 continue;
3556 }
3557 out->offload_thread_blocked = true;
3558 pthread_mutex_unlock(&out->lock);
3559 send_callback = false;
3560 switch(cmd->cmd) {
3561 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003562 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003563 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003564 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003565 send_callback = true;
3566 event = STREAM_CBK_EVENT_WRITE_READY;
3567 break;
3568 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003569 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303570 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003571 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303572 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003573 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303574 if (ret < 0)
3575 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303576 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303577 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003578 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003579 else
3580 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003581 if (-ENETRESET != ret && !(-EINTR == ret &&
3582 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303583 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303584 pthread_mutex_lock(&out->lock);
3585 out->send_new_metadata = 1;
3586 out->send_next_track_params = true;
3587 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303588 event = STREAM_CBK_EVENT_DRAIN_READY;
3589 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3590 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303591 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003592 break;
3593 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003594 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003595 ret = compress_drain(out->compr);
3596 ALOGD("copl(%p):out of compress_drain", out);
3597 // EINTR check avoids drain interruption due to SSR
3598 if (-ENETRESET != ret && !(-EINTR == ret &&
3599 CARD_STATUS_OFFLINE == out->card_status)) {
3600 send_callback = true;
3601 event = STREAM_CBK_EVENT_DRAIN_READY;
3602 } else
3603 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003604 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303605 case OFFLOAD_CMD_ERROR:
3606 ALOGD("copl(%p): sending error callback to AF", out);
3607 send_callback = true;
3608 event = STREAM_CBK_EVENT_ERROR;
3609 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003610 default:
3611 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3612 break;
3613 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003614 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003615 out->offload_thread_blocked = false;
3616 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003617 if (send_callback && out->client_callback) {
3618 ALOGVV("%s: sending client_callback event %d", __func__, event);
3619 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003620 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003621 free(cmd);
3622 }
3623
3624 pthread_cond_signal(&out->cond);
3625 while (!list_empty(&out->offload_cmd_list)) {
3626 item = list_head(&out->offload_cmd_list);
3627 list_remove(item);
3628 free(node_to_item(item, struct offload_cmd, node));
3629 }
3630 pthread_mutex_unlock(&out->lock);
3631
3632 return NULL;
3633}
3634
3635static int create_offload_callback_thread(struct stream_out *out)
3636{
3637 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3638 list_init(&out->offload_cmd_list);
3639 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3640 offload_thread_loop, out);
3641 return 0;
3642}
3643
3644static int destroy_offload_callback_thread(struct stream_out *out)
3645{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003646 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003647 stop_compressed_output_l(out);
3648 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3649
3650 pthread_mutex_unlock(&out->lock);
3651 pthread_join(out->offload_thread, (void **) NULL);
3652 pthread_cond_destroy(&out->offload_cond);
3653
3654 return 0;
3655}
3656
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003657static int stop_output_stream(struct stream_out *out)
3658{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303659 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003660 struct audio_usecase *uc_info;
3661 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003662 bool has_voip_usecase =
3663 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003664
Eric Laurent994a6932013-07-17 11:51:42 -07003665 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003666 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003667 uc_info = get_usecase_from_list(adev, out->usecase);
3668 if (uc_info == NULL) {
3669 ALOGE("%s: Could not find the usecase (%d) in the list",
3670 __func__, out->usecase);
3671 return -EINVAL;
3672 }
3673
Derek Chenea197282019-01-07 17:35:01 -08003674 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3675 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003676
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003677 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303678 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003679 if (adev->visualizer_stop_output != NULL)
3680 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003681
3682 audio_extn_dts_remove_state_notifier_node(out->usecase);
3683
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003684 if (adev->offload_effects_stop_output != NULL)
3685 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07003686 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3687 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3688 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003689 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003690
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003691 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3692 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003693 voice_set_device_mute_flag(adev, false);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003694 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003695
Eric Laurent150dbfe2013-02-27 14:31:02 -08003696 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003697 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003698
3699 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003700 disable_snd_device(adev, uc_info->out_snd_device);
Zhou Songd9bd9302020-08-04 16:34:45 +08003701 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
3702 disable_snd_device(adev, SND_DEVICE_OUT_HAPTICS);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003703
Aalique Grahame22e49102018-12-18 14:23:57 -08003704 audio_extn_extspk_update(adev->extspk);
3705
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003706 if (is_offload_usecase(out->usecase)) {
3707 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3708 adev->dsp_bit_width_enforce_mode,
3709 false);
3710 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003711 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003712 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3713 false);
3714
3715 if (ret != 0)
3716 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3717 /* default service interval was successfully updated,
3718 reopen USB backend with new service interval */
3719 ret = 0;
3720 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003721
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003722 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303723 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003724 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303725 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003726 ALOGV("Disable passthrough , reset mixer to pcm");
3727 /* NO_PASSTHROUGH */
Meng Wang4c32fb42020-01-16 17:57:11 +08003728#ifdef AUDIO_GKI_ENABLED
3729 /* out->compr_config.codec->reserved[0] is for compr_passthr */
3730 out->compr_config.codec->reserved[0] = 0;
3731#else
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003732 out->compr_config.codec->compr_passthr = 0;
Meng Wang4c32fb42020-01-16 17:57:11 +08003733#endif
Mingming Yin21854652016-04-13 11:54:02 -07003734 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003735 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3736 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003737
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303738 /* Must be called after removing the usecase from list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003739 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL))
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303740 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303741
Manish Dewangan21a850a2017-08-14 12:03:55 +05303742 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003743 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3744 if (ret < 0)
3745 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3746 }
3747
juyuchen2d415992018-11-16 14:15:16 +08003748 /* 1) media + voip output routing to handset must route media back to
3749 speaker when voip stops.
3750 2) trigger voip input to reroute when voip output changes to
3751 hearing aid. */
Aalique Grahame22e49102018-12-18 14:23:57 -08003752 if (has_voip_usecase ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003753 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003754 struct listnode *node;
3755 struct audio_usecase *usecase;
3756 list_for_each(node, &adev->usecase_list) {
3757 usecase = node_to_item(node, struct audio_usecase, list);
juyuchen2d415992018-11-16 14:15:16 +08003758 if ((usecase->type == PCM_CAPTURE &&
Revathi Uddarajud9f23d92020-07-27 10:55:06 +05303759 usecase->id != USECASE_AUDIO_RECORD_VOIP &&
3760 usecase->id != USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY)
juyuchen2d415992018-11-16 14:15:16 +08003761 || usecase == uc_info)
Aalique Grahame22e49102018-12-18 14:23:57 -08003762 continue;
3763
3764 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
3765 __func__, usecase->id, use_case_table[usecase->id],
3766 out->usecase, use_case_table[out->usecase]);
3767 select_devices(adev, usecase->id);
3768 }
3769 }
3770
Garmond Leung5fd0b552018-04-17 11:56:12 -07003771 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003772 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003773 return ret;
3774}
3775
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003776struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
3777 unsigned int flags, unsigned int pcm_open_retry_count,
3778 struct pcm_config *config)
3779{
3780 struct pcm* pcm = NULL;
3781
3782 while (1) {
3783 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
3784 if (pcm == NULL || !pcm_is_ready(pcm)) {
3785 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
3786 if (pcm != NULL) {
3787 pcm_close(pcm);
3788 pcm = NULL;
3789 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003790 if (pcm_open_retry_count == 0)
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003791 return NULL;
3792
Weiyin Jiang72197252019-10-09 11:49:32 +08003793 pcm_open_retry_count--;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003794 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3795 continue;
3796 }
3797 break;
3798 }
3799
3800 if (pcm_is_ready(pcm)) {
3801 int ret = pcm_prepare(pcm);
3802 if (ret < 0) {
3803 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3804 pcm_close(pcm);
3805 pcm = NULL;
3806 }
3807 }
3808
3809 return pcm;
3810}
3811
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003812int start_output_stream(struct stream_out *out)
3813{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003814 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003815 struct audio_usecase *uc_info;
3816 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003817 char mixer_ctl_name[128];
3818 struct mixer_ctl *ctl = NULL;
3819 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303820 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003821 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003822
Haynes Mathew George380745d2017-10-04 15:27:45 -07003823 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003824 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3825 ret = -EINVAL;
3826 goto error_config;
3827 }
3828
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003829 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303830 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003831 get_device_types(&out->device_list), is_haptic_usecase);
3832
3833 bool is_speaker_active = compare_device_type(&out->device_list,
3834 AUDIO_DEVICE_OUT_SPEAKER);
3835 bool is_speaker_safe_active = compare_device_type(&out->device_list,
3836 AUDIO_DEVICE_OUT_SPEAKER_SAFE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303837
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303838 if (CARD_STATUS_OFFLINE == out->card_status ||
3839 CARD_STATUS_OFFLINE == adev->card_status) {
3840 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303841 ret = -EIO;
Mingshu Pang5fc696f2020-02-28 12:32:00 +08003842 goto error_fatal;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303843 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303844
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003845 //Update incall music usecase to reflect correct voice session
3846 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3847 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
3848 if (ret != 0) {
3849 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3850 __func__, ret);
3851 goto error_config;
3852 }
3853 }
3854
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003855 if (is_a2dp_out_device_type(&out->device_list)) {
Florian Pfister1a84f312018-07-19 14:38:18 +02003856 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003857 if (is_speaker_active || is_speaker_safe_active) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303858 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303859 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303860 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3861 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3862 ret = -EAGAIN;
3863 goto error_config;
3864 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303865 }
3866 }
3867 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003868 if (is_sco_out_device_type(&out->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303869 if (!adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003870 if (is_speaker_active) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303871 //combo usecase just by pass a2dp
3872 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003873 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303874 } else {
3875 ALOGE("%s: SCO profile is not ready, return error", __func__);
3876 ret = -EAGAIN;
3877 goto error_config;
3878 }
3879 }
3880 }
3881
Eric Laurentb23d5282013-05-14 15:27:20 -07003882 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003883 if (out->pcm_device_id < 0) {
3884 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3885 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003886 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003887 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003888 }
3889
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003890 if (is_haptic_usecase) {
Meng Wang51d8c2a2020-04-27 15:23:21 +08003891 adev->haptic_pcm_device_id = platform_get_pcm_device_id(
3892 USECASE_AUDIO_PLAYBACK_HAPTICS, PCM_PLAYBACK);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003893 if (adev->haptic_pcm_device_id < 0) {
3894 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
3895 __func__, adev->haptic_pcm_device_id, out->usecase);
3896 ret = -EINVAL;
3897 goto error_config;
3898 }
3899 }
3900
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003901 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003902
3903 if (!uc_info) {
3904 ret = -ENOMEM;
3905 goto error_config;
3906 }
3907
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003908 uc_info->id = out->usecase;
3909 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003910 uc_info->stream.out = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003911 list_init(&uc_info->device_list);
3912 assign_devices(&uc_info->device_list, &out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003913 uc_info->in_snd_device = SND_DEVICE_NONE;
3914 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003915
3916 /* This must be called before adding this usecase to the list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003917 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003918 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3919 /* USB backend is not reopened immediately.
3920 This is eventually done as part of select_devices */
3921 }
3922
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003923 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003924
Wei Wangf7ca6c92017-11-21 14:51:20 -08003925 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303926 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3927 adev->perf_lock_opts,
3928 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303929
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003930 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303931 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303932 if (audio_extn_passthru_is_enabled() &&
3933 audio_extn_passthru_is_passthrough_stream(out)) {
3934 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303935 }
3936 }
3937
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003938 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003939 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303940 if (!a2dp_combo) {
3941 check_a2dp_restore_l(adev, out, false);
3942 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003943 struct listnode dev;
3944 list_init(&dev);
3945 assign_devices(&dev, &out->device_list);
3946 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
3947 reassign_device_list(&out->device_list,
3948 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aalique Grahame22e49102018-12-18 14:23:57 -08003949 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003950 reassign_device_list(&out->device_list,
3951 AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303952 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003953 assign_devices(&out->device_list, &dev);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303954 }
3955 } else {
Revathi Uddarajub26e3932020-06-10 14:51:02 +05303956 select_devices(adev, out->usecase);
3957 if (is_a2dp_out_device_type(&out->device_list) &&
3958 !adev->a2dp_started) {
3959 if (is_speaker_active || is_speaker_safe_active) {
3960 struct listnode dev;
3961 list_init(&dev);
3962 assign_devices(&dev, &out->device_list);
3963 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
3964 reassign_device_list(&out->device_list,
3965 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
3966 else
3967 reassign_device_list(&out->device_list,
3968 AUDIO_DEVICE_OUT_SPEAKER, "");
3969 select_devices(adev, out->usecase);
3970 assign_devices(&out->device_list, &dev);
3971 } else {
3972 ret = -EINVAL;
3973 goto error_open;
3974 }
3975 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303976 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003977
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003978 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3979 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003980 voice_set_device_mute_flag(adev, true);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003981 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003982
Derek Chenea197282019-01-07 17:35:01 -08003983 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3984 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003985
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003986 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3987 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003988
3989 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07003990 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07003991 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3992 ALOGE("%s: pcm stream not ready", __func__);
3993 goto error_open;
3994 }
3995 ret = pcm_start(out->pcm);
3996 if (ret < 0) {
3997 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3998 goto error_open;
3999 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07004000 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07004001 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004002 unsigned int flags = PCM_OUT;
4003 unsigned int pcm_open_retry_count = 0;
4004 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
4005 flags |= PCM_MMAP | PCM_NOIRQ;
4006 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004007 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08004008 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004009 } else
4010 flags |= PCM_MONOTONIC;
4011
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004012 if ((adev->vr_audio_mode_enabled) &&
4013 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
4014 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4015 "PCM_Dev %d Topology", out->pcm_device_id);
4016 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4017 if (!ctl) {
4018 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
4019 __func__, mixer_ctl_name);
4020 } else {
4021 //if success use ULLPP
4022 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
4023 __func__, mixer_ctl_name, out->pcm_device_id);
4024 //There is a still a possibility that some sessions
4025 // that request for FAST|RAW when 3D audio is active
4026 //can go through ULLPP. Ideally we expects apps to
4027 //listen to audio focus and stop concurrent playback
4028 //Also, we will look for mode flag (voice_in_communication)
4029 //before enabling the realtime flag.
4030 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
4031 }
4032 }
4033
Surendar Karka91fa3682018-07-02 18:12:12 +05304034 if (out->realtime)
4035 platform_set_stream_channel_map(adev->platform, out->channel_mask,
4036 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
4037
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004038 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
4039 flags, pcm_open_retry_count,
4040 &(out->config));
4041 if (out->pcm == NULL) {
4042 ret = -EIO;
4043 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004044 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004045
4046 if (is_haptic_usecase) {
4047 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
4048 adev->haptic_pcm_device_id,
4049 flags, pcm_open_retry_count,
4050 &(adev->haptics_config));
4051 // failure to open haptics pcm shouldnt stop audio,
4052 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07004053
4054 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
4055 ALOGD("%s: enable haptic audio synchronization", __func__);
4056 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
4057 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004058 }
4059
Surendar Karka91fa3682018-07-02 18:12:12 +05304060 if (!out->realtime)
4061 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Surendar Karkaf51b5842018-04-26 11:28:38 +05304062 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004063
Zhou Song2b8f28f2017-09-11 10:51:38 +08004064 // apply volume for voip playback after path is set up
4065 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
4066 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05304067 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
4068 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304069 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
4070 out->apply_volume = false;
Derek Chenf13dd492018-11-13 14:53:51 -08004071 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
4072 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304073 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004074 } else {
Zhou Song79929fe2020-01-20 17:57:43 +08004075 /*
4076 * set custom channel map if:
4077 * 1. neither mono nor stereo clips i.e. channels > 2 OR
4078 * 2. custom channel map has been set by client
4079 * else default channel map of FC/FR/FL can always be set to DSP
4080 */
4081 if (popcount(out->channel_mask) > 2 || out->channel_map_param.channel_map[0])
4082 platform_set_stream_channel_map(adev->platform, out->channel_mask,
4083 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08004084 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
4085 adev->dsp_bit_width_enforce_mode,
4086 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004087 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07004088 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004089 out->compr = compress_open(adev->snd_card,
4090 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004091 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004092 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05304093 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05304094 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
4095 adev->card_status = CARD_STATUS_OFFLINE;
4096 out->card_status = CARD_STATUS_OFFLINE;
4097 ret = -EIO;
4098 goto error_open;
4099 }
4100
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004101 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004102 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004103 compress_close(out->compr);
4104 out->compr = NULL;
4105 ret = -EIO;
4106 goto error_open;
4107 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304108 /* compress_open sends params of the track, so reset the flag here */
4109 out->is_compr_metadata_avail = false;
4110
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004111 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004112 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07004113
Fred Oh3f43e742015-03-04 18:42:34 -08004114 /* Since small bufs uses blocking writes, a write will be blocked
4115 for the default max poll time (20s) in the event of an SSR.
4116 Reduce the poll time to observe and deal with SSR faster.
4117 */
Ashish Jain5106d362016-05-11 19:23:33 +05304118 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08004119 compress_set_max_poll_wait(out->compr, 1000);
4120 }
4121
Manish Dewangan69426c82017-01-30 17:35:36 +05304122 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05304123 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05304124
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004125 audio_extn_dts_create_state_notifier_node(out->usecase);
4126 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4127 popcount(out->channel_mask),
4128 out->playback_started);
4129
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004130#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304131 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004132 audio_extn_dolby_send_ddp_endp_params(adev);
4133#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05304134 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
4135 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004136 if (adev->visualizer_start_output != NULL)
4137 adev->visualizer_start_output(out->handle, out->pcm_device_id);
4138 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05304139 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004140 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004141 }
Derek Chenf13dd492018-11-13 14:53:51 -08004142
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004143 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf13dd492018-11-13 14:53:51 -08004144 /* Update cached volume from media to offload/direct stream */
4145 struct listnode *node = NULL;
4146 list_for_each(node, &adev->active_outputs_list) {
4147 streams_output_ctxt_t *out_ctxt = node_to_item(node,
4148 streams_output_ctxt_t,
4149 list);
4150 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
4151 out->volume_l = out_ctxt->output->volume_l;
4152 out->volume_r = out_ctxt->output->volume_r;
4153 }
4154 }
4155 out_set_compr_volume(&out->stream,
4156 out->volume_l, out->volume_r);
4157 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004158 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004159
4160 if (ret == 0) {
4161 register_out_stream(out);
4162 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07004163 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4164 ALOGE("%s: pcm stream not ready", __func__);
4165 goto error_open;
4166 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004167 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004168 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004169 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004170 if (ret < 0)
4171 goto error_open;
4172 }
4173 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004174 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304175 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07004176 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004177
vivek mehtad15d2bf2019-05-17 13:35:10 -07004178 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
4179 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4180 audio_low_latency_hint_start();
4181 }
4182
Manish Dewangan21a850a2017-08-14 12:03:55 +05304183 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07004184 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07004185 if (ret < 0)
4186 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
4187 }
4188
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004189 // consider a scenario where on pause lower layers are tear down.
4190 // so on resume, swap mixer control need to be sent only when
4191 // backend is active, hence rather than sending from enable device
4192 // sending it from start of streamtream
4193
4194 platform_set_swap_channels(adev, true);
4195
Haynes Mathew George380745d2017-10-04 15:27:45 -07004196 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304197 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004198 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004199error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004200 if (adev->haptic_pcm) {
4201 pcm_close(adev->haptic_pcm);
4202 adev->haptic_pcm = NULL;
4203 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004204 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304205 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004206 stop_output_stream(out);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004207error_fatal:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05304208 /*
4209 * sleep 50ms to allow sufficient time for kernel
4210 * drivers to recover incases like SSR.
4211 */
4212 usleep(50000);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004213error_config:
Haynes Mathew George380745d2017-10-04 15:27:45 -07004214 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304215 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004216 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004217}
4218
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004219static int check_input_parameters(uint32_t sample_rate,
4220 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08004221 int channel_count,
4222 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004223{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004224 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004225
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304226 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
4227 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
4228 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07004229 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02004230 !audio_extn_compr_cap_format_supported(format) &&
4231 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004232 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004233
Aalique Grahame22e49102018-12-18 14:23:57 -08004234 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
4235 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
4236 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
4237 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
4238 return -EINVAL;
4239 }
4240
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004241 switch (channel_count) {
4242 case 1:
4243 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304244 case 3:
4245 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004246 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07004247 case 8:
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05304248 case 10:
4249 case 12:
4250 case 14:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004251 break;
4252 default:
4253 ret = -EINVAL;
4254 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004255
4256 switch (sample_rate) {
4257 case 8000:
4258 case 11025:
4259 case 12000:
4260 case 16000:
4261 case 22050:
4262 case 24000:
4263 case 32000:
4264 case 44100:
4265 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004266 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304267 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004268 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304269 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004270 break;
4271 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004272 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004273 }
4274
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004275 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004276}
4277
Naresh Tanniru04f71882018-06-26 17:46:22 +05304278
4279/** Add a value in a list if not already present.
4280 * @return true if value was successfully inserted or already present,
4281 * false if the list is full and does not contain the value.
4282 */
4283static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
4284 for (size_t i = 0; i < list_length; i++) {
4285 if (list[i] == value) return true; // value is already present
4286 if (list[i] == 0) { // no values in this slot
4287 list[i] = value;
4288 return true; // value inserted
4289 }
4290 }
4291 return false; // could not insert value
4292}
4293
4294/** Add channel_mask in supported_channel_masks if not already present.
4295 * @return true if channel_mask was successfully inserted or already present,
4296 * false if supported_channel_masks is full and does not contain channel_mask.
4297 */
4298static void register_channel_mask(audio_channel_mask_t channel_mask,
4299 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
4300 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
4301 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
4302}
4303
4304/** Add format in supported_formats if not already present.
4305 * @return true if format was successfully inserted or already present,
4306 * false if supported_formats is full and does not contain format.
4307 */
4308static void register_format(audio_format_t format,
4309 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
4310 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
4311 "%s: stream can not declare supporting its format %x", __func__, format);
4312}
4313/** Add sample_rate in supported_sample_rates if not already present.
4314 * @return true if sample_rate was successfully inserted or already present,
4315 * false if supported_sample_rates is full and does not contain sample_rate.
4316 */
4317static void register_sample_rate(uint32_t sample_rate,
4318 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
4319 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
4320 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
4321}
4322
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004323static inline uint32_t lcm(uint32_t num1, uint32_t num2)
4324{
4325 uint32_t high = num1, low = num2, temp = 0;
4326
4327 if (!num1 || !num2)
4328 return 0;
4329
4330 if (num1 < num2) {
4331 high = num2;
4332 low = num1;
4333 }
4334
4335 while (low != 0) {
4336 temp = low;
4337 low = high % low;
4338 high = temp;
4339 }
4340 return (num1 * num2)/high;
4341}
4342
4343static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
4344{
4345 uint32_t remainder = 0;
4346
4347 if (!multiplier)
4348 return num;
4349
4350 remainder = num % multiplier;
4351 if (remainder)
4352 num += (multiplier - remainder);
4353
4354 return num;
4355}
4356
Aalique Grahame22e49102018-12-18 14:23:57 -08004357static size_t get_stream_buffer_size(size_t duration_ms,
4358 uint32_t sample_rate,
4359 audio_format_t format,
4360 int channel_count,
4361 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004362{
4363 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004364 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004365
Aalique Grahame22e49102018-12-18 14:23:57 -08004366 size = (sample_rate * duration_ms) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004367 if (is_low_latency)
4368 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304369
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004370 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08004371 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004372
Ralf Herzbd08d632018-09-28 15:50:49 +02004373 /* make sure the size is multiple of 32 bytes and additionally multiple of
4374 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004375 * At 48 kHz mono 16-bit PCM:
4376 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
4377 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004378 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004379 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004380 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07004381
4382 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004383}
4384
Aalique Grahame22e49102018-12-18 14:23:57 -08004385static size_t get_input_buffer_size(uint32_t sample_rate,
4386 audio_format_t format,
4387 int channel_count,
4388 bool is_low_latency)
4389{
4390 /* Don't know if USB HIFI in this context so use true to be conservative */
4391 if (check_input_parameters(sample_rate, format, channel_count,
4392 true /*is_usb_hifi */) != 0)
4393 return 0;
4394
4395 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4396 sample_rate,
4397 format,
4398 channel_count,
4399 is_low_latency);
4400}
4401
Derek Chenf6318be2017-06-12 17:16:24 -04004402size_t get_output_period_size(uint32_t sample_rate,
4403 audio_format_t format,
4404 int channel_count,
4405 int duration /*in millisecs*/)
Ashish Jain058165c2016-09-28 23:18:48 +05304406{
4407 size_t size = 0;
4408 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
4409
4410 if ((duration == 0) || (sample_rate == 0) ||
4411 (bytes_per_sample == 0) || (channel_count == 0)) {
4412 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
4413 bytes_per_sample, channel_count);
4414 return -EINVAL;
4415 }
4416
4417 size = (sample_rate *
4418 duration *
4419 bytes_per_sample *
4420 channel_count) / 1000;
4421 /*
4422 * To have same PCM samples for all channels, the buffer size requires to
4423 * be multiple of (number of channels * bytes per sample)
4424 * For writes to succeed, the buffer must be written at address which is multiple of 32
4425 */
4426 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
4427
4428 return (size/(channel_count * bytes_per_sample));
4429}
4430
Zhou Song48453a02018-01-10 17:50:59 +08004431static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05304432{
4433 uint64_t actual_frames_rendered = 0;
Weiyin Jiang4813da12020-05-28 00:37:28 +08004434 uint64_t written_frames = 0;
4435 uint64_t kernel_frames = 0;
4436 uint64_t dsp_frames = 0;
4437 uint64_t signed_frames = 0;
4438 size_t kernel_buffer_size = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304439
4440 /* This adjustment accounts for buffering after app processor.
4441 * It is based on estimated DSP latency per use case, rather than exact.
4442 */
George Gao9ba8a142020-07-23 14:30:03 -07004443 dsp_frames = platform_render_latency(out) *
Weiyin Jiang4813da12020-05-28 00:37:28 +08004444 out->sample_rate / 1000000LL;
Ashish Jain5106d362016-05-11 19:23:33 +05304445
Zhou Song48453a02018-01-10 17:50:59 +08004446 pthread_mutex_lock(&out->position_query_lock);
Weiyin Jiang4813da12020-05-28 00:37:28 +08004447 written_frames = out->written /
4448 (audio_bytes_per_sample(out->hal_ip_format) * popcount(out->channel_mask));
4449
Ashish Jain5106d362016-05-11 19:23:33 +05304450 /* not querying actual state of buffering in kernel as it would involve an ioctl call
4451 * which then needs protection, this causes delay in TS query for pcm_offload usecase
4452 * hence only estimate.
4453 */
Weiyin Jiang4813da12020-05-28 00:37:28 +08004454 kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
4455 kernel_frames = kernel_buffer_size /
4456 (audio_bytes_per_sample(out->hal_op_format) * popcount(out->channel_mask));
Ashish Jain5106d362016-05-11 19:23:33 +05304457
Weiyin Jiang4813da12020-05-28 00:37:28 +08004458 if (written_frames >= (kernel_frames + dsp_frames))
4459 signed_frames = written_frames - kernel_frames - dsp_frames;
Ashish Jain5106d362016-05-11 19:23:33 +05304460
Zhou Song48453a02018-01-10 17:50:59 +08004461 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05304462 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08004463 if (timestamp != NULL )
4464 *timestamp = out->writeAt;
4465 } else if (timestamp != NULL) {
4466 clock_gettime(CLOCK_MONOTONIC, timestamp);
4467 }
4468 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304469
Weiyin Jiang4813da12020-05-28 00:37:28 +08004470 ALOGVV("%s signed frames %lld written frames %lld kernel frames %lld dsp frames %lld",
4471 __func__, signed_frames, written_frames, kernel_frames, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05304472
4473 return actual_frames_rendered;
4474}
4475
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004476static uint32_t out_get_sample_rate(const struct audio_stream *stream)
4477{
4478 struct stream_out *out = (struct stream_out *)stream;
4479
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004480 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004481}
4482
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004483static int out_set_sample_rate(struct audio_stream *stream __unused,
4484 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004485{
4486 return -ENOSYS;
4487}
4488
4489static size_t out_get_buffer_size(const struct audio_stream *stream)
4490{
4491 struct stream_out *out = (struct stream_out *)stream;
4492
Varun Balaraje49253e2017-07-06 19:48:56 +05304493 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05304494 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05304495 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304496 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4497 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
4498 else
4499 return out->compr_config.fragment_size;
4500 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004501 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304502 else if (is_offload_usecase(out->usecase) &&
4503 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304504 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004505
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004506 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004507 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004508}
4509
4510static uint32_t out_get_channels(const struct audio_stream *stream)
4511{
4512 struct stream_out *out = (struct stream_out *)stream;
4513
4514 return out->channel_mask;
4515}
4516
4517static audio_format_t out_get_format(const struct audio_stream *stream)
4518{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004519 struct stream_out *out = (struct stream_out *)stream;
4520
4521 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004522}
4523
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004524static int out_set_format(struct audio_stream *stream __unused,
4525 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004526{
4527 return -ENOSYS;
4528}
4529
4530static int out_standby(struct audio_stream *stream)
4531{
4532 struct stream_out *out = (struct stream_out *)stream;
4533 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07004534 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004535
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304536 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4537 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004538
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004539 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004540 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004541 if (adev->adm_deregister_stream)
4542 adev->adm_deregister_stream(adev->adm_data, out->handle);
4543
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004544 if (is_offload_usecase(out->usecase))
4545 stop_compressed_output_l(out);
4546
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004547 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004548 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004549 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4550 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304551 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08004552 pthread_mutex_unlock(&adev->lock);
4553 pthread_mutex_unlock(&out->lock);
4554 ALOGD("VOIP output entered standby");
4555 return 0;
4556 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004557 if (out->pcm) {
4558 pcm_close(out->pcm);
4559 out->pcm = NULL;
4560 }
Meng Wanga09da002020-04-20 12:56:04 +08004561 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4562 if (adev->haptic_pcm) {
4563 pcm_close(adev->haptic_pcm);
4564 adev->haptic_pcm = NULL;
4565 }
4566
4567 if (adev->haptic_buffer != NULL) {
4568 free(adev->haptic_buffer);
4569 adev->haptic_buffer = NULL;
4570 adev->haptic_buffer_size = 0;
4571 }
4572 adev->haptic_pcm_device_id = 0;
4573 }
4574
Haynes Mathew George16081042017-05-31 17:16:49 -07004575 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4576 do_stop = out->playback_started;
4577 out->playback_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07004578
4579 if (out->mmap_shared_memory_fd >= 0) {
4580 ALOGV("%s: closing mmap_shared_memory_fd = %d",
4581 __func__, out->mmap_shared_memory_fd);
4582 close(out->mmap_shared_memory_fd);
4583 out->mmap_shared_memory_fd = -1;
4584 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004585 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004586 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004587 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304588 out->send_next_track_params = false;
4589 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004590 out->gapless_mdata.encoder_delay = 0;
4591 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004592 if (out->compr != NULL) {
4593 compress_close(out->compr);
4594 out->compr = NULL;
4595 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004596 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004597 if (do_stop) {
4598 stop_output_stream(out);
4599 }
Lakshman Chaluvaraju06677b42019-06-24 10:04:52 +05304600 // if fm is active route on selected device in UI
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004601 audio_extn_fm_route_on_selected_device(adev, &out->device_list);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004602 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004603 }
4604 pthread_mutex_unlock(&out->lock);
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07004605 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004606 return 0;
4607}
4608
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304609static int out_on_error(struct audio_stream *stream)
4610{
4611 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004612 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304613
4614 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004615 // always send CMD_ERROR for offload streams, this
4616 // is needed e.g. when SSR happens within compress_open
4617 // since the stream is active, offload_callback_thread is also active.
4618 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
4619 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004620 }
4621 pthread_mutex_unlock(&out->lock);
4622
4623 status = out_standby(&out->stream.common);
4624
4625 lock_output_stream(out);
4626 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004627 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304628 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05304629
4630 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
4631 ALOGD("Setting previous card status if offline");
4632 out->prev_card_status_offline = true;
4633 }
4634
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304635 pthread_mutex_unlock(&out->lock);
4636
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004637 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304638}
4639
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304640/*
4641 *standby implementation without locks, assumes that the callee already
4642 *has taken adev and out lock.
4643 */
4644int out_standby_l(struct audio_stream *stream)
4645{
4646 struct stream_out *out = (struct stream_out *)stream;
4647 struct audio_device *adev = out->dev;
4648
4649 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4650 stream, out->usecase, use_case_table[out->usecase]);
4651
4652 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07004653 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304654 if (adev->adm_deregister_stream)
4655 adev->adm_deregister_stream(adev->adm_data, out->handle);
4656
4657 if (is_offload_usecase(out->usecase))
4658 stop_compressed_output_l(out);
4659
4660 out->standby = true;
4661 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4662 voice_extn_compress_voip_close_output_stream(stream);
4663 out->started = 0;
4664 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07004665 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304666 return 0;
4667 } else if (!is_offload_usecase(out->usecase)) {
4668 if (out->pcm) {
4669 pcm_close(out->pcm);
4670 out->pcm = NULL;
4671 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004672 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4673 if (adev->haptic_pcm) {
4674 pcm_close(adev->haptic_pcm);
4675 adev->haptic_pcm = NULL;
4676 }
4677
4678 if (adev->haptic_buffer != NULL) {
4679 free(adev->haptic_buffer);
4680 adev->haptic_buffer = NULL;
4681 adev->haptic_buffer_size = 0;
4682 }
4683 adev->haptic_pcm_device_id = 0;
4684 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304685 } else {
4686 ALOGD("copl(%p):standby", out);
4687 out->send_next_track_params = false;
4688 out->is_compr_metadata_avail = false;
4689 out->gapless_mdata.encoder_delay = 0;
4690 out->gapless_mdata.encoder_padding = 0;
4691 if (out->compr != NULL) {
4692 compress_close(out->compr);
4693 out->compr = NULL;
4694 }
4695 }
4696 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004697 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304698 }
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07004699 ALOGV("%s: exit", __func__);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304700 return 0;
4701}
4702
Aalique Grahame22e49102018-12-18 14:23:57 -08004703static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004704{
Aalique Grahame22e49102018-12-18 14:23:57 -08004705 struct stream_out *out = (struct stream_out *)stream;
4706
4707 // We try to get the lock for consistency,
4708 // but it isn't necessary for these variables.
4709 // If we're not in standby, we may be blocked on a write.
4710 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
4711 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
4712 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
4713
Andy Hunga1f48fa2019-07-01 18:14:53 -07004714 char buffer[256]; // for statistics formatting
4715 if (!is_offload_usecase(out->usecase)) {
4716 simple_stats_to_string(&out->fifo_underruns, buffer, sizeof(buffer));
4717 dprintf(fd, " Fifo frame underruns: %s\n", buffer);
4718 }
4719
Andy Hungc6bfd4a2019-07-01 18:26:00 -07004720 if (out->start_latency_ms.n > 0) {
4721 simple_stats_to_string(&out->start_latency_ms, buffer, sizeof(buffer));
4722 dprintf(fd, " Start latency ms: %s\n", buffer);
4723 }
4724
Aalique Grahame22e49102018-12-18 14:23:57 -08004725 if (locked) {
4726 pthread_mutex_unlock(&out->lock);
4727 }
4728
4729 // dump error info
4730 (void)error_log_dump(
4731 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
4732
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004733 return 0;
4734}
4735
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004736static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
4737{
4738 int ret = 0;
4739 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08004740
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004741 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004742 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004743 return -EINVAL;
4744 }
4745
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304746 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08004747
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004748 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
4749 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304750 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004751 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004752 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
4753 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304754 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004755 }
4756
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004757 ALOGV("%s new encoder delay %u and padding %u", __func__,
4758 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
4759
4760 return 0;
4761}
4762
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004763static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
4764{
4765 return out == adev->primary_output || out == adev->voice_tx_output;
4766}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004767
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304768// note: this call is safe only if the stream_cb is
4769// removed first in close_output_stream (as is done now).
4770static void out_snd_mon_cb(void * stream, struct str_parms * parms)
4771{
4772 if (!stream || !parms)
4773 return;
4774
4775 struct stream_out *out = (struct stream_out *)stream;
4776 struct audio_device *adev = out->dev;
4777
4778 card_status_t status;
4779 int card;
4780 if (parse_snd_card_status(parms, &card, &status) < 0)
4781 return;
4782
4783 pthread_mutex_lock(&adev->lock);
4784 bool valid_cb = (card == adev->snd_card);
4785 pthread_mutex_unlock(&adev->lock);
4786
4787 if (!valid_cb)
4788 return;
4789
4790 lock_output_stream(out);
4791 if (out->card_status != status)
4792 out->card_status = status;
4793 pthread_mutex_unlock(&out->lock);
4794
4795 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
4796 use_case_table[out->usecase],
4797 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4798
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304799 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304800 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304801 if (voice_is_call_state_active(adev) &&
4802 out == adev->primary_output) {
4803 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
4804 pthread_mutex_lock(&adev->lock);
4805 voice_stop_call(adev);
4806 adev->mode = AUDIO_MODE_NORMAL;
4807 pthread_mutex_unlock(&adev->lock);
4808 }
4809 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304810 return;
4811}
4812
Kevin Rocardfce19002017-08-07 19:21:36 -07004813static int get_alive_usb_card(struct str_parms* parms) {
4814 int card;
4815 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
4816 !audio_extn_usb_alive(card)) {
4817 return card;
4818 }
4819 return -ENODEV;
4820}
4821
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004822int route_output_stream(struct stream_out *out,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004823 struct listnode *devices)
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004824{
4825 struct audio_device *adev = out->dev;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004826 int ret = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004827 struct listnode new_devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004828 bool bypass_a2dp = false;
4829 bool reconfig = false;
4830 unsigned long service_interval = 0;
4831
4832 ALOGD("%s: enter: usecase(%d: %s) devices %x",
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004833 __func__, out->usecase, use_case_table[out->usecase], get_device_types(devices));
4834
4835 list_init(&new_devices);
4836 assign_devices(&new_devices, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004837
4838 lock_output_stream(out);
4839 pthread_mutex_lock(&adev->lock);
4840
4841 /*
4842 * When HDMI cable is unplugged the music playback is paused and
4843 * the policy manager sends routing=0. But the audioflinger continues
4844 * to write data until standby time (3sec). As the HDMI core is
4845 * turned off, the write gets blocked.
4846 * Avoid this by routing audio to speaker until standby.
4847 */
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08004848 if (is_single_device_type_equal(&out->device_list,
4849 AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004850 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004851 !audio_extn_passthru_is_passthrough_stream(out) &&
4852 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004853 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004854 }
4855 /*
4856 * When A2DP is disconnected the
4857 * music playback is paused and the policy manager sends routing=0
4858 * But the audioflinger continues to write data until standby time
4859 * (3sec). As BT is turned off, the write gets blocked.
4860 * Avoid this by routing audio to speaker until standby.
4861 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004862 if (is_a2dp_out_device_type(&out->device_list) &&
4863 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004864 !audio_extn_a2dp_source_is_ready() &&
4865 !adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004866 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004867 }
4868 /*
4869 * When USB headset is disconnected the music platback paused
4870 * and the policy manager send routing=0. But if the USB is connected
4871 * back before the standby time, AFE is not closed and opened
4872 * when USB is connected back. So routing to speker will guarantee
4873 * AFE reconfiguration and AFE will be opend once USB is connected again
4874 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004875 if (is_usb_out_device_type(&out->device_list) &&
4876 list_empty(&new_devices) &&
4877 !audio_extn_usb_connected(NULL)) {
4878 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
4879 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004880 /* To avoid a2dp to sco overlapping / BT device improper state
4881 * check with BT lib about a2dp streaming support before routing
4882 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004883 if (is_a2dp_out_device_type(&new_devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004884 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004885 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER) ||
4886 compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004887 //combo usecase just by pass a2dp
4888 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
4889 bypass_a2dp = true;
4890 } else {
4891 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
4892 /* update device to a2dp and don't route as BT returned error
4893 * However it is still possible a2dp routing called because
4894 * of current active device disconnection (like wired headset)
4895 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004896 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004897 pthread_mutex_unlock(&adev->lock);
4898 pthread_mutex_unlock(&out->lock);
4899 goto error;
4900 }
4901 }
4902 }
4903
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004904 // Workaround: If routing to an non existing usb device, fail gracefully
4905 // The routing request will otherwise block during 10 second
4906 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004907 if (is_usb_out_device_type(&new_devices)) {
4908 struct str_parms *parms =
4909 str_parms_create_str(get_usb_device_address(&new_devices));
4910 if (!parms)
4911 goto error;
4912 if ((card = get_alive_usb_card(parms)) >= 0) {
4913 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
4914 pthread_mutex_unlock(&adev->lock);
4915 pthread_mutex_unlock(&out->lock);
4916 str_parms_destroy(parms);
4917 ret = -ENOSYS;
4918 goto error;
4919 }
4920 str_parms_destroy(parms);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004921 }
4922
Weiyin Jiang80c8f9a2020-01-10 20:42:08 +08004923 // Workaround: If routing to an non existing hdmi device, fail gracefully
4924 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4925 (platform_get_edid_info_v2(adev->platform,
4926 out->extconn.cs.controller,
4927 out->extconn.cs.stream) != 0)) {
4928 ALOGW("out_set_parameters() ignoring rerouting to non existing HDMI/DP");
4929 pthread_mutex_unlock(&adev->lock);
4930 pthread_mutex_unlock(&out->lock);
4931 ret = -ENOSYS;
4932 goto error;
4933 }
4934
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004935 /*
4936 * select_devices() call below switches all the usecases on the same
4937 * backend to the new device. Refer to check_usecases_codec_backend() in
4938 * the select_devices(). But how do we undo this?
4939 *
4940 * For example, music playback is active on headset (deep-buffer usecase)
4941 * and if we go to ringtones and select a ringtone, low-latency usecase
4942 * will be started on headset+speaker. As we can't enable headset+speaker
4943 * and headset devices at the same time, select_devices() switches the music
4944 * playback to headset+speaker while starting low-lateny usecase for ringtone.
4945 * So when the ringtone playback is completed, how do we undo the same?
4946 *
4947 * We are relying on the out_set_parameters() call on deep-buffer output,
4948 * once the ringtone playback is ended.
4949 * NOTE: We should not check if the current devices are same as new devices.
4950 * Because select_devices() must be called to switch back the music
4951 * playback to headset.
4952 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004953 if (!list_empty(&new_devices)) {
4954 bool same_dev = compare_devices(&out->device_list, &new_devices);
4955 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004956
4957 if (output_drives_call(adev, out)) {
4958 if (!voice_is_call_state_active(adev)) {
4959 if (adev->mode == AUDIO_MODE_IN_CALL) {
4960 adev->current_call_output = out;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004961 ret = voice_start_call(adev);
4962 }
4963 } else {
4964 adev->current_call_output = out;
4965 voice_update_devices_for_all_voice_usecases(adev);
4966 }
4967 }
4968
Mingshu Pang971ff702020-09-09 15:28:22 +08004969 if (is_usb_out_device_type(&out->device_list)) {
4970 service_interval = audio_extn_usb_find_service_interval(false, true /*playback*/);
4971 audio_extn_usb_set_service_interval(true /*playback*/,
4972 service_interval,
4973 &reconfig);
4974 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
4975 }
4976
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004977 if (!out->standby) {
4978 if (!same_dev) {
4979 ALOGV("update routing change");
4980 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4981 adev->perf_lock_opts,
4982 adev->perf_lock_opts_size);
4983 if (adev->adm_on_routing_change)
4984 adev->adm_on_routing_change(adev->adm_data,
4985 out->handle);
4986 }
4987 if (!bypass_a2dp) {
4988 select_devices(adev, out->usecase);
4989 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004990 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4991 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004992 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004993 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004994 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004995 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004996 }
4997
4998 if (!same_dev) {
4999 // on device switch force swap, lower functions will make sure
5000 // to check if swap is allowed or not.
5001 platform_set_swap_channels(adev, true);
5002 audio_extn_perf_lock_release(&adev->perf_lock_handle);
5003 }
5004 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
5005 out->a2dp_compress_mute &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005006 (!is_a2dp_out_device_type(&out->device_list) || audio_extn_a2dp_source_is_ready())) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005007 pthread_mutex_lock(&out->compr_mute_lock);
5008 out->a2dp_compress_mute = false;
5009 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5010 pthread_mutex_unlock(&out->compr_mute_lock);
5011 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
5012 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
5013 }
5014 }
5015 }
5016
5017 pthread_mutex_unlock(&adev->lock);
5018 pthread_mutex_unlock(&out->lock);
5019
5020 /*handles device and call state changes*/
5021 audio_extn_extspk_update(adev->extspk);
5022
5023error:
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005024 ALOGV("%s: exit: code(%d)", __func__, ret);
5025 return ret;
5026}
5027
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005028static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
5029{
5030 struct stream_out *out = (struct stream_out *)stream;
5031 struct audio_device *adev = out->dev;
5032 struct str_parms *parms;
5033 char value[32];
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005034 int ret = 0, err;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005035 int ext_controller = -1;
5036 int ext_stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005037
sangwoobc677242013-08-08 16:53:43 +09005038 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005039 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005040 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305041 if (!parms)
5042 goto error;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005043
5044 err = platform_get_controller_stream_from_params(parms, &ext_controller,
5045 &ext_stream);
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08005046 if (err == 0) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005047 out->extconn.cs.controller = ext_controller;
5048 out->extconn.cs.stream = ext_stream;
5049 ALOGD("%s: usecase(%s) new controller/stream (%d/%d)", __func__,
5050 use_case_table[out->usecase], out->extconn.cs.controller,
5051 out->extconn.cs.stream);
5052 }
5053
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005054 if (out == adev->primary_output) {
5055 pthread_mutex_lock(&adev->lock);
5056 audio_extn_set_parameters(adev, parms);
5057 pthread_mutex_unlock(&adev->lock);
5058 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005059 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005060 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005061 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005062
5063 audio_extn_dts_create_state_notifier_node(out->usecase);
5064 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5065 popcount(out->channel_mask),
5066 out->playback_started);
5067
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08005068 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005069 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005070
Surendar Karkaf51b5842018-04-26 11:28:38 +05305071 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
5072 sizeof(value));
5073 if (err >= 0) {
5074 if (!strncmp("true", value, sizeof("true")) || atoi(value))
5075 audio_extn_send_dual_mono_mixing_coefficients(out);
5076 }
5077
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305078 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5079 if (err >= 0) {
5080 strlcpy(out->profile, value, sizeof(out->profile));
5081 ALOGV("updating stream profile with value '%s'", out->profile);
5082 lock_output_stream(out);
5083 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
5084 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005085 &out->device_list, out->flags,
5086 out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305087 out->sample_rate, out->bit_width,
5088 out->channel_mask, out->profile,
5089 &out->app_type_cfg);
5090 pthread_mutex_unlock(&out->lock);
5091 }
5092
Alexy Joseph98988832017-01-13 14:56:59 -08005093 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005094 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
5095 // and vendor.audio.hal.output.suspend.supported is set to true
5096 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08005097 //check suspend parameter only for low latency and if the property
5098 //is enabled
5099 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
5100 ALOGI("%s: got suspend_playback %s", __func__, value);
5101 lock_output_stream(out);
5102 if (!strncmp(value, "false", 5)) {
5103 //suspend_playback=false is supposed to set QOS value back to 75%
5104 //the mixer control sent with value Enable will achieve that
5105 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5106 } else if (!strncmp (value, "true", 4)) {
5107 //suspend_playback=true is supposed to remove QOS value
5108 //resetting the mixer control will set the default value
5109 //for the mixer control which is Disable and this removes the QOS vote
5110 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5111 } else {
5112 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
5113 " got %s", __func__, value);
5114 ret = -1;
5115 }
5116
5117 if (ret != 0) {
5118 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
5119 __func__, out->pm_qos_mixer_path, ret);
5120 }
5121
5122 pthread_mutex_unlock(&out->lock);
5123 }
5124 }
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005125
Alexy Joseph98988832017-01-13 14:56:59 -08005126 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005127 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305128error:
Eric Laurent994a6932013-07-17 11:51:42 -07005129 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005130 return ret;
5131}
5132
Paul McLeana50b7332018-12-17 08:24:21 -07005133static int in_set_microphone_direction(const struct audio_stream_in *stream,
5134 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07005135 struct stream_in *in = (struct stream_in *)stream;
5136
5137 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
5138
5139 in->direction = dir;
5140
5141 if (in->standby)
5142 return 0;
5143
5144 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07005145}
5146
5147static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07005148 struct stream_in *in = (struct stream_in *)stream;
5149
5150 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
5151
5152 if (zoom > 1.0 || zoom < -1.0)
5153 return -EINVAL;
5154
5155 in->zoom = zoom;
5156
5157 if (in->standby)
5158 return 0;
5159
5160 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07005161}
5162
5163
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005164static bool stream_get_parameter_channels(struct str_parms *query,
5165 struct str_parms *reply,
5166 audio_channel_mask_t *supported_channel_masks) {
5167 int ret = -1;
5168 char value[512];
5169 bool first = true;
5170 size_t i, j;
5171
5172 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
5173 ret = 0;
5174 value[0] = '\0';
5175 i = 0;
5176 while (supported_channel_masks[i] != 0) {
5177 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5178 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
5179 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305180 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005181
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305182 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005183 first = false;
5184 break;
5185 }
5186 }
5187 i++;
5188 }
5189 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5190 }
5191 return ret == 0;
5192}
5193
5194static bool stream_get_parameter_formats(struct str_parms *query,
5195 struct str_parms *reply,
5196 audio_format_t *supported_formats) {
5197 int ret = -1;
5198 char value[256];
5199 size_t i, j;
5200 bool first = true;
5201
5202 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
5203 ret = 0;
5204 value[0] = '\0';
5205 i = 0;
5206 while (supported_formats[i] != 0) {
5207 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5208 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
5209 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305210 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005211 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305212 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005213 first = false;
5214 break;
5215 }
5216 }
5217 i++;
5218 }
5219 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
5220 }
5221 return ret == 0;
5222}
5223
5224static bool stream_get_parameter_rates(struct str_parms *query,
5225 struct str_parms *reply,
5226 uint32_t *supported_sample_rates) {
5227
5228 int i;
5229 char value[256];
5230 int ret = -1;
5231 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
5232 ret = 0;
5233 value[0] = '\0';
5234 i=0;
5235 int cursor = 0;
5236 while (supported_sample_rates[i]) {
5237 int avail = sizeof(value) - cursor;
5238 ret = snprintf(value + cursor, avail, "%s%d",
5239 cursor > 0 ? "|" : "",
5240 supported_sample_rates[i]);
5241 if (ret < 0 || ret >= avail) {
5242 // if cursor is at the last element of the array
5243 // overwrite with \0 is duplicate work as
5244 // snprintf already put a \0 in place.
5245 // else
5246 // we had space to write the '|' at value[cursor]
5247 // (which will be overwritten) or no space to fill
5248 // the first element (=> cursor == 0)
5249 value[cursor] = '\0';
5250 break;
5251 }
5252 cursor += ret;
5253 ++i;
5254 }
5255 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
5256 value);
5257 }
5258 return ret >= 0;
5259}
5260
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005261static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
5262{
5263 struct stream_out *out = (struct stream_out *)stream;
5264 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005265 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005266 char value[256];
5267 struct str_parms *reply = str_parms_create();
5268 size_t i, j;
5269 int ret;
5270 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005271
5272 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005273 if (reply) {
5274 str_parms_destroy(reply);
5275 }
5276 if (query) {
5277 str_parms_destroy(query);
5278 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005279 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
5280 return NULL;
5281 }
5282
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005283 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005284 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
5285 if (ret >= 0) {
5286 value[0] = '\0';
5287 i = 0;
5288 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005289 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5290 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005291 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005292 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005293 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005294 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005295 first = false;
5296 break;
5297 }
5298 }
5299 i++;
5300 }
5301 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5302 str = str_parms_to_str(reply);
5303 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005304 voice_extn_out_get_parameters(out, query, reply);
5305 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005306 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005307
Alexy Joseph62142aa2015-11-16 15:10:34 -08005308
5309 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
5310 if (ret >= 0) {
5311 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05305312 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
5313 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08005314 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305315 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005316 } else {
5317 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05305318 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005319 }
5320 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005321 if (str)
5322 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08005323 str = str_parms_to_str(reply);
5324 }
5325
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005326 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
5327 if (ret >= 0) {
5328 value[0] = '\0';
5329 i = 0;
5330 first = true;
5331 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005332 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5333 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005334 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005335 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005336 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005337 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005338 first = false;
5339 break;
5340 }
5341 }
5342 i++;
5343 }
5344 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005345 if (str)
5346 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005347 str = str_parms_to_str(reply);
5348 }
Mingming Yin3a941d42016-02-17 18:08:05 -08005349
5350 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
5351 if (ret >= 0) {
5352 value[0] = '\0';
5353 i = 0;
5354 first = true;
5355 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005356 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
5357 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005358 if (!first) {
5359 strlcat(value, "|", sizeof(value));
5360 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005361 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08005362 first = false;
5363 break;
5364 }
5365 }
5366 i++;
5367 }
5368 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
5369 if (str)
5370 free(str);
5371 str = str_parms_to_str(reply);
5372 }
5373
Alexy Joseph98988832017-01-13 14:56:59 -08005374 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
5375 //only low latency track supports suspend_resume
5376 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005377 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08005378 if (str)
5379 free(str);
5380 str = str_parms_to_str(reply);
5381 }
5382
5383
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005384 str_parms_destroy(query);
5385 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07005386 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005387 return str;
5388}
5389
5390static uint32_t out_get_latency(const struct audio_stream_out *stream)
5391{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005392 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005393 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08005394 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005395
Alexy Josephaa54c872014-12-03 02:46:47 -08005396 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05305397 lock_output_stream(out);
5398 latency = audio_extn_utils_compress_get_dsp_latency(out);
5399 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005400 } else if ((out->realtime) ||
5401 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005402 // since the buffer won't be filled up faster than realtime,
5403 // return a smaller number
5404 if (out->config.rate)
5405 period_ms = (out->af_period_multiplier * out->config.period_size *
5406 1000) / (out->config.rate);
5407 else
5408 period_ms = 0;
George Gao9ba8a142020-07-23 14:30:03 -07005409 latency = period_ms + platform_render_latency(out) / 1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005410 } else {
5411 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005412 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08005413 }
5414
Zhou Songd2537a02020-06-11 22:04:46 +08005415 if (!out->standby && is_a2dp_out_device_type(&out->device_list))
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08005416 latency += audio_extn_a2dp_get_encoder_latency();
5417
Anish Kumar50ebcbf2014-12-09 04:01:39 +05305418 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08005419 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005420}
5421
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305422static float AmpToDb(float amplification)
5423{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305424 float db = DSD_VOLUME_MIN_DB;
5425 if (amplification > 0) {
5426 db = 20 * log10(amplification);
5427 if(db < DSD_VOLUME_MIN_DB)
5428 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305429 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305430 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305431}
5432
Arun Mirpuri5d170872019-03-26 13:21:31 -07005433static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
5434 float right)
5435{
5436 struct stream_out *out = (struct stream_out *)stream;
5437 long volume = 0;
5438 char mixer_ctl_name[128] = "";
5439 struct audio_device *adev = out->dev;
5440 struct mixer_ctl *ctl = NULL;
5441 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5442 PCM_PLAYBACK);
5443
5444 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5445 "Playback %d Volume", pcm_device_id);
5446 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5447 if (!ctl) {
5448 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5449 __func__, mixer_ctl_name);
5450 return -EINVAL;
5451 }
5452 if (left != right)
5453 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
5454 __func__, left, right);
5455 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
5456 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
5457 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
5458 __func__, mixer_ctl_name, volume);
5459 return -EINVAL;
5460 }
5461 return 0;
5462}
5463
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305464static int out_set_compr_volume(struct audio_stream_out *stream, float left,
5465 float right)
5466{
5467 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305468 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305469 char mixer_ctl_name[128];
5470 struct audio_device *adev = out->dev;
5471 struct mixer_ctl *ctl;
5472 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5473 PCM_PLAYBACK);
5474
5475 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5476 "Compress Playback %d Volume", pcm_device_id);
5477 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5478 if (!ctl) {
5479 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5480 __func__, mixer_ctl_name);
5481 return -EINVAL;
5482 }
5483 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
5484 __func__, mixer_ctl_name, left, right);
5485 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
5486 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
5487 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5488
5489 return 0;
5490}
5491
Zhou Song2b8f28f2017-09-11 10:51:38 +08005492static int out_set_voip_volume(struct audio_stream_out *stream, float left,
5493 float right)
5494{
5495 struct stream_out *out = (struct stream_out *)stream;
5496 char mixer_ctl_name[] = "App Type Gain";
5497 struct audio_device *adev = out->dev;
5498 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305499 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08005500
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07005501 if (!is_valid_volume(left, right)) {
5502 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
5503 __func__, left, right);
5504 return -EINVAL;
5505 }
5506
Zhou Song2b8f28f2017-09-11 10:51:38 +08005507 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5508 if (!ctl) {
5509 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5510 __func__, mixer_ctl_name);
5511 return -EINVAL;
5512 }
5513
5514 set_values[0] = 0; //0: Rx Session 1:Tx Session
5515 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305516 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
5517 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005518
5519 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
5520 return 0;
5521}
5522
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305523static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
5524 float right)
5525{
5526 struct stream_out *out = (struct stream_out *)stream;
5527 /* Volume control for pcm playback */
5528 if (left != right) {
5529 return -EINVAL;
5530 } else {
5531 char mixer_ctl_name[128];
5532 struct audio_device *adev = out->dev;
5533 struct mixer_ctl *ctl;
5534 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5535 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
5536 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5537 if (!ctl) {
5538 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5539 return -EINVAL;
5540 }
5541
5542 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
5543 int ret = mixer_ctl_set_value(ctl, 0, volume);
5544 if (ret < 0) {
5545 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
5546 return -EINVAL;
5547 }
5548
5549 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
5550
5551 return 0;
5552 }
5553}
5554
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005555static int out_set_volume(struct audio_stream_out *stream, float left,
5556 float right)
5557{
Eric Laurenta9024de2013-04-04 09:19:12 -07005558 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005559 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305560 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005561
Arun Mirpuri5d170872019-03-26 13:21:31 -07005562 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07005563 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
5564 /* only take left channel into account: the API is for stereo anyway */
5565 out->muted = (left == 0.0f);
5566 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005567 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305568 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005569 /*
5570 * Set mute or umute on HDMI passthrough stream.
5571 * Only take left channel into account.
5572 * Mute is 0 and unmute 1
5573 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305574 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305575 } else if (out->format == AUDIO_FORMAT_DSD){
5576 char mixer_ctl_name[128] = "DSD Volume";
5577 struct audio_device *adev = out->dev;
5578 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5579
5580 if (!ctl) {
5581 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5582 __func__, mixer_ctl_name);
5583 return -EINVAL;
5584 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05305585 volume[0] = (long)(AmpToDb(left));
5586 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305587 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5588 return 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005589 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS) &&
Derek Chendf05eea2019-08-01 13:57:49 -07005590 (out->car_audio_stream == CAR_AUDIO_STREAM_MEDIA)) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005591 ALOGD("%s: Overriding offload set volume for media bus stream", __func__);
5592 struct listnode *node = NULL;
5593 list_for_each(node, &adev->active_outputs_list) {
5594 streams_output_ctxt_t *out_ctxt = node_to_item(node,
5595 streams_output_ctxt_t,
5596 list);
5597 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
5598 out->volume_l = out_ctxt->output->volume_l;
5599 out->volume_r = out_ctxt->output->volume_r;
5600 }
5601 }
5602 if (!out->a2dp_compress_mute) {
5603 ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5604 }
5605 return ret;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005606 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305607 pthread_mutex_lock(&out->compr_mute_lock);
Arun Mirpuri5d170872019-03-26 13:21:31 -07005608 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305609 if (!out->a2dp_compress_mute)
5610 ret = out_set_compr_volume(stream, left, right);
5611 out->volume_l = left;
5612 out->volume_r = right;
5613 pthread_mutex_unlock(&out->compr_mute_lock);
5614 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005615 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005616 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005617 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
5618 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
5619 if (!out->standby) {
5620 audio_extn_utils_send_app_type_gain(out->dev,
5621 out->app_type_cfg.app_type,
5622 &out->app_type_cfg.gain[0]);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005623 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08005624 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08005625 out->volume_l = left;
5626 out->volume_r = right;
5627 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005628 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5629 ALOGV("%s: MMAP set volume called", __func__);
5630 if (!out->standby)
5631 ret = out_set_mmap_volume(stream, left, right);
5632 out->volume_l = left;
5633 out->volume_r = right;
5634 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305635 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05305636 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5637 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305638 /* Volume control for pcm playback */
5639 if (!out->standby)
5640 ret = out_set_pcm_volume(stream, left, right);
5641 else
5642 out->apply_volume = true;
5643
5644 out->volume_l = left;
5645 out->volume_r = right;
5646 return ret;
Derek Chenf13dd492018-11-13 14:53:51 -08005647 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
5648 ALOGV("%s: bus device set volume called", __func__);
5649 if (!out->standby)
5650 ret = out_set_pcm_volume(stream, left, right);
5651 out->volume_l = left;
5652 out->volume_r = right;
5653 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07005654 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005655
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005656 return -ENOSYS;
5657}
5658
Zhou Songc9672822017-08-16 16:01:39 +08005659static void update_frames_written(struct stream_out *out, size_t bytes)
5660{
5661 size_t bpf = 0;
5662
5663 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
5664 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
5665 bpf = 1;
5666 else if (!is_offload_usecase(out->usecase))
5667 bpf = audio_bytes_per_sample(out->format) *
5668 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08005669
5670 pthread_mutex_lock(&out->position_query_lock);
5671 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08005672 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08005673 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
5674 }
5675 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08005676}
5677
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005678int split_and_write_audio_haptic_data(struct stream_out *out,
5679 const void *buffer, size_t bytes_to_write)
5680{
5681 struct audio_device *adev = out->dev;
5682
5683 int ret = 0;
5684 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5685 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
5686 size_t frame_size = channel_count * bytes_per_sample;
5687 size_t frame_count = bytes_to_write / frame_size;
5688
5689 bool force_haptic_path =
5690 property_get_bool("vendor.audio.test_haptic", false);
5691
5692 // extract Haptics data from Audio buffer
5693 bool alloc_haptic_buffer = false;
5694 int haptic_channel_count = adev->haptics_config.channels;
5695 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
5696 size_t audio_frame_size = frame_size - haptic_frame_size;
5697 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
5698
5699 if (adev->haptic_buffer == NULL) {
5700 alloc_haptic_buffer = true;
5701 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
5702 free(adev->haptic_buffer);
5703 adev->haptic_buffer_size = 0;
5704 alloc_haptic_buffer = true;
5705 }
5706
5707 if (alloc_haptic_buffer) {
5708 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08005709 if(adev->haptic_buffer == NULL) {
5710 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
5711 return -ENOMEM;
5712 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005713 adev->haptic_buffer_size = total_haptic_buffer_size;
5714 }
5715
5716 size_t src_index = 0, aud_index = 0, hap_index = 0;
5717 uint8_t *audio_buffer = (uint8_t *)buffer;
5718 uint8_t *haptic_buffer = adev->haptic_buffer;
5719
5720 // This is required for testing only. This works for stereo data only.
5721 // One channel is fed to audio stream and other to haptic stream for testing.
5722 if (force_haptic_path)
5723 audio_frame_size = haptic_frame_size = bytes_per_sample;
5724
5725 for (size_t i = 0; i < frame_count; i++) {
5726 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
5727 audio_frame_size);
5728 aud_index += audio_frame_size;
5729 src_index += audio_frame_size;
5730
5731 if (adev->haptic_pcm)
5732 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
5733 haptic_frame_size);
5734 hap_index += haptic_frame_size;
5735 src_index += haptic_frame_size;
5736
5737 // This is required for testing only.
5738 // Discard haptic channel data.
5739 if (force_haptic_path)
5740 src_index += haptic_frame_size;
5741 }
5742
5743 // write to audio pipeline
5744 ret = pcm_write(out->pcm, (void *)audio_buffer,
5745 frame_count * audio_frame_size);
5746
5747 // write to haptics pipeline
5748 if (adev->haptic_pcm)
5749 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
5750 frame_count * haptic_frame_size);
5751
5752 return ret;
5753}
5754
Aalique Grahame22e49102018-12-18 14:23:57 -08005755#ifdef NO_AUDIO_OUT
5756static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
5757 const void *buffer __unused, size_t bytes)
5758{
5759 struct stream_out *out = (struct stream_out *)stream;
5760
5761 /* No Output device supported other than BT for playback.
5762 * Sleep for the amount of buffer duration
5763 */
5764 lock_output_stream(out);
5765 usleep(bytes * 1000000 / audio_stream_out_frame_size(
5766 (const struct audio_stream_out *)&out->stream) /
5767 out_get_sample_rate(&out->stream.common));
5768 pthread_mutex_unlock(&out->lock);
5769 return bytes;
5770}
5771#endif
5772
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005773static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
5774 size_t bytes)
5775{
5776 struct stream_out *out = (struct stream_out *)stream;
5777 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07005778 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305779 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005780 const size_t frame_size = audio_stream_out_frame_size(stream);
5781 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305782 struct audio_usecase *usecase = NULL;
Meng Wang4c32fb42020-01-16 17:57:11 +08005783 uint32_t compr_passthr = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005784
Haynes Mathew George380745d2017-10-04 15:27:45 -07005785 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005786 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305787
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305788 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08005789
Dhananjay Kumarac341582017-02-23 23:42:25 +05305790 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305791 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05305792 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
5793 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005794 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305795 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05305796 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05305797 ALOGD(" %s: sound card is not active/SSR state", __func__);
5798 ret= -EIO;
5799 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305800 }
5801 }
5802
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305803 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305804 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305805 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305806 goto exit;
5807 }
5808
Haynes Mathew George16081042017-05-31 17:16:49 -07005809 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5810 ret = -EINVAL;
5811 goto exit;
5812 }
5813
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005814 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305815 !out->is_iec61937_info_available) {
5816
5817 if (!audio_extn_passthru_is_passthrough_stream(out)) {
5818 out->is_iec61937_info_available = true;
5819 } else if (audio_extn_passthru_is_enabled()) {
5820 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05305821 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05305822
5823 if((out->format == AUDIO_FORMAT_DTS) ||
5824 (out->format == AUDIO_FORMAT_DTS_HD)) {
5825 ret = audio_extn_passthru_update_dts_stream_configuration(out,
5826 buffer, bytes);
5827 if (ret) {
5828 if (ret != -ENOSYS) {
5829 out->is_iec61937_info_available = false;
5830 ALOGD("iec61937 transmission info not yet updated retry");
5831 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305832 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05305833 /* if stream has started and after that there is
5834 * stream config change (iec transmission config)
5835 * then trigger select_device to update backend configuration.
5836 */
5837 out->stream_config_changed = true;
5838 pthread_mutex_lock(&adev->lock);
5839 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305840 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08005841 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305842 ret = -EINVAL;
5843 goto exit;
5844 }
Manish Dewangan671a4202017-08-18 17:30:46 +05305845 pthread_mutex_unlock(&adev->lock);
5846 out->stream_config_changed = false;
5847 out->is_iec61937_info_available = true;
5848 }
5849 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305850
Meng Wang4c32fb42020-01-16 17:57:11 +08005851#ifdef AUDIO_GKI_ENABLED
5852 /* out->compr_config.codec->reserved[0] is for compr_passthr */
5853 compr_passthr = out->compr_config.codec->reserved[0];
5854#else
5855 compr_passthr = out->compr_config.codec->compr_passthr;
5856#endif
5857
Garmond Leung317cbf12017-09-13 16:20:50 -07005858 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Meng Wang4c32fb42020-01-16 17:57:11 +08005859 (compr_passthr == PASSTHROUGH) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305860 (out->is_iec61937_info_available == true)) {
5861 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
5862 ret = -EINVAL;
5863 goto exit;
5864 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05305865 }
5866 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305867
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005868 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02005869 (audio_extn_a2dp_source_is_suspended())) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005870 if (!(compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER) ||
5871 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305872 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305873 ret = -EIO;
5874 goto exit;
5875 }
5876 }
5877 }
5878
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005879 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005880 out->standby = false;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005881 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
5882
Eric Laurent150dbfe2013-02-27 14:31:02 -08005883 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005884 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
5885 ret = voice_extn_compress_voip_start_output_stream(out);
5886 else
5887 ret = start_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005888 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005889 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005890 out->standby = true;
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005891 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005892 goto exit;
5893 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305894 out->started = 1;
Andy Hunga1f48fa2019-07-01 18:14:53 -07005895 out->last_fifo_valid = false; // we're coming out of standby, last_fifo isn't valid.
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005896
5897 if ((last_known_cal_step != -1) && (adev->platform != NULL)) {
vivek mehtab72d08d2016-04-29 03:16:47 -07005898 ALOGD("%s: retry previous failed cal level set", __func__);
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005899 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05305900 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005901 }
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005902 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305903
5904 if ((out->is_iec61937_info_available == true) &&
5905 (audio_extn_passthru_is_passthrough_stream(out))&&
5906 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
5907 ret = -EINVAL;
5908 goto exit;
5909 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05305910 if (out->set_dual_mono)
5911 audio_extn_send_dual_mono_mixing_coefficients(out);
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005912
5913 // log startup time in ms.
5914 simple_stats_log(
5915 &out->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005916 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005917
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005918 if (adev->is_channel_status_set == false &&
5919 compare_device_type(&out->device_list,
5920 AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Alexy Josephb1379942016-01-29 15:49:38 -08005921 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05305922 adev->is_channel_status_set = true;
5923 }
5924
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305925 if ((adev->use_old_pspd_mix_ctrl == true) &&
5926 (out->pspd_coeff_sent == false)) {
5927 /*
5928 * Need to resend pspd coefficients after stream started for
5929 * older kernel version as it does not save the coefficients
5930 * and also stream has to be started for coeff to apply.
5931 */
5932 usecase = get_usecase_from_list(adev, out->usecase);
5933 if (usecase != NULL) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05305934 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305935 out->pspd_coeff_sent = true;
5936 }
5937 }
5938
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005939 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08005940 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005941 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005942 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005943 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
5944 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305945 if (out->send_next_track_params && out->is_compr_metadata_avail) {
5946 ALOGD("copl(%p):send next track params in gapless", out);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08005947 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305948 out->send_next_track_params = false;
5949 out->is_compr_metadata_avail = false;
5950 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005951 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05305952 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305953 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005954
Ashish Jain83a6cc22016-06-28 14:34:17 +05305955 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305956 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05305957 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05305958 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005959 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05305960 return -EINVAL;
5961 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05305962 audio_format_t dst_format = out->hal_op_format;
5963 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305964
Dieter Luecking5d57def2018-09-07 14:23:37 +02005965 /* prevent division-by-zero */
5966 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
5967 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
5968 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
5969 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05305970 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005971 ATRACE_END();
5972 return -EINVAL;
5973 }
5974
Ashish Jainf1eaa582016-05-23 20:54:24 +05305975 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
5976 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
5977
Ashish Jain83a6cc22016-06-28 14:34:17 +05305978 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305979 dst_format,
5980 buffer,
5981 src_format,
5982 frames);
5983
Ashish Jain83a6cc22016-06-28 14:34:17 +05305984 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305985 bytes_to_write);
5986
5987 /*Convert written bytes in audio flinger format*/
5988 if (ret > 0)
5989 ret = ((ret * format_to_bitwidth_table[out->format]) /
5990 format_to_bitwidth_table[dst_format]);
5991 }
5992 } else
5993 ret = compress_write(out->compr, buffer, bytes);
5994
Zhou Songc9672822017-08-16 16:01:39 +08005995 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
5996 update_frames_written(out, bytes);
5997
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305998 if (ret < 0)
5999 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08006000 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05306001 /*msg to cb thread only if non blocking write is enabled*/
6002 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05306003 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006004 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05306005 } else if (-ENETRESET == ret) {
6006 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306007 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05306008 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05306009 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006010 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05306011 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006012 }
Ashish Jain5106d362016-05-11 19:23:33 +05306013
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05306014 /* Call compr start only when non-zero bytes of data is there to be rendered */
6015 if (!out->playback_started && ret > 0) {
6016 int status = compress_start(out->compr);
6017 if (status < 0) {
6018 ret = status;
6019 ALOGE("%s: compr start failed with err %d", __func__, errno);
6020 goto exit;
6021 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07006022 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006023 out->playback_started = 1;
6024 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006025
6026 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6027 popcount(out->channel_mask),
6028 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006029 }
6030 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006031 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006032 return ret;
6033 } else {
6034 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006035 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006036 if (out->muted)
6037 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006038 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
6039 __func__, frames, frame_size, bytes_to_write);
6040
Aalique Grahame22e49102018-12-18 14:23:57 -08006041 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07006042 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
6043 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
6044 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006045 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
6046 int16_t *src = (int16_t *)buffer;
6047 int16_t *dst = (int16_t *)buffer;
6048
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006049 LOG_ALWAYS_FATAL_IF(channel_count > 2 ||
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006050 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08006051 "out_write called for %s use case with wrong properties",
6052 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006053
6054 /*
6055 * FIXME: this can be removed once audio flinger mixer supports
6056 * mono output
6057 */
6058
6059 /*
6060 * Code below goes over each frame in the buffer and adds both
6061 * L and R samples and then divides by 2 to convert to mono
6062 */
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006063 if (channel_count == 2) {
6064 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
6065 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
6066 }
6067 bytes_to_write /= 2;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006068 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006069 }
Andy Hunga1f48fa2019-07-01 18:14:53 -07006070
6071 // Note: since out_get_presentation_position() is called alternating with out_write()
6072 // by AudioFlinger, we can check underruns using the prior timestamp read.
6073 // (Alternately we could check if the buffer is empty using pcm_get_htimestamp().
6074 if (out->last_fifo_valid) {
6075 // compute drain to see if there is an underrun.
6076 const int64_t current_ns = systemTime(SYSTEM_TIME_MONOTONIC); // sys call
Dhananjay Kumara4429632020-07-11 02:53:37 +05306077 int64_t time_diff_ns = current_ns - out->last_fifo_time_ns;
6078 int64_t frames_by_time =
6079 ((time_diff_ns > 0) && (time_diff_ns < (INT64_MAX / out->config.rate))) ?
6080 (time_diff_ns * out->config.rate / NANOS_PER_SECOND) : 0;
Andy Hunga1f48fa2019-07-01 18:14:53 -07006081 const int64_t underrun = frames_by_time - out->last_fifo_frames_remaining;
6082
6083 if (underrun > 0) {
6084 simple_stats_log(&out->fifo_underruns, underrun);
6085
6086 ALOGW("%s: underrun(%lld) "
6087 "frames_by_time(%lld) > out->last_fifo_frames_remaining(%lld)",
6088 __func__,
6089 (long long)out->fifo_underruns.n,
6090 (long long)frames_by_time,
6091 (long long)out->last_fifo_frames_remaining);
6092 }
6093 out->last_fifo_valid = false; // we're writing below, mark fifo info as stale.
6094 }
6095
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306096 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006097
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006098 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006099
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006100 if (out->config.rate)
6101 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
6102 out->config.rate;
6103
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006104 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006105 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
6106
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006107 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006108 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006109 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306110 out->convert_buffer != NULL) {
6111
6112 memcpy_by_audio_format(out->convert_buffer,
6113 out->hal_op_format,
6114 buffer,
6115 out->hal_ip_format,
6116 out->config.period_size * out->config.channels);
6117
6118 ret = pcm_write(out->pcm, out->convert_buffer,
6119 (out->config.period_size *
6120 out->config.channels *
6121 format_to_bitwidth_table[out->hal_op_format]));
6122 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05306123 /*
6124 * To avoid underrun in DSP when the application is not pumping
6125 * data at required rate, check for the no. of bytes and ignore
6126 * pcm_write if it is less than actual buffer size.
6127 * It is a work around to a change in compress VOIP driver.
6128 */
6129 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
6130 bytes < (out->config.period_size * out->config.channels *
6131 audio_bytes_per_sample(out->format))) {
6132 size_t voip_buf_size =
6133 out->config.period_size * out->config.channels *
6134 audio_bytes_per_sample(out->format);
6135 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
6136 __func__, bytes, voip_buf_size);
6137 usleep(((uint64_t)voip_buf_size - bytes) *
6138 1000000 / audio_stream_out_frame_size(stream) /
6139 out_get_sample_rate(&out->stream.common));
6140 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006141 } else {
6142 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
6143 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
6144 else
6145 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
6146 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306147 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006148
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006149 release_out_focus(out);
6150
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306151 if (ret < 0)
6152 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08006153 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05306154 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006155 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006156 }
6157
6158exit:
Zhou Songc9672822017-08-16 16:01:39 +08006159 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306160 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306161 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306162 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006163 pthread_mutex_unlock(&out->lock);
6164
6165 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006166 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08006167 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306168 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306169 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306170 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306171 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306172 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306173 out->standby = true;
6174 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306175 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006176 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
6177 /* prevent division-by-zero */
6178 uint32_t stream_size = audio_stream_out_frame_size(stream);
6179 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006180
Dieter Luecking5d57def2018-09-07 14:23:37 +02006181 if ((stream_size == 0) || (srate == 0)) {
6182 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
6183 ATRACE_END();
6184 return -EINVAL;
6185 }
6186 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
6187 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006188 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05306189 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006190 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006191 return ret;
6192 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006193 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07006194 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006195 return bytes;
6196}
6197
6198static int out_get_render_position(const struct audio_stream_out *stream,
6199 uint32_t *dsp_frames)
6200{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006201 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08006202
6203 if (dsp_frames == NULL)
6204 return -EINVAL;
6205
6206 *dsp_frames = 0;
6207 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08006208 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05306209
6210 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
6211 * this operation and adev_close_output_stream(where out gets reset).
6212 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05306213 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006214 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05306215 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006216 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05306217 return 0;
6218 }
6219
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006220 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05306221 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306222 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006223 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306224 if (ret < 0)
6225 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006226 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05306227 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006228 }
Naresh Tanniru80659832014-06-04 18:17:56 +05306229 if (-ENETRESET == ret) {
6230 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306231 out->card_status = CARD_STATUS_OFFLINE;
6232 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306233 } else if(ret < 0) {
6234 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306235 ret = -EINVAL;
6236 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05306237 /*
6238 * Handle corner case where compress session is closed during SSR
6239 * and timestamp is queried
6240 */
6241 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306242 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306243 } else if (out->prev_card_status_offline) {
6244 ALOGE("ERROR: previously sound card was offline,return error");
6245 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306246 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306247 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006248 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05306249 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306250 pthread_mutex_unlock(&out->lock);
6251 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08006252 } else if (audio_is_linear_pcm(out->format)) {
6253 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006254 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08006255 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006256 } else
6257 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006258}
6259
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006260static int out_add_audio_effect(const struct audio_stream *stream __unused,
6261 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006262{
6263 return 0;
6264}
6265
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006266static int out_remove_audio_effect(const struct audio_stream *stream __unused,
6267 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006268{
6269 return 0;
6270}
6271
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006272static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
6273 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006274{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05306275 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006276}
6277
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006278static int out_get_presentation_position(const struct audio_stream_out *stream,
6279 uint64_t *frames, struct timespec *timestamp)
6280{
6281 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05306282 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07006283 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006284
Ashish Jain5106d362016-05-11 19:23:33 +05306285 /* below piece of code is not guarded against any lock because audioFliner serializes
6286 * this operation and adev_close_output_stream( where out gets reset).
6287 */
6288 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05306289 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006290 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05306291 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
6292 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
6293 return 0;
6294 }
6295
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006296 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006297
Ashish Jain5106d362016-05-11 19:23:33 +05306298 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
6299 ret = compress_get_tstamp(out->compr, &dsp_frames,
6300 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08006301 // Adjustment accounts for A2dp encoder latency with offload usecases
6302 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006303 if (is_a2dp_out_device_type(&out->device_list)) {
yidongh0515e042017-07-06 15:00:34 +08006304 unsigned long offset =
6305 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
6306 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
6307 }
Ashish Jain5106d362016-05-11 19:23:33 +05306308 ALOGVV("%s rendered frames %ld sample_rate %d",
6309 __func__, dsp_frames, out->sample_rate);
6310 *frames = dsp_frames;
6311 if (ret < 0)
6312 ret = -errno;
6313 if (-ENETRESET == ret) {
6314 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306315 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05306316 ret = -EINVAL;
6317 } else
6318 ret = 0;
6319 /* this is the best we can do */
6320 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07006321 } else {
6322 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08006323 unsigned int avail;
6324 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
George Gao62ebc722019-07-29 16:29:44 -07006325 uint64_t signed_frames = 0;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006326 uint64_t frames_temp = 0;
George Gao62ebc722019-07-29 16:29:44 -07006327
Andy Hunga1f48fa2019-07-01 18:14:53 -07006328 if (out->kernel_buffer_size > avail) {
6329 frames_temp = out->last_fifo_frames_remaining = out->kernel_buffer_size - avail;
6330 } else {
6331 ALOGW("%s: avail:%u > kernel_buffer_size:%zu clamping!",
6332 __func__, avail, out->kernel_buffer_size);
6333 avail = out->kernel_buffer_size;
6334 frames_temp = out->last_fifo_frames_remaining = 0;
6335 }
6336 out->last_fifo_valid = true;
6337 out->last_fifo_time_ns = audio_utils_ns_from_timespec(timestamp);
6338
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006339 if (out->written >= frames_temp)
6340 signed_frames = out->written - frames_temp;
George Gao62ebc722019-07-29 16:29:44 -07006341
Andy Hunga1f48fa2019-07-01 18:14:53 -07006342 ALOGVV("%s: frames:%lld avail:%u kernel_buffer_size:%zu",
6343 __func__, (long long)signed_frames, avail, out->kernel_buffer_size);
6344
Weiyin Jiangd4633762018-03-16 12:05:03 +08006345 // This adjustment accounts for buffering after app processor.
6346 // It is based on estimated DSP latency per use case, rather than exact.
George Gao9ba8a142020-07-23 14:30:03 -07006347 frames_temp = platform_render_latency(out) *
Robert Lee58215542019-07-15 20:55:12 +08006348 out->sample_rate / 1000000LL;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006349 if (signed_frames >= frames_temp)
6350 signed_frames -= frames_temp;
Aniket Kumar Lataff613152017-07-18 18:19:21 -07006351
Weiyin Jiangd4633762018-03-16 12:05:03 +08006352 // Adjustment accounts for A2dp encoder latency with non offload usecases
6353 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006354 if (is_a2dp_out_device_type(&out->device_list)) {
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006355 frames_temp = audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000;
6356 if (signed_frames >= frames_temp)
6357 signed_frames -= frames_temp;
Weiyin Jiangd4633762018-03-16 12:05:03 +08006358 }
6359
6360 // It would be unusual for this value to be negative, but check just in case ...
George Gao62ebc722019-07-29 16:29:44 -07006361 *frames = signed_frames;
6362 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006363 }
Eric Laurenta7a33042019-07-10 16:20:22 -07006364 } else if (out->card_status == CARD_STATUS_OFFLINE ||
6365 // audioflinger still needs position updates when A2DP is suspended
Jasmine Cha5c2517f2019-09-09 11:07:28 +08006366 (is_a2dp_out_device_type(&out->device_list) && audio_extn_a2dp_source_is_suspended())) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306367 *frames = out->written;
6368 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306369 if (is_offload_usecase(out->usecase))
6370 ret = -EINVAL;
6371 else
6372 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006373 }
6374 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006375 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006376 return ret;
6377}
6378
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006379static int out_set_callback(struct audio_stream_out *stream,
6380 stream_callback_t callback, void *cookie)
6381{
6382 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006383 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006384
6385 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006386 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006387 out->client_callback = callback;
6388 out->client_cookie = cookie;
6389 if (out->adsp_hdlr_stream_handle) {
6390 ret = audio_extn_adsp_hdlr_stream_set_callback(
6391 out->adsp_hdlr_stream_handle,
6392 callback,
6393 cookie);
6394 if (ret)
6395 ALOGW("%s:adsp hdlr callback registration failed %d",
6396 __func__, ret);
6397 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006398 pthread_mutex_unlock(&out->lock);
6399 return 0;
6400}
6401
6402static int out_pause(struct audio_stream_out* stream)
6403{
6404 struct stream_out *out = (struct stream_out *)stream;
6405 int status = -ENOSYS;
6406 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006407 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006408 ALOGD("copl(%p):pause compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306409 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006410 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006411 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306412 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05306413 status = compress_pause(out->compr);
6414
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006415 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006416
Mingming Yin21854652016-04-13 11:54:02 -07006417 if (audio_extn_passthru_is_active()) {
6418 ALOGV("offload use case, pause passthru");
6419 audio_extn_passthru_on_pause(out);
6420 }
6421
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306422 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006423 audio_extn_dts_notify_playback_state(out->usecase, 0,
6424 out->sample_rate, popcount(out->channel_mask),
6425 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006426 }
6427 pthread_mutex_unlock(&out->lock);
6428 }
6429 return status;
6430}
6431
6432static int out_resume(struct audio_stream_out* stream)
6433{
6434 struct stream_out *out = (struct stream_out *)stream;
6435 int status = -ENOSYS;
6436 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006437 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006438 ALOGD("copl(%p):resume compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306439 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006440 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006441 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306442 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306443 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07006444 }
6445 if (!status) {
6446 out->offload_state = OFFLOAD_STATE_PLAYING;
6447 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306448 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006449 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6450 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006451 }
6452 pthread_mutex_unlock(&out->lock);
6453 }
6454 return status;
6455}
6456
6457static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
6458{
6459 struct stream_out *out = (struct stream_out *)stream;
6460 int status = -ENOSYS;
6461 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006462 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006463 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006464 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
6465 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
6466 else
6467 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
6468 pthread_mutex_unlock(&out->lock);
6469 }
6470 return status;
6471}
6472
6473static int out_flush(struct audio_stream_out* stream)
6474{
6475 struct stream_out *out = (struct stream_out *)stream;
6476 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006477 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006478 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006479 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006480 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
6481 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006482 } else {
6483 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
6484 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08006485 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006486 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006487 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006488 return 0;
6489 }
6490 return -ENOSYS;
6491}
6492
Haynes Mathew George16081042017-05-31 17:16:49 -07006493static int out_stop(const struct audio_stream_out* stream)
6494{
6495 struct stream_out *out = (struct stream_out *)stream;
6496 struct audio_device *adev = out->dev;
6497 int ret = -ENOSYS;
6498
6499 ALOGV("%s", __func__);
6500 pthread_mutex_lock(&adev->lock);
6501 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6502 out->playback_started && out->pcm != NULL) {
6503 pcm_stop(out->pcm);
6504 ret = stop_output_stream(out);
6505 out->playback_started = false;
6506 }
6507 pthread_mutex_unlock(&adev->lock);
6508 return ret;
6509}
6510
6511static int out_start(const struct audio_stream_out* stream)
6512{
6513 struct stream_out *out = (struct stream_out *)stream;
6514 struct audio_device *adev = out->dev;
6515 int ret = -ENOSYS;
6516
6517 ALOGV("%s", __func__);
6518 pthread_mutex_lock(&adev->lock);
6519 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6520 !out->playback_started && out->pcm != NULL) {
6521 ret = start_output_stream(out);
6522 if (ret == 0) {
6523 out->playback_started = true;
6524 }
6525 }
6526 pthread_mutex_unlock(&adev->lock);
6527 return ret;
6528}
6529
6530/*
6531 * Modify config->period_count based on min_size_frames
6532 */
6533static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
6534{
6535 int periodCountRequested = (min_size_frames + config->period_size - 1)
6536 / config->period_size;
6537 int periodCount = MMAP_PERIOD_COUNT_MIN;
6538
6539 ALOGV("%s original config.period_size = %d config.period_count = %d",
6540 __func__, config->period_size, config->period_count);
6541
6542 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
6543 periodCount *= 2;
6544 }
6545 config->period_count = periodCount;
6546
6547 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
6548}
6549
Phil Burkfe17efd2019-03-25 10:23:35 -07006550// Read offset for the positional timestamp from a persistent vendor property.
6551// This is to workaround apparent inaccuracies in the timing information that
6552// is used by the AAudio timing model. The inaccuracies can cause glitches.
6553static int64_t get_mmap_out_time_offset() {
6554 const int32_t kDefaultOffsetMicros = 0;
6555 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006556 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07006557 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
6558 return mmap_time_offset_micros * (int64_t)1000;
6559}
6560
Haynes Mathew George16081042017-05-31 17:16:49 -07006561static int out_create_mmap_buffer(const struct audio_stream_out *stream,
6562 int32_t min_size_frames,
6563 struct audio_mmap_buffer_info *info)
6564{
6565 struct stream_out *out = (struct stream_out *)stream;
6566 struct audio_device *adev = out->dev;
6567 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07006568 unsigned int offset1 = 0;
6569 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006570 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006571 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006572 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07006573
Arun Mirpuri5d170872019-03-26 13:21:31 -07006574 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306575 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07006576 pthread_mutex_lock(&adev->lock);
6577
Sharad Sanglec6f32552018-05-04 16:15:38 +05306578 if (CARD_STATUS_OFFLINE == out->card_status ||
6579 CARD_STATUS_OFFLINE == adev->card_status) {
6580 ALOGW("out->card_status or adev->card_status offline, try again");
6581 ret = -EIO;
6582 goto exit;
6583 }
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306584 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07006585 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
6586 ret = -EINVAL;
6587 goto exit;
6588 }
6589 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
6590 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
6591 ret = -ENOSYS;
6592 goto exit;
6593 }
6594 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
6595 if (out->pcm_device_id < 0) {
6596 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6597 __func__, out->pcm_device_id, out->usecase);
6598 ret = -EINVAL;
6599 goto exit;
6600 }
6601
6602 adjust_mmap_period_count(&out->config, min_size_frames);
6603
Arun Mirpuri5d170872019-03-26 13:21:31 -07006604 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006605 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
6606 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
6607 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306608 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306609 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6610 out->card_status = CARD_STATUS_OFFLINE;
6611 adev->card_status = CARD_STATUS_OFFLINE;
6612 ret = -EIO;
6613 goto exit;
6614 }
6615
Haynes Mathew George16081042017-05-31 17:16:49 -07006616 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
6617 step = "open";
6618 ret = -ENODEV;
6619 goto exit;
6620 }
6621 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
6622 if (ret < 0) {
6623 step = "begin";
6624 goto exit;
6625 }
juyuchen626833d2019-06-04 16:48:02 +08006626
6627 info->flags = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006628 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07006629 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07006630 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006631 ret = platform_get_mmap_data_fd(adev->platform,
6632 out->pcm_device_id, 0 /*playback*/,
6633 &info->shared_memory_fd,
6634 &mmap_size);
6635 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07006636 // Fall back to non exclusive mode
6637 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
6638 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07006639 out->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
6640 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, out->mmap_shared_memory_fd);
6641
Arun Mirpuri5d170872019-03-26 13:21:31 -07006642 if (mmap_size < buffer_size) {
6643 step = "mmap";
6644 goto exit;
6645 }
juyuchen626833d2019-06-04 16:48:02 +08006646 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006647 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006648 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006649 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07006650
6651 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
6652 if (ret < 0) {
6653 step = "commit";
6654 goto exit;
6655 }
6656
Phil Burkfe17efd2019-03-25 10:23:35 -07006657 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
6658
Haynes Mathew George16081042017-05-31 17:16:49 -07006659 out->standby = false;
6660 ret = 0;
6661
Arun Mirpuri5d170872019-03-26 13:21:31 -07006662 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006663 __func__, info->shared_memory_address, info->buffer_size_frames);
6664
6665exit:
6666 if (ret != 0) {
6667 if (out->pcm == NULL) {
6668 ALOGE("%s: %s - %d", __func__, step, ret);
6669 } else {
6670 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
6671 pcm_close(out->pcm);
6672 out->pcm = NULL;
6673 }
6674 }
6675 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306676 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07006677 return ret;
6678}
6679
6680static int out_get_mmap_position(const struct audio_stream_out *stream,
6681 struct audio_mmap_position *position)
6682{
6683 struct stream_out *out = (struct stream_out *)stream;
6684 ALOGVV("%s", __func__);
6685 if (position == NULL) {
6686 return -EINVAL;
6687 }
6688 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08006689 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006690 return -ENOSYS;
6691 }
6692 if (out->pcm == NULL) {
6693 return -ENOSYS;
6694 }
6695
6696 struct timespec ts = { 0, 0 };
6697 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
6698 if (ret < 0) {
6699 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
6700 return ret;
6701 }
Phil Burkfe17efd2019-03-25 10:23:35 -07006702 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
6703 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07006704 return 0;
6705}
6706
6707
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006708/** audio_stream_in implementation **/
6709static uint32_t in_get_sample_rate(const struct audio_stream *stream)
6710{
6711 struct stream_in *in = (struct stream_in *)stream;
6712
6713 return in->config.rate;
6714}
6715
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006716static int in_set_sample_rate(struct audio_stream *stream __unused,
6717 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006718{
6719 return -ENOSYS;
6720}
6721
6722static size_t in_get_buffer_size(const struct audio_stream *stream)
6723{
6724 struct stream_in *in = (struct stream_in *)stream;
6725
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006726 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
6727 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07006728 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
6729 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306730 else if(audio_extn_cin_attached_usecase(in))
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306731 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006732
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006733 return in->config.period_size * in->af_period_multiplier *
6734 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006735}
6736
6737static uint32_t in_get_channels(const struct audio_stream *stream)
6738{
6739 struct stream_in *in = (struct stream_in *)stream;
6740
6741 return in->channel_mask;
6742}
6743
6744static audio_format_t in_get_format(const struct audio_stream *stream)
6745{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006746 struct stream_in *in = (struct stream_in *)stream;
6747
6748 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006749}
6750
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006751static int in_set_format(struct audio_stream *stream __unused,
6752 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006753{
6754 return -ENOSYS;
6755}
6756
6757static int in_standby(struct audio_stream *stream)
6758{
6759 struct stream_in *in = (struct stream_in *)stream;
6760 struct audio_device *adev = in->dev;
6761 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306762 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
6763 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006764 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306765
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006766 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006767 if (!in->standby && in->is_st_session) {
6768 ALOGD("%s: sound trigger pcm stop lab", __func__);
6769 audio_extn_sound_trigger_stop_lab(in);
George Gao3018ede2019-10-23 13:23:00 -07006770 if (adev->num_va_sessions > 0)
6771 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006772 in->standby = 1;
6773 }
6774
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006775 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006776 if (adev->adm_deregister_stream)
6777 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
6778
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08006779 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006780 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08006781 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08006782 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08006783 voice_extn_compress_voip_close_input_stream(stream);
6784 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07006785 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6786 do_stop = in->capture_started;
6787 in->capture_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07006788 if (in->mmap_shared_memory_fd >= 0) {
6789 ALOGV("%s: closing mmap_shared_memory_fd = %d",
6790 __func__, in->mmap_shared_memory_fd);
6791 close(in->mmap_shared_memory_fd);
6792 in->mmap_shared_memory_fd = -1;
6793 }
Zhou Songa8895042016-07-05 17:54:22 +08006794 } else {
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306795 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05306796 audio_extn_cin_close_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08006797 }
6798
Arun Mirpuri5d170872019-03-26 13:21:31 -07006799 if (in->pcm) {
6800 ATRACE_BEGIN("pcm_in_close");
6801 pcm_close(in->pcm);
6802 ATRACE_END();
6803 in->pcm = NULL;
6804 }
6805
Carter Hsu2e429db2019-05-14 18:50:52 +08006806 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08006807 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006808
George Gao3018ede2019-10-23 13:23:00 -07006809 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
6810 if (adev->num_va_sessions > 0)
6811 adev->num_va_sessions--;
6812 }
Quinn Malef6050362019-01-30 15:55:40 -08006813
Eric Laurent150dbfe2013-02-27 14:31:02 -08006814 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006815 }
6816 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07006817 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006818 return status;
6819}
6820
Aalique Grahame22e49102018-12-18 14:23:57 -08006821static int in_dump(const struct audio_stream *stream,
6822 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006823{
Aalique Grahame22e49102018-12-18 14:23:57 -08006824 struct stream_in *in = (struct stream_in *)stream;
6825
6826 // We try to get the lock for consistency,
6827 // but it isn't necessary for these variables.
6828 // If we're not in standby, we may be blocked on a read.
6829 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
6830 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
6831 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
6832 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
6833
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006834 char buffer[256]; // for statistics formatting
6835 if (in->start_latency_ms.n > 0) {
6836 simple_stats_to_string(&in->start_latency_ms, buffer, sizeof(buffer));
6837 dprintf(fd, " Start latency ms: %s\n", buffer);
6838 }
6839
Aalique Grahame22e49102018-12-18 14:23:57 -08006840 if (locked) {
6841 pthread_mutex_unlock(&in->lock);
6842 }
6843
6844 // dump error info
6845 (void)error_log_dump(
6846 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
6847
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006848 return 0;
6849}
6850
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306851static void in_snd_mon_cb(void * stream, struct str_parms * parms)
6852{
6853 if (!stream || !parms)
6854 return;
6855
6856 struct stream_in *in = (struct stream_in *)stream;
6857 struct audio_device *adev = in->dev;
6858
6859 card_status_t status;
6860 int card;
6861 if (parse_snd_card_status(parms, &card, &status) < 0)
6862 return;
6863
6864 pthread_mutex_lock(&adev->lock);
6865 bool valid_cb = (card == adev->snd_card);
6866 pthread_mutex_unlock(&adev->lock);
6867
6868 if (!valid_cb)
6869 return;
6870
6871 lock_input_stream(in);
6872 if (in->card_status != status)
6873 in->card_status = status;
6874 pthread_mutex_unlock(&in->lock);
6875
6876 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
6877 use_case_table[in->usecase],
6878 status == CARD_STATUS_OFFLINE ? "offline" : "online");
6879
6880 // a better solution would be to report error back to AF and let
6881 // it put the stream to standby
6882 if (status == CARD_STATUS_OFFLINE)
6883 in_standby(&in->stream.common);
6884
6885 return;
6886}
6887
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006888int route_input_stream(struct stream_in *in,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006889 struct listnode *devices,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006890 audio_source_t source)
6891{
6892 struct audio_device *adev = in->dev;
6893 int ret = 0;
6894
6895 lock_input_stream(in);
6896 pthread_mutex_lock(&adev->lock);
6897
6898 /* no audio source uses val == 0 */
6899 if ((in->source != source) && (source != AUDIO_SOURCE_DEFAULT)) {
6900 in->source = source;
6901 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6902 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
6903 (voice_extn_compress_voip_is_format_supported(in->format)) &&
6904 (in->config.rate == 8000 || in->config.rate == 16000 ||
6905 in->config.rate == 32000 || in->config.rate == 48000 ) &&
6906 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
6907 ret = voice_extn_compress_voip_open_input_stream(in);
6908 if (ret != 0) {
6909 ALOGE("%s: Compress voip input cannot be opened, error:%d",
6910 __func__, ret);
6911 }
6912 }
6913 }
6914
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006915 if (!compare_devices(&in->device_list, devices) && !list_empty(devices) &&
6916 is_audio_in_device_type(devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006917 // Workaround: If routing to an non existing usb device, fail gracefully
6918 // The routing request will otherwise block during 10 second
6919 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006920 struct str_parms *usb_addr =
6921 str_parms_create_str(get_usb_device_address(devices));
6922 if (is_usb_in_device_type(devices) && usb_addr &&
6923 (card = get_alive_usb_card(usb_addr)) >= 0) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006924 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
6925 ret = -ENOSYS;
6926 } else {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006927 /* If recording is in progress, change the tx device to new device */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006928 assign_devices(&in->device_list, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006929 if (!in->standby && !in->is_st_session) {
6930 ALOGV("update input routing change");
6931 // inform adm before actual routing to prevent glitches.
6932 if (adev->adm_on_routing_change) {
6933 adev->adm_on_routing_change(adev->adm_data,
6934 in->capture_handle);
6935 ret = select_devices(adev, in->usecase);
6936 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6937 adev->adm_routing_changed = true;
6938 }
6939 }
6940 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006941 if (usb_addr)
6942 str_parms_destroy(usb_addr);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006943 }
6944 pthread_mutex_unlock(&adev->lock);
6945 pthread_mutex_unlock(&in->lock);
6946
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07006947 ALOGV("%s: exit: status(%d)", __func__, ret);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006948 return ret;
6949}
6950
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006951static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
6952{
6953 struct stream_in *in = (struct stream_in *)stream;
6954 struct audio_device *adev = in->dev;
6955 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006956 char value[32];
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306957 int err = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006958
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306959 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006960 parms = str_parms_create_str(kvpairs);
6961
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306962 if (!parms)
6963 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006964 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006965 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006966
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306967 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
6968 if (err >= 0) {
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306969 strlcpy(in->profile, value, sizeof(in->profile));
6970 ALOGV("updating stream profile with value '%s'", in->profile);
6971 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
6972 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006973 &in->device_list, in->flags, in->format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306974 in->sample_rate, in->bit_width,
6975 in->profile, &in->app_type_cfg);
6976 }
6977
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006978 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006979 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006980
6981 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306982error:
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306983 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006984}
6985
6986static char* in_get_parameters(const struct audio_stream *stream,
6987 const char *keys)
6988{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006989 struct stream_in *in = (struct stream_in *)stream;
6990 struct str_parms *query = str_parms_create_str(keys);
6991 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006992 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006993
6994 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08006995 if (reply) {
6996 str_parms_destroy(reply);
6997 }
6998 if (query) {
6999 str_parms_destroy(query);
7000 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007001 ALOGE("in_get_parameters: failed to create query or reply");
7002 return NULL;
7003 }
7004
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007005 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007006
7007 voice_extn_in_get_parameters(in, query, reply);
7008
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007009 stream_get_parameter_channels(query, reply,
7010 &in->supported_channel_masks[0]);
7011 stream_get_parameter_formats(query, reply,
7012 &in->supported_formats[0]);
7013 stream_get_parameter_rates(query, reply,
7014 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007015 str = str_parms_to_str(reply);
7016 str_parms_destroy(query);
7017 str_parms_destroy(reply);
7018
7019 ALOGV("%s: exit: returns - %s", __func__, str);
7020 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007021}
7022
Aalique Grahame22e49102018-12-18 14:23:57 -08007023static int in_set_gain(struct audio_stream_in *stream,
7024 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007025{
Aalique Grahame22e49102018-12-18 14:23:57 -08007026 struct stream_in *in = (struct stream_in *)stream;
7027 char mixer_ctl_name[128];
7028 struct mixer_ctl *ctl;
7029 int ctl_value;
7030
7031 ALOGV("%s: gain %f", __func__, gain);
7032
7033 if (stream == NULL)
7034 return -EINVAL;
7035
7036 /* in_set_gain() only used to silence MMAP capture for now */
7037 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
7038 return -ENOSYS;
7039
7040 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
7041
7042 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
7043 if (!ctl) {
7044 ALOGW("%s: Could not get ctl for mixer cmd - %s",
7045 __func__, mixer_ctl_name);
7046 return -ENOSYS;
7047 }
7048
7049 if (gain < RECORD_GAIN_MIN)
7050 gain = RECORD_GAIN_MIN;
7051 else if (gain > RECORD_GAIN_MAX)
7052 gain = RECORD_GAIN_MAX;
7053 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
7054
7055 mixer_ctl_set_value(ctl, 0, ctl_value);
7056
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007057 return 0;
7058}
7059
7060static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
7061 size_t bytes)
7062{
7063 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05307064
7065 if (in == NULL) {
7066 ALOGE("%s: stream_in ptr is NULL", __func__);
7067 return -EINVAL;
7068 }
7069
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007070 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05307071 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307072 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007073
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007074 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05307075
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007076 if (in->is_st_session) {
7077 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
7078 /* Read from sound trigger HAL */
7079 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08007080 if (in->standby) {
George Gao3018ede2019-10-23 13:23:00 -07007081 if (adev->num_va_sessions < UINT_MAX)
7082 adev->num_va_sessions++;
Quinn Malef6050362019-01-30 15:55:40 -08007083 in->standby = 0;
7084 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007085 pthread_mutex_unlock(&in->lock);
7086 return bytes;
7087 }
7088
Haynes Mathew George16081042017-05-31 17:16:49 -07007089 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
7090 ret = -ENOSYS;
7091 goto exit;
7092 }
7093
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007094 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
7095 !in->standby && adev->adm_routing_changed) {
7096 ret = -ENOSYS;
7097 goto exit;
7098 }
7099
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007100 if (in->standby) {
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007101 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
7102
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007103 pthread_mutex_lock(&adev->lock);
7104 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
7105 ret = voice_extn_compress_voip_start_input_stream(in);
7106 else
7107 ret = start_input_stream(in);
George Gao3018ede2019-10-23 13:23:00 -07007108 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
7109 if (adev->num_va_sessions < UINT_MAX)
7110 adev->num_va_sessions++;
7111 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007112 pthread_mutex_unlock(&adev->lock);
7113 if (ret != 0) {
7114 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007115 }
7116 in->standby = 0;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007117
7118 // log startup time in ms.
7119 simple_stats_log(
7120 &in->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007121 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007122
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05307123 /* Avoid read if capture_stopped is set */
7124 if (android_atomic_acquire_load(&(in->capture_stopped)) > 0) {
7125 ALOGD("%s: force stopped catpure session, ignoring read request", __func__);
7126 ret = -EINVAL;
7127 goto exit;
7128 }
7129
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007130 // what's the duration requested by the client?
7131 long ns = 0;
7132
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307133 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007134 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
7135 in->config.rate;
7136
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007137 ret = request_in_focus(in, ns);
7138 if (ret != 0)
7139 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007140 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007141
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307142 if (audio_extn_cin_attached_usecase(in)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307143 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
7144 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307145 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007146 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307147 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07007148 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007149 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007150 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07007151 } else if (audio_extn_ffv_get_stream() == in) {
7152 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307153 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007154 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307155 /* data from DSP comes in 24_8 format, convert it to 8_24 */
7156 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
7157 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
7158 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307159 ret = -EINVAL;
7160 goto exit;
7161 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307162 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307163 ret = -errno;
7164 }
7165 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307166 /* bytes read is always set to bytes for non compress usecases */
7167 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007168 }
7169
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007170 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007171
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007172 /*
Quinn Malef6050362019-01-30 15:55:40 -08007173 * Instead of writing zeroes here, we could trust the hardware to always
7174 * provide zeroes when muted. This is also muted with voice recognition
7175 * usecases so that other clients do not have access to voice recognition
7176 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007177 */
Quinn Malef6050362019-01-30 15:55:40 -08007178 if ((ret == 0 && voice_get_mic_mute(adev) &&
7179 !voice_is_in_call_rec_stream(in) &&
Zhou Song62ea0282020-03-22 19:53:01 +08007180 (in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY &&
7181 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY2)) ||
Quinn Malef6050362019-01-30 15:55:40 -08007182 (adev->num_va_sessions &&
7183 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
7184 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
7185 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007186 memset(buffer, 0, bytes);
7187
7188exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307189 frame_size = audio_stream_in_frame_size(stream);
7190 if (frame_size > 0)
7191 in->frames_read += bytes_read/frame_size;
7192
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007193 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307194 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007195 pthread_mutex_unlock(&in->lock);
7196
7197 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307198 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307199 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307200 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307201 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307202 in->standby = true;
7203 }
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307204 if (!audio_extn_cin_attached_usecase(in)) {
Sharad Sangled17c9122017-03-20 15:58:52 +05307205 bytes_read = bytes;
7206 memset(buffer, 0, bytes);
7207 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007208 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007209 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7210 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007211 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05307212 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05307213 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007214 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307215 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007216}
7217
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007218static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007219{
7220 return 0;
7221}
7222
Aalique Grahame22e49102018-12-18 14:23:57 -08007223static int in_get_capture_position(const struct audio_stream_in *stream,
7224 int64_t *frames, int64_t *time)
7225{
7226 if (stream == NULL || frames == NULL || time == NULL) {
7227 return -EINVAL;
7228 }
7229 struct stream_in *in = (struct stream_in *)stream;
7230 int ret = -ENOSYS;
7231
7232 lock_input_stream(in);
7233 // note: ST sessions do not close the alsa pcm driver synchronously
7234 // on standby. Therefore, we may return an error even though the
7235 // pcm stream is still opened.
7236 if (in->standby) {
7237 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
7238 "%s stream in standby but pcm not NULL for non ST session", __func__);
7239 goto exit;
7240 }
7241 if (in->pcm) {
7242 struct timespec timestamp;
7243 unsigned int avail;
7244 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
7245 *frames = in->frames_read + avail;
Robert Lee58215542019-07-15 20:55:12 +08007246 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec
George Gao9ba8a142020-07-23 14:30:03 -07007247 - platform_capture_latency(in) * 1000LL;
Aalique Grahame22e49102018-12-18 14:23:57 -08007248 ret = 0;
7249 }
7250 }
7251exit:
7252 pthread_mutex_unlock(&in->lock);
7253 return ret;
7254}
7255
Carter Hsu2e429db2019-05-14 18:50:52 +08007256static int in_update_effect_list(bool add, effect_handle_t effect,
7257 struct listnode *head)
7258{
7259 struct listnode *node;
7260 struct in_effect_list *elist = NULL;
7261 struct in_effect_list *target = NULL;
7262 int ret = 0;
7263
7264 if (!head)
7265 return ret;
7266
7267 list_for_each(node, head) {
7268 elist = node_to_item(node, struct in_effect_list, list);
7269 if (elist->handle == effect) {
7270 target = elist;
7271 break;
7272 }
7273 }
7274
7275 if (add) {
7276 if (target) {
7277 ALOGD("effect %p already exist", effect);
7278 return ret;
7279 }
7280
7281 target = (struct in_effect_list *)
7282 calloc(1, sizeof(struct in_effect_list));
7283
7284 if (!target) {
7285 ALOGE("%s:fail to allocate memory", __func__);
7286 return -ENOMEM;
7287 }
7288
7289 target->handle = effect;
7290 list_add_tail(head, &target->list);
7291 } else {
7292 if (target) {
7293 list_remove(&target->list);
7294 free(target);
7295 }
7296 }
7297
7298 return ret;
7299}
7300
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007301static int add_remove_audio_effect(const struct audio_stream *stream,
7302 effect_handle_t effect,
7303 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007304{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007305 struct stream_in *in = (struct stream_in *)stream;
7306 int status = 0;
7307 effect_descriptor_t desc;
7308
7309 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007310 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
7311
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007312 if (status != 0)
7313 return status;
7314
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007315 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007316 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08007317 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08007318 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
7319 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007320 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08007321
7322 in_update_effect_list(enable, effect, &in->aec_list);
7323 enable = !list_empty(&in->aec_list);
7324 if (enable == in->enable_aec)
7325 goto exit;
7326
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007327 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007328 ALOGD("AEC enable %d", enable);
7329
Aalique Grahame22e49102018-12-18 14:23:57 -08007330 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7331 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
7332 in->dev->enable_voicerx = enable;
7333 struct audio_usecase *usecase;
7334 struct listnode *node;
7335 list_for_each(node, &in->dev->usecase_list) {
7336 usecase = node_to_item(node, struct audio_usecase, list);
7337 if (usecase->type == PCM_PLAYBACK)
7338 select_devices(in->dev, usecase->id);
7339 }
7340 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007341 if (!in->standby) {
7342 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
7343 select_devices(in->dev, in->usecase);
7344 }
7345
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007346 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007347 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
7348
7349 in_update_effect_list(enable, effect, &in->ns_list);
7350 enable = !list_empty(&in->ns_list);
7351 if (enable == in->enable_ns)
7352 goto exit;
7353
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007354 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007355 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007356 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08007357 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7358 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007359 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
7360 select_devices(in->dev, in->usecase);
7361 } else
7362 select_devices(in->dev, in->usecase);
7363 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007364 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007365exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007366 pthread_mutex_unlock(&in->dev->lock);
7367 pthread_mutex_unlock(&in->lock);
7368
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007369 return 0;
7370}
7371
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007372static int in_add_audio_effect(const struct audio_stream *stream,
7373 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007374{
Eric Laurent994a6932013-07-17 11:51:42 -07007375 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007376 return add_remove_audio_effect(stream, effect, true);
7377}
7378
7379static int in_remove_audio_effect(const struct audio_stream *stream,
7380 effect_handle_t effect)
7381{
Eric Laurent994a6932013-07-17 11:51:42 -07007382 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007383 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007384}
7385
Derek Chenf939fb72018-11-13 13:34:41 -08007386streams_input_ctxt_t *in_get_stream(struct audio_device *dev,
7387 audio_io_handle_t input)
7388{
7389 struct listnode *node;
7390
7391 list_for_each(node, &dev->active_inputs_list) {
7392 streams_input_ctxt_t *in_ctxt = node_to_item(node,
7393 streams_input_ctxt_t,
7394 list);
7395 if (in_ctxt->input->capture_handle == input) {
7396 return in_ctxt;
7397 }
7398 }
7399 return NULL;
7400}
7401
7402streams_output_ctxt_t *out_get_stream(struct audio_device *dev,
7403 audio_io_handle_t output)
7404{
7405 struct listnode *node;
7406
7407 list_for_each(node, &dev->active_outputs_list) {
7408 streams_output_ctxt_t *out_ctxt = node_to_item(node,
7409 streams_output_ctxt_t,
7410 list);
7411 if (out_ctxt->output->handle == output) {
7412 return out_ctxt;
7413 }
7414 }
7415 return NULL;
7416}
7417
Haynes Mathew George16081042017-05-31 17:16:49 -07007418static int in_stop(const struct audio_stream_in* stream)
7419{
7420 struct stream_in *in = (struct stream_in *)stream;
7421 struct audio_device *adev = in->dev;
7422
7423 int ret = -ENOSYS;
7424 ALOGV("%s", __func__);
7425 pthread_mutex_lock(&adev->lock);
7426 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7427 in->capture_started && in->pcm != NULL) {
7428 pcm_stop(in->pcm);
7429 ret = stop_input_stream(in);
7430 in->capture_started = false;
7431 }
7432 pthread_mutex_unlock(&adev->lock);
7433 return ret;
7434}
7435
7436static int in_start(const struct audio_stream_in* stream)
7437{
7438 struct stream_in *in = (struct stream_in *)stream;
7439 struct audio_device *adev = in->dev;
7440 int ret = -ENOSYS;
7441
7442 ALOGV("%s in %p", __func__, in);
7443 pthread_mutex_lock(&adev->lock);
7444 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7445 !in->capture_started && in->pcm != NULL) {
7446 if (!in->capture_started) {
7447 ret = start_input_stream(in);
7448 if (ret == 0) {
7449 in->capture_started = true;
7450 }
7451 }
7452 }
7453 pthread_mutex_unlock(&adev->lock);
7454 return ret;
7455}
7456
Phil Burke0a86d12019-02-16 22:28:11 -08007457// Read offset for the positional timestamp from a persistent vendor property.
7458// This is to workaround apparent inaccuracies in the timing information that
7459// is used by the AAudio timing model. The inaccuracies can cause glitches.
7460static int64_t in_get_mmap_time_offset() {
7461 const int32_t kDefaultOffsetMicros = 0;
7462 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08007463 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08007464 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
7465 return mmap_time_offset_micros * (int64_t)1000;
7466}
7467
Haynes Mathew George16081042017-05-31 17:16:49 -07007468static int in_create_mmap_buffer(const struct audio_stream_in *stream,
7469 int32_t min_size_frames,
7470 struct audio_mmap_buffer_info *info)
7471{
7472 struct stream_in *in = (struct stream_in *)stream;
7473 struct audio_device *adev = in->dev;
7474 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07007475 unsigned int offset1 = 0;
7476 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007477 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07007478 uint32_t mmap_size = 0;
7479 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007480
7481 pthread_mutex_lock(&adev->lock);
7482 ALOGV("%s in %p", __func__, in);
7483
Sharad Sanglec6f32552018-05-04 16:15:38 +05307484 if (CARD_STATUS_OFFLINE == in->card_status||
7485 CARD_STATUS_OFFLINE == adev->card_status) {
7486 ALOGW("in->card_status or adev->card_status offline, try again");
7487 ret = -EIO;
7488 goto exit;
7489 }
7490
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307491 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07007492 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
7493 ret = -EINVAL;
7494 goto exit;
7495 }
7496 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
7497 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
7498 ALOGV("%s in %p", __func__, in);
7499 ret = -ENOSYS;
7500 goto exit;
7501 }
7502 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
7503 if (in->pcm_device_id < 0) {
7504 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
7505 __func__, in->pcm_device_id, in->usecase);
7506 ret = -EINVAL;
7507 goto exit;
7508 }
7509
7510 adjust_mmap_period_count(&in->config, min_size_frames);
7511
7512 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
7513 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
7514 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
7515 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307516 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307517 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7518 in->card_status = CARD_STATUS_OFFLINE;
7519 adev->card_status = CARD_STATUS_OFFLINE;
7520 ret = -EIO;
7521 goto exit;
7522 }
7523
Haynes Mathew George16081042017-05-31 17:16:49 -07007524 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
7525 step = "open";
7526 ret = -ENODEV;
7527 goto exit;
7528 }
7529
7530 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
7531 if (ret < 0) {
7532 step = "begin";
7533 goto exit;
7534 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007535
juyuchen626833d2019-06-04 16:48:02 +08007536 info->flags = 0;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007537 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
7538 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
7539 info->burst_size_frames = in->config.period_size;
7540 ret = platform_get_mmap_data_fd(adev->platform,
7541 in->pcm_device_id, 1 /*capture*/,
7542 &info->shared_memory_fd,
7543 &mmap_size);
7544 if (ret < 0) {
7545 // Fall back to non exclusive mode
7546 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
7547 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07007548 in->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
7549 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, in->mmap_shared_memory_fd);
7550
Arun Mirpuri5d170872019-03-26 13:21:31 -07007551 if (mmap_size < buffer_size) {
7552 step = "mmap";
7553 goto exit;
7554 }
juyuchen626833d2019-06-04 16:48:02 +08007555 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007556 }
7557
7558 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07007559
7560 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
7561 if (ret < 0) {
7562 step = "commit";
7563 goto exit;
7564 }
7565
Phil Burke0a86d12019-02-16 22:28:11 -08007566 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
7567
Haynes Mathew George16081042017-05-31 17:16:49 -07007568 in->standby = false;
7569 ret = 0;
7570
7571 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
7572 __func__, info->shared_memory_address, info->buffer_size_frames);
7573
7574exit:
7575 if (ret != 0) {
7576 if (in->pcm == NULL) {
7577 ALOGE("%s: %s - %d", __func__, step, ret);
7578 } else {
7579 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
7580 pcm_close(in->pcm);
7581 in->pcm = NULL;
7582 }
7583 }
7584 pthread_mutex_unlock(&adev->lock);
7585 return ret;
7586}
7587
7588static int in_get_mmap_position(const struct audio_stream_in *stream,
7589 struct audio_mmap_position *position)
7590{
7591 struct stream_in *in = (struct stream_in *)stream;
7592 ALOGVV("%s", __func__);
7593 if (position == NULL) {
7594 return -EINVAL;
7595 }
7596 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
7597 return -ENOSYS;
7598 }
7599 if (in->pcm == NULL) {
7600 return -ENOSYS;
7601 }
7602 struct timespec ts = { 0, 0 };
7603 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
7604 if (ret < 0) {
7605 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
7606 return ret;
7607 }
Phil Burke0a86d12019-02-16 22:28:11 -08007608 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7609 + in->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07007610 return 0;
7611}
7612
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307613static int in_get_active_microphones(const struct audio_stream_in *stream,
7614 struct audio_microphone_characteristic_t *mic_array,
7615 size_t *mic_count) {
7616 struct stream_in *in = (struct stream_in *)stream;
7617 struct audio_device *adev = in->dev;
7618 ALOGVV("%s", __func__);
7619
7620 lock_input_stream(in);
7621 pthread_mutex_lock(&adev->lock);
7622 int ret = platform_get_active_microphones(adev->platform,
7623 audio_channel_count_from_in_mask(in->channel_mask),
7624 in->usecase, mic_array, mic_count);
7625 pthread_mutex_unlock(&adev->lock);
7626 pthread_mutex_unlock(&in->lock);
7627
7628 return ret;
7629}
7630
7631static int adev_get_microphones(const struct audio_hw_device *dev,
7632 struct audio_microphone_characteristic_t *mic_array,
7633 size_t *mic_count) {
7634 struct audio_device *adev = (struct audio_device *)dev;
7635 ALOGVV("%s", __func__);
7636
7637 pthread_mutex_lock(&adev->lock);
7638 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
7639 pthread_mutex_unlock(&adev->lock);
7640
7641 return ret;
7642}
juyuchendb308c22019-01-21 11:57:17 -07007643
7644static void in_update_sink_metadata(struct audio_stream_in *stream,
7645 const struct sink_metadata *sink_metadata) {
7646
7647 if (stream == NULL
7648 || sink_metadata == NULL
7649 || sink_metadata->tracks == NULL) {
7650 return;
7651 }
7652
7653 int error = 0;
7654 struct stream_in *in = (struct stream_in *)stream;
7655 struct audio_device *adev = in->dev;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007656 struct listnode devices;
Zhou Song62ea0282020-03-22 19:53:01 +08007657 bool is_ha_usecase = false;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007658
7659 list_init(&devices);
juyuchendb308c22019-01-21 11:57:17 -07007660
7661 if (sink_metadata->track_count != 0)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007662 reassign_device_list(&devices, sink_metadata->tracks->dest_device, "");
juyuchendb308c22019-01-21 11:57:17 -07007663
7664 lock_input_stream(in);
7665 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007666 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, get_device_types(&devices));
juyuchendb308c22019-01-21 11:57:17 -07007667
Zhou Song62ea0282020-03-22 19:53:01 +08007668 is_ha_usecase = adev->ha_proxy_enable ?
7669 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2 :
7670 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY;
7671 if (is_ha_usecase && !list_empty(&devices)
juyuchendb308c22019-01-21 11:57:17 -07007672 && adev->voice_tx_output != NULL) {
7673 /* Use the rx device from afe-proxy record to route voice call because
7674 there is no routing if tx device is on primary hal and rx device
7675 is on other hal during voice call. */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007676 assign_devices(&adev->voice_tx_output->device_list, &devices);
juyuchendb308c22019-01-21 11:57:17 -07007677
7678 if (!voice_is_call_state_active(adev)) {
7679 if (adev->mode == AUDIO_MODE_IN_CALL) {
7680 adev->current_call_output = adev->voice_tx_output;
7681 error = voice_start_call(adev);
7682 if (error != 0)
7683 ALOGE("%s: start voice call failed %d", __func__, error);
7684 }
7685 } else {
7686 adev->current_call_output = adev->voice_tx_output;
7687 voice_update_devices_for_all_voice_usecases(adev);
7688 }
7689 }
7690
7691 pthread_mutex_unlock(&adev->lock);
7692 pthread_mutex_unlock(&in->lock);
7693}
7694
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307695int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07007696 audio_io_handle_t handle,
7697 audio_devices_t devices,
7698 audio_output_flags_t flags,
7699 struct audio_config *config,
7700 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04007701 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007702{
7703 struct audio_device *adev = (struct audio_device *)dev;
7704 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05307705 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007706 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007707 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05307708 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007709 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
7710 bool is_usb_dev = audio_is_usb_out_device(devices) &&
7711 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
7712 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007713 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07007714 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
7715 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007716 bool force_haptic_path =
7717 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007718 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08007719#ifdef AUDIO_GKI_ENABLED
7720 __s32 *generic_dec;
7721#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007722
kunleizdff872d2018-08-20 14:40:33 +08007723 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007724 is_usb_dev = false;
7725 devices = AUDIO_DEVICE_OUT_SPEAKER;
7726 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
7727 __func__, devices);
Mingshu Pangdbd20562019-11-25 18:04:39 +08007728 if (config->format == AUDIO_FORMAT_DEFAULT)
7729 config->format = AUDIO_FORMAT_PCM_16_BIT;
7730 if (config->sample_rate == 0)
7731 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7732 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7733 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
kunleizd6a9e0c2018-07-30 15:38:52 +08007734 }
7735
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007736 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05307737
Rahul Sharma99770982019-03-06 17:05:26 +05307738 pthread_mutex_lock(&adev->lock);
7739 if (out_get_stream(adev, handle) != NULL) {
7740 ALOGW("%s, output stream already opened", __func__);
7741 ret = -EEXIST;
7742 }
7743 pthread_mutex_unlock(&adev->lock);
7744 if (ret)
7745 return ret;
7746
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007747 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
7748
Mingming Yin3a941d42016-02-17 18:08:05 -08007749 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04007750 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
7751 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307752
7753
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007754 if (!out) {
7755 return -ENOMEM;
7756 }
7757
Haynes Mathew George204045b2015-02-25 20:32:03 -08007758 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007759 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307760 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08007761 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08007762 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
7763
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007764 if (devices == AUDIO_DEVICE_NONE)
7765 devices = AUDIO_DEVICE_OUT_SPEAKER;
7766
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007767 out->flags = flags;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007768 list_init(&out->device_list);
7769 update_device_list(&out->device_list, devices, address, true /* add devices */);
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07007770 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07007771 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007772 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05307773 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05307774 if (out->channel_mask == AUDIO_CHANNEL_NONE)
7775 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
7776 else
7777 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07007778 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007779 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08007780 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307781 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307782 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307783 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007784 out->hal_output_suspend_supported = 0;
7785 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05307786 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05307787 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05307788 out->pspd_coeff_sent = false;
Phil Burkd898ba62019-06-20 12:49:01 -07007789 out->mmap_shared_memory_fd = -1; // not open
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007790
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05307791 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05307792 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07007793 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
7794
Aalique Grahame22e49102018-12-18 14:23:57 -08007795 if (direct_dev &&
7796 (audio_is_linear_pcm(out->format) ||
7797 config->format == AUDIO_FORMAT_DEFAULT) &&
7798 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
7799 audio_format_t req_format = config->format;
7800 audio_channel_mask_t req_channel_mask = config->channel_mask;
7801 uint32_t req_sample_rate = config->sample_rate;
7802
7803 pthread_mutex_lock(&adev->lock);
7804 if (is_hdmi) {
7805 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
7806 ret = read_hdmi_sink_caps(out);
7807 if (config->sample_rate == 0)
7808 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7809 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7810 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
7811 if (config->format == AUDIO_FORMAT_DEFAULT)
7812 config->format = AUDIO_FORMAT_PCM_16_BIT;
7813 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007814 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
7815 &config->format,
7816 &out->supported_formats[0],
7817 MAX_SUPPORTED_FORMATS,
7818 &config->channel_mask,
7819 &out->supported_channel_masks[0],
7820 MAX_SUPPORTED_CHANNEL_MASKS,
7821 &config->sample_rate,
7822 &out->supported_sample_rates[0],
7823 MAX_SUPPORTED_SAMPLE_RATES);
7824 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007825 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007826
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007827 pthread_mutex_unlock(&adev->lock);
7828 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007829 if (ret == -ENOSYS) {
7830 /* ignore and go with default */
7831 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007832 }
7833 // For MMAP NO IRQ, allow conversions in ADSP
7834 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
7835 goto error_open;
7836 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007837 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08007838 goto error_open;
7839 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007840
7841 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
7842 config->sample_rate = req_sample_rate;
7843 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
7844 config->channel_mask = req_channel_mask;
7845 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
7846 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08007847 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007848
7849 out->sample_rate = config->sample_rate;
7850 out->channel_mask = config->channel_mask;
7851 out->format = config->format;
7852 if (is_hdmi) {
7853 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7854 out->config = pcm_config_hdmi_multi;
7855 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7856 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7857 out->config = pcm_config_mmap_playback;
7858 out->stream.start = out_start;
7859 out->stream.stop = out_stop;
7860 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7861 out->stream.get_mmap_position = out_get_mmap_position;
7862 } else {
7863 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7864 out->config = pcm_config_hifi;
7865 }
7866
7867 out->config.rate = out->sample_rate;
7868 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7869 if (is_hdmi) {
7870 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7871 audio_bytes_per_sample(out->format));
7872 }
7873 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08007874 }
7875
Derek Chenf6318be2017-06-12 17:16:24 -04007876 /* validate bus device address */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007877 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04007878 /* extract car audio stream index */
7879 out->car_audio_stream =
7880 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
7881 if (out->car_audio_stream < 0) {
7882 ALOGE("%s: invalid car audio stream %x",
7883 __func__, out->car_audio_stream);
7884 ret = -EINVAL;
7885 goto error_open;
7886 }
Derek Chen5f67a942020-02-24 23:08:13 -08007887 ALOGV("%s: car_audio_stream %x", __func__, out->car_audio_stream);
Derek Chenf6318be2017-06-12 17:16:24 -04007888 }
7889
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007890 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007891 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007892 if (!voice_extn_is_compress_voip_supported()) {
7893 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
7894 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07007895 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
Lakshman Chaluvarajue7fc9482020-05-30 14:29:29 +05307896 config->channel_mask : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007897 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
7898 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07007899 out->volume_l = INVALID_OUT_VOLUME;
7900 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07007901
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007902 out->config = default_pcm_config_voip_copp;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007903 out->config.rate = out->sample_rate;
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007904 uint32_t channel_count =
7905 audio_channel_count_from_out_mask(out->channel_mask);
Ramjee Singh968858a2020-08-06 16:30:48 +05307906 out->config.channels = channel_count;
7907
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007908 uint32_t buffer_size = get_stream_buffer_size(DEFAULT_VOIP_BUF_DURATION_MS,
7909 out->sample_rate, out->format,
7910 channel_count, false);
7911 uint32_t frame_size = audio_bytes_per_sample(out->format) * channel_count;
7912 if (frame_size != 0)
7913 out->config.period_size = buffer_size / frame_size;
7914 else
7915 ALOGW("%s: frame size is 0 for format %#x", __func__, out->format);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007916 }
7917 } else {
7918 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7919 voice_extn_compress_voip_is_active(out->dev)) &&
7920 (voice_extn_compress_voip_is_config_supported(config))) {
7921 ret = voice_extn_compress_voip_open_output_stream(out);
7922 if (ret != 0) {
7923 ALOGE("%s: Compress voip output cannot be opened, error:%d",
7924 __func__, ret);
7925 goto error_open;
7926 }
Sujin Panicker19027262019-09-16 18:28:06 +05307927 } else {
7928 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
7929 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007930 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007931 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007932 } else if (audio_is_linear_pcm(out->format) &&
7933 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
7934 out->channel_mask = config->channel_mask;
7935 out->sample_rate = config->sample_rate;
7936 out->format = config->format;
7937 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7938 // does this change?
7939 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
7940 out->config.rate = config->sample_rate;
7941 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7942 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7943 audio_bytes_per_sample(config->format));
7944 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07007945 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307946 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307947 pthread_mutex_lock(&adev->lock);
7948 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
7949 pthread_mutex_unlock(&adev->lock);
7950
7951 // reject offload during card offline to allow
7952 // fallback to s/w paths
7953 if (offline) {
7954 ret = -ENODEV;
7955 goto error_open;
7956 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007957
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007958 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
7959 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
7960 ALOGE("%s: Unsupported Offload information", __func__);
7961 ret = -EINVAL;
7962 goto error_open;
7963 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007964
Atul Khare3fa6e542017-08-09 00:56:17 +05307965 if (config->offload_info.format == 0)
7966 config->offload_info.format = config->format;
7967 if (config->offload_info.sample_rate == 0)
7968 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007969
Mingming Yin90310102013-11-13 16:57:00 -08007970 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307971 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07007972 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007973 ret = -EINVAL;
7974 goto error_open;
7975 }
7976
Ben Romberger0f8c87b2017-05-24 17:41:11 -07007977 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
7978 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
7979 (audio_extn_passthru_is_passthrough_stream(out)) &&
7980 !((config->sample_rate == 48000) ||
7981 (config->sample_rate == 96000) ||
7982 (config->sample_rate == 192000))) {
7983 ALOGE("%s: Unsupported sample rate %d for audio format %x",
7984 __func__, config->sample_rate, config->offload_info.format);
7985 ret = -EINVAL;
7986 goto error_open;
7987 }
7988
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007989 out->compr_config.codec = (struct snd_codec *)
7990 calloc(1, sizeof(struct snd_codec));
7991
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007992 if (!out->compr_config.codec) {
7993 ret = -ENOMEM;
7994 goto error_open;
7995 }
7996
Dhananjay Kumarac341582017-02-23 23:42:25 +05307997 out->stream.pause = out_pause;
7998 out->stream.resume = out_resume;
7999 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05308000 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05308001 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07008002 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05308003 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07008004 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05308005 } else {
8006 out->usecase = get_offload_usecase(adev, false /* is_compress */);
8007 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07008008 }
vivek mehta446c3962015-09-14 10:57:35 -07008009
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308010 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8011 ALOGD("%s: Setting latency mode to true", __func__);
Meng Wang4c32fb42020-01-16 17:57:11 +08008012#ifdef AUDIO_GKI_ENABLED
8013 /* out->compr_config.codec->reserved[1] is for flags */
8014 out->compr_config.codec->reserved[1] |= audio_extn_utils_get_perf_mode_flag();
8015#else
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308016 out->compr_config.codec->flags |= audio_extn_utils_get_perf_mode_flag();
Meng Wang4c32fb42020-01-16 17:57:11 +08008017#endif
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308018 }
8019
vivek mehta446c3962015-09-14 10:57:35 -07008020 if (out->usecase == USECASE_INVALID) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008021 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Mingming Yin3a941d42016-02-17 18:08:05 -08008022 config->format == 0 && config->sample_rate == 0 &&
8023 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07008024 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08008025 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
8026 } else {
8027 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
8028 ret = -EEXIST;
8029 goto error_open;
8030 }
vivek mehta446c3962015-09-14 10:57:35 -07008031 }
8032
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008033 if (config->offload_info.channel_mask)
8034 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008035 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008036 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008037 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008038 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05308039 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008040 ret = -EINVAL;
8041 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008042 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008043
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008044 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008045 out->sample_rate = config->offload_info.sample_rate;
8046
Mingming Yin3ee55c62014-08-04 14:23:35 -07008047 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008048
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308049 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05308050 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308051 audio_extn_dolby_send_ddp_endp_params(adev);
8052 audio_extn_dolby_set_dmid(adev);
8053 }
vivek mehta0ea887a2015-08-26 14:01:20 -07008054
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008055 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08008056 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008057 out->compr_config.codec->bit_rate =
8058 config->offload_info.bit_rate;
8059 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05308060 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008061 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05308062 /* Update bit width only for non passthrough usecases.
8063 * For passthrough usecases, the output will always be opened @16 bit
8064 */
8065 if (!audio_extn_passthru_is_passthrough_stream(out))
8066 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308067
8068 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
Meng Wang4c32fb42020-01-16 17:57:11 +08008069#ifdef AUDIO_GKI_ENABLED
8070 /* out->compr_config.codec->reserved[1] is for flags */
8071 out->compr_config.codec->reserved[1] |= COMPRESSED_TIMESTAMP_FLAG;
8072 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->reserved[1]);
8073#else
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308074 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
8075 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
Meng Wang4c32fb42020-01-16 17:57:11 +08008076#endif
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308077
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008078 /*TODO: Do we need to change it for passthrough */
8079 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008080
Manish Dewangana6fc5442015-08-24 20:30:31 +05308081 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
8082 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308083 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05308084 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308085 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
8086 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308087
8088 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
8089 AUDIO_FORMAT_PCM) {
8090
8091 /*Based on platform support, configure appropriate alsa format for corresponding
8092 *hal input format.
8093 */
8094 out->compr_config.codec->format = hal_format_to_alsa(
8095 config->offload_info.format);
8096
Ashish Jain83a6cc22016-06-28 14:34:17 +05308097 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05308098 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308099 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308100
Dhananjay Kumarac341582017-02-23 23:42:25 +05308101 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05308102 *hal input format and alsa format might differ based on platform support.
8103 */
8104 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05308105 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308106
8107 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
8108
Deeraj Soman93155a62019-09-30 19:00:37 +05308109 if (property_get_bool("vendor.audio.offload.buffer.duration.enabled", false)) {
8110 if ((config->offload_info.duration_us >= MIN_OFFLOAD_BUFFER_DURATION_MS * 1000) &&
8111 (config->offload_info.duration_us <= MAX_OFFLOAD_BUFFER_DURATION_MS * 1000))
8112 out->info.duration_us = (int64_t)config->offload_info.duration_us;
8113 }
Deeraj Soman65358ab2019-02-07 15:40:49 +05308114
Ashish Jainf1eaa582016-05-23 20:54:24 +05308115 /* Check if alsa session is configured with the same format as HAL input format,
8116 * if not then derive correct fragment size needed to accomodate the
8117 * conversion of HAL input format to alsa format.
8118 */
8119 audio_extn_utils_update_direct_pcm_fragment_size(out);
8120
8121 /*if hal input and output fragment size is different this indicates HAL input format is
8122 *not same as the alsa format
8123 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308124 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05308125 /*Allocate a buffer to convert input data to the alsa configured format.
8126 *size of convert buffer is equal to the size required to hold one fragment size
8127 *worth of pcm data, this is because flinger does not write more than fragment_size
8128 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308129 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
8130 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05308131 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
8132 ret = -ENOMEM;
8133 goto error_open;
8134 }
8135 }
8136 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
8137 out->compr_config.fragment_size =
8138 audio_extn_passthru_get_buffer_size(&config->offload_info);
8139 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8140 } else {
8141 out->compr_config.fragment_size =
8142 platform_get_compress_offload_buffer_size(&config->offload_info);
8143 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8144 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008145
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308146 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8147 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
8148 }
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008149 if (config->offload_info.format == AUDIO_FORMAT_FLAC) {
8150#ifdef AUDIO_GKI_ENABLED
8151 generic_dec =
8152 &(out->compr_config.codec->options.generic.reserved[1]);
8153 ((struct snd_generic_dec_flac *)generic_dec)->sample_size =
8154 AUDIO_OUTPUT_BIT_WIDTH;
8155#else
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05308156 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008157#endif
8158 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008159
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05308160 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
8161 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
8162 }
8163
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008164 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
8165 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008166
Manish Dewangan69426c82017-01-30 17:35:36 +05308167 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
8168 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
8169 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
8170 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8171 out->render_mode = RENDER_MODE_AUDIO_MASTER;
8172 } else {
8173 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
8174 }
Alexy Josephaa54c872014-12-03 02:46:47 -08008175
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05308176 memset(&out->channel_map_param, 0,
8177 sizeof(struct audio_out_channel_map_param));
8178
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008179 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05308180 out->send_next_track_params = false;
8181 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008182 out->offload_state = OFFLOAD_STATE_IDLE;
8183 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08008184 out->writeAt.tv_sec = 0;
8185 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008186
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008187 audio_extn_dts_create_state_notifier_node(out->usecase);
8188
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008189 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
8190 __func__, config->offload_info.version,
8191 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05308192
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308193 /* Check if DSD audio format is supported in codec
8194 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308195 */
8196
8197 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308198 (!platform_check_codec_dsd_support(adev->platform) ||
8199 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308200 ret = -EINVAL;
8201 goto error_open;
8202 }
8203
Ashish Jain5106d362016-05-11 19:23:33 +05308204 /* Disable gapless if any of the following is true
8205 * passthrough playback
8206 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05308207 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05308208 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308209 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308210 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07008211 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308212 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308213 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05308214 check_and_set_gapless_mode(adev, false);
8215 } else
8216 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07008217
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308218 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07008219 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
8220 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308221 if (config->format == AUDIO_FORMAT_DSD) {
8222 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
Meng Wang4c32fb42020-01-16 17:57:11 +08008223#ifdef AUDIO_GKI_ENABLED
8224 /* out->compr_config.codec->reserved[0] is for compr_passthr */
8225 out->compr_config.codec->reserved[0] = PASSTHROUGH_DSD;
8226#else
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308227 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
Meng Wang4c32fb42020-01-16 17:57:11 +08008228#endif
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308229 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07008230
8231 create_offload_callback_thread(out);
8232
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008233 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008234 switch (config->sample_rate) {
8235 case 0:
8236 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8237 break;
8238 case 8000:
8239 case 16000:
8240 case 48000:
8241 out->sample_rate = config->sample_rate;
8242 break;
8243 default:
8244 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
8245 config->sample_rate);
8246 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8247 ret = -EINVAL;
8248 goto error_open;
8249 }
8250 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8251 switch (config->channel_mask) {
8252 case AUDIO_CHANNEL_NONE:
8253 case AUDIO_CHANNEL_OUT_STEREO:
8254 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8255 break;
8256 default:
8257 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
8258 config->channel_mask);
8259 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8260 ret = -EINVAL;
8261 goto error_open;
8262 }
8263 switch (config->format) {
8264 case AUDIO_FORMAT_DEFAULT:
8265 case AUDIO_FORMAT_PCM_16_BIT:
8266 out->format = AUDIO_FORMAT_PCM_16_BIT;
8267 break;
8268 default:
8269 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
8270 config->format);
8271 config->format = AUDIO_FORMAT_PCM_16_BIT;
8272 ret = -EINVAL;
8273 goto error_open;
8274 }
8275
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05308276 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008277 if (ret != 0) {
8278 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008279 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008280 goto error_open;
8281 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008282 } else if (is_single_device_type_equal(&out->device_list,
8283 AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08008284 switch (config->sample_rate) {
8285 case 0:
8286 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
8287 break;
8288 case 8000:
8289 case 16000:
8290 case 48000:
8291 out->sample_rate = config->sample_rate;
8292 break;
8293 default:
8294 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
8295 config->sample_rate);
8296 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8297 ret = -EINVAL;
8298 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008299 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008300 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8301 switch (config->channel_mask) {
8302 case AUDIO_CHANNEL_NONE:
8303 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8304 break;
8305 case AUDIO_CHANNEL_OUT_STEREO:
8306 out->channel_mask = config->channel_mask;
8307 break;
8308 default:
8309 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
8310 config->channel_mask);
8311 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8312 ret = -EINVAL;
8313 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008314 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008315 switch (config->format) {
8316 case AUDIO_FORMAT_DEFAULT:
8317 out->format = AUDIO_FORMAT_PCM_16_BIT;
8318 break;
8319 case AUDIO_FORMAT_PCM_16_BIT:
8320 out->format = config->format;
8321 break;
8322 default:
8323 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
8324 config->format);
8325 config->format = AUDIO_FORMAT_PCM_16_BIT;
8326 ret = -EINVAL;
8327 break;
8328 }
8329 if (ret != 0)
8330 goto error_open;
8331
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008332 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
8333 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08008334 out->config.rate = out->sample_rate;
8335 out->config.channels =
8336 audio_channel_count_from_out_mask(out->channel_mask);
8337 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008338 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008339 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05308340 unsigned int channels = 0;
8341 /*Update config params to default if not set by the caller*/
8342 if (config->sample_rate == 0)
8343 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8344 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8345 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8346 if (config->format == AUDIO_FORMAT_DEFAULT)
8347 config->format = AUDIO_FORMAT_PCM_16_BIT;
8348
8349 channels = audio_channel_count_from_out_mask(out->channel_mask);
8350
Varun Balaraje49253e2017-07-06 19:48:56 +05308351 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
8352 out->usecase = get_interactive_usecase(adev);
8353 out->config = pcm_config_low_latency;
8354 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05308355 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008356 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
8357 out->flags);
8358 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07008359 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8360 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8361 out->config = pcm_config_mmap_playback;
8362 out->stream.start = out_start;
8363 out->stream.stop = out_stop;
8364 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8365 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308366 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8367 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008368 out->hal_output_suspend_supported =
8369 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
8370 out->dynamic_pm_qos_config_supported =
8371 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
8372 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08008373 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
8374 } else {
8375 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
8376 //the mixer path will be a string similar to "low-latency-playback resume"
8377 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
8378 strlcat(out->pm_qos_mixer_path,
8379 " resume", MAX_MIXER_PATH_LEN);
8380 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
8381 out->pm_qos_mixer_path);
8382 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308383 out->config = pcm_config_low_latency;
8384 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
8385 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
8386 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05308387 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
8388 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
8389 if (out->config.period_size <= 0) {
8390 ALOGE("Invalid configuration period size is not valid");
8391 ret = -EINVAL;
8392 goto error_open;
8393 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008394 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
8395 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
8396 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008397 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
8398 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
8399 out->config = pcm_config_haptics_audio;
8400 if (force_haptic_path)
8401 adev->haptics_config = pcm_config_haptics_audio;
8402 else
8403 adev->haptics_config = pcm_config_haptics;
8404
Meng Wangd08ce322020-04-02 08:59:20 +08008405 channels =
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008406 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
8407
8408 if (force_haptic_path) {
8409 out->config.channels = 1;
8410 adev->haptics_config.channels = 1;
8411 } else
8412 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 -08008413 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008414 ret = audio_extn_auto_hal_open_output_stream(out);
8415 if (ret) {
8416 ALOGE("%s: Failed to open output stream for bus device", __func__);
8417 ret = -EINVAL;
8418 goto error_open;
8419 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308420 } else {
8421 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008422 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8423 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308424 }
8425 out->hal_ip_format = format = out->format;
8426 out->config.format = hal_format_to_pcm(out->hal_ip_format);
8427 out->hal_op_format = pcm_format_to_hal(out->config.format);
8428 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
8429 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008430 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05308431 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308432 if (out->hal_ip_format != out->hal_op_format) {
8433 uint32_t buffer_size = out->config.period_size *
8434 format_to_bitwidth_table[out->hal_op_format] *
8435 out->config.channels;
8436 out->convert_buffer = calloc(1, buffer_size);
8437 if (out->convert_buffer == NULL){
8438 ALOGE("Allocation failed for convert buffer for size %d",
8439 out->compr_config.fragment_size);
8440 ret = -ENOMEM;
8441 goto error_open;
8442 }
8443 ALOGD("Convert buffer allocated of size %d", buffer_size);
8444 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008445 }
8446
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008447 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
8448 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308449
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008450 /* TODO remove this hardcoding and check why width is zero*/
8451 if (out->bit_width == 0)
8452 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308453 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008454 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008455 &out->device_list, out->flags,
8456 out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05308457 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05308458 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08008459 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08008460 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
8461 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008462 if(adev->primary_output == NULL)
8463 adev->primary_output = out;
8464 else {
8465 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008466 ret = -EEXIST;
8467 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008468 }
8469 }
8470
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008471 /* Check if this usecase is already existing */
8472 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07008473 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
8474 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008475 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008476 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008477 ret = -EEXIST;
8478 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008479 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008480
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008481 pthread_mutex_unlock(&adev->lock);
8482
8483 out->stream.common.get_sample_rate = out_get_sample_rate;
8484 out->stream.common.set_sample_rate = out_set_sample_rate;
8485 out->stream.common.get_buffer_size = out_get_buffer_size;
8486 out->stream.common.get_channels = out_get_channels;
8487 out->stream.common.get_format = out_get_format;
8488 out->stream.common.set_format = out_set_format;
8489 out->stream.common.standby = out_standby;
8490 out->stream.common.dump = out_dump;
8491 out->stream.common.set_parameters = out_set_parameters;
8492 out->stream.common.get_parameters = out_get_parameters;
8493 out->stream.common.add_audio_effect = out_add_audio_effect;
8494 out->stream.common.remove_audio_effect = out_remove_audio_effect;
8495 out->stream.get_latency = out_get_latency;
8496 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08008497#ifdef NO_AUDIO_OUT
8498 out->stream.write = out_write_for_no_output;
8499#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008500 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08008501#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008502 out->stream.get_render_position = out_get_render_position;
8503 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008504 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008505
Haynes Mathew George16081042017-05-31 17:16:49 -07008506 if (out->realtime)
8507 out->af_period_multiplier = af_period_multiplier;
8508 else
8509 out->af_period_multiplier = 1;
8510
Andy Hunga1f48fa2019-07-01 18:14:53 -07008511 out->kernel_buffer_size = out->config.period_size * out->config.period_count;
8512
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008513 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07008514 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008515 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008516
8517 config->format = out->stream.common.get_format(&out->stream.common);
8518 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
8519 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308520 register_format(out->format, out->supported_formats);
8521 register_channel_mask(out->channel_mask, out->supported_channel_masks);
8522 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008523
Aalique Grahame22e49102018-12-18 14:23:57 -08008524 out->error_log = error_log_create(
8525 ERROR_LOG_ENTRIES,
8526 1000000000 /* aggregate consecutive identical errors within one second in ns */);
8527
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308528 /*
8529 By locking output stream before registering, we allow the callback
8530 to update stream's state only after stream's initial state is set to
8531 adev state.
8532 */
8533 lock_output_stream(out);
8534 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
8535 pthread_mutex_lock(&adev->lock);
8536 out->card_status = adev->card_status;
8537 pthread_mutex_unlock(&adev->lock);
8538 pthread_mutex_unlock(&out->lock);
8539
Aalique Grahame22e49102018-12-18 14:23:57 -08008540 stream_app_type_cfg_init(&out->app_type_cfg);
8541
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008542 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308543 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07008544 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008545
8546 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
8547 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
8548 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008549 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05308550 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008551 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07008552 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05308553 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
8554 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008555 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
8556 out->usecase, PCM_PLAYBACK);
8557 hdlr_stream_cfg.flags = out->flags;
8558 hdlr_stream_cfg.type = PCM_PLAYBACK;
8559 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
8560 &hdlr_stream_cfg);
8561 if (ret) {
8562 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
8563 out->adsp_hdlr_stream_handle = NULL;
8564 }
8565 }
Gangadhar Sb0210342019-02-22 17:39:41 +05308566 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
8567 is_direct_passthough, false);
8568 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
8569 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07008570 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07008571 if (ret < 0) {
8572 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
8573 out->ip_hdlr_handle = NULL;
8574 }
8575 }
Derek Chenf939fb72018-11-13 13:34:41 -08008576
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008577 ret = io_streams_map_insert(adev, &out->stream.common,
8578 out->handle, AUDIO_PATCH_HANDLE_NONE);
8579 if (ret != 0)
8580 goto error_open;
8581
Derek Chenf939fb72018-11-13 13:34:41 -08008582 streams_output_ctxt_t *out_ctxt = (streams_output_ctxt_t *)
8583 calloc(1, sizeof(streams_output_ctxt_t));
8584 if (out_ctxt == NULL) {
8585 ALOGE("%s fail to allocate output ctxt", __func__);
8586 ret = -ENOMEM;
8587 goto error_open;
8588 }
8589 out_ctxt->output = out;
8590
8591 pthread_mutex_lock(&adev->lock);
8592 list_add_tail(&adev->active_outputs_list, &out_ctxt->list);
8593 pthread_mutex_unlock(&adev->lock);
8594
Eric Laurent994a6932013-07-17 11:51:42 -07008595 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008596 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008597
8598error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05308599 if (out->convert_buffer)
8600 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008601 free(out);
8602 *stream_out = NULL;
8603 ALOGD("%s: exit: ret %d", __func__, ret);
8604 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008605}
8606
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308607void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008608 struct audio_stream_out *stream)
8609{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008610 struct stream_out *out = (struct stream_out *)stream;
8611 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008612 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008613
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008614 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308615
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008616 io_streams_map_remove(adev, out->handle);
8617
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308618 // must deregister from sndmonitor first to prevent races
8619 // between the callback and close_stream
8620 audio_extn_snd_mon_unregister_listener(out);
8621
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008622 /* close adsp hdrl session before standby */
8623 if (out->adsp_hdlr_stream_handle) {
8624 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
8625 if (ret)
8626 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
8627 out->adsp_hdlr_stream_handle = NULL;
8628 }
8629
Manish Dewangan21a850a2017-08-14 12:03:55 +05308630 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07008631 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
8632 out->ip_hdlr_handle = NULL;
8633 }
8634
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008635 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308636 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008637 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308638 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308639 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008640 if(ret != 0)
8641 ALOGE("%s: Compress voip output cannot be closed, error:%d",
8642 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008643 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008644 out_standby(&stream->common);
8645
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008646 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008647 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008648 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008649 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008650 if (out->compr_config.codec != NULL)
8651 free(out->compr_config.codec);
8652 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008653
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05308654 out->a2dp_compress_mute = false;
8655
Varun Balaraje49253e2017-07-06 19:48:56 +05308656 if (is_interactive_usecase(out->usecase))
8657 free_interactive_usecase(adev, out->usecase);
8658
Ashish Jain83a6cc22016-06-28 14:34:17 +05308659 if (out->convert_buffer != NULL) {
8660 free(out->convert_buffer);
8661 out->convert_buffer = NULL;
8662 }
8663
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008664 if (adev->voice_tx_output == out)
8665 adev->voice_tx_output = NULL;
8666
Aalique Grahame22e49102018-12-18 14:23:57 -08008667 error_log_destroy(out->error_log);
8668 out->error_log = NULL;
8669
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05308670 if (adev->primary_output == out)
8671 adev->primary_output = NULL;
8672
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008673 pthread_cond_destroy(&out->cond);
8674 pthread_mutex_destroy(&out->lock);
Derek Chenf939fb72018-11-13 13:34:41 -08008675
8676 pthread_mutex_lock(&adev->lock);
8677 streams_output_ctxt_t *out_ctxt = out_get_stream(adev, out->handle);
8678 if (out_ctxt != NULL) {
8679 list_remove(&out_ctxt->list);
8680 free(out_ctxt);
8681 } else {
8682 ALOGW("%s, output stream already closed", __func__);
8683 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008684 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08008685 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07008686 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008687}
8688
8689static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
8690{
8691 struct audio_device *adev = (struct audio_device *)dev;
8692 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008693 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008694 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008695 int ret;
8696 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08008697 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008698 struct listnode *node;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008699 int controller = -1, stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008700
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008701 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008702 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008703
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308704 if (!parms)
8705 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05308706
Derek Chen6f293672019-04-01 01:40:24 -07008707 /* notify adev and input/output streams on the snd card status */
8708 adev_snd_mon_cb((void *)adev, parms);
8709
8710 list_for_each(node, &adev->active_outputs_list) {
8711 streams_output_ctxt_t *out_ctxt = node_to_item(node,
8712 streams_output_ctxt_t,
8713 list);
8714 out_snd_mon_cb((void *)out_ctxt->output, parms);
8715 }
8716
8717 list_for_each(node, &adev->active_inputs_list) {
8718 streams_input_ctxt_t *in_ctxt = node_to_item(node,
8719 streams_input_ctxt_t,
8720 list);
8721 in_snd_mon_cb((void *)in_ctxt->input, parms);
8722 }
8723
Zhou Songd6d71752019-05-21 18:08:51 +08008724 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308725 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
8726 if (ret >= 0) {
8727 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08008728 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308729 adev->bt_sco_on = true;
Zhou Songd6d71752019-05-21 18:08:51 +08008730 } else {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308731 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008732 audio_extn_sco_reset_configuration();
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008733 }
8734 }
8735
8736 ret = str_parms_get_str(parms, "A2dpSuspended", value, sizeof(value));
8737 if (ret>=0) {
8738 if (!strncmp(value, "false", 5) &&
8739 audio_extn_a2dp_source_is_suspended()) {
8740 struct audio_usecase *usecase;
8741 struct listnode *node;
Zhou Songd6d71752019-05-21 18:08:51 +08008742 list_for_each(node, &adev->usecase_list) {
8743 usecase = node_to_item(node, struct audio_usecase, list);
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008744 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008745 is_sco_in_device_type(&usecase->stream.in->device_list)) {
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008746 ALOGD("a2dp resumed, switch bt sco mic to handset mic");
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008747 reassign_device_list(&usecase->stream.in->device_list,
8748 AUDIO_DEVICE_IN_BUILTIN_MIC, "");
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008749 select_devices(adev, usecase->id);
8750 }
Zhou Songd6d71752019-05-21 18:08:51 +08008751 }
8752 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308753 }
8754
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008755 status = voice_set_parameters(adev, parms);
8756 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008757 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008758
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008759 status = platform_set_parameters(adev->platform, parms);
8760 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008761 goto done;
8762
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008763 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
8764 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07008765 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008766 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8767 adev->bluetooth_nrec = true;
8768 else
8769 adev->bluetooth_nrec = false;
8770 }
8771
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008772 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
8773 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008774 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8775 adev->screen_off = false;
8776 else
8777 adev->screen_off = true;
Quinn Male70f20f32019-06-26 16:50:26 -07008778 audio_extn_sound_trigger_update_screen_status(adev->screen_off);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008779 }
8780
Eric Laurent4b084132018-10-19 17:33:43 -07008781 ret = str_parms_get_int(parms, "rotation", &val);
8782 if (ret >= 0) {
8783 bool reverse_speakers = false;
8784 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8785 switch (val) {
8786 // FIXME: note that the code below assumes that the speakers are in the correct placement
8787 // relative to the user when the device is rotated 90deg from its default rotation. This
8788 // assumption is device-specific, not platform-specific like this code.
8789 case 270:
8790 reverse_speakers = true;
8791 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
8792 break;
8793 case 0:
8794 case 180:
8795 camera_rotation = CAMERA_ROTATION_PORTRAIT;
8796 break;
8797 case 90:
8798 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8799 break;
8800 default:
8801 ALOGE("%s: unexpected rotation of %d", __func__, val);
8802 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008803 }
Eric Laurent4b084132018-10-19 17:33:43 -07008804 if (status == 0) {
8805 // check and set swap
8806 // - check if orientation changed and speaker active
8807 // - set rotation and cache the rotation value
8808 adev->camera_orientation =
8809 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
8810 if (!audio_extn_is_maxx_audio_enabled())
8811 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
8812 }
8813 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008814
Mingming Yin514a8bc2014-07-29 15:22:21 -07008815 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
8816 if (ret >= 0) {
8817 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8818 adev->bt_wb_speech_enabled = true;
8819 else
8820 adev->bt_wb_speech_enabled = false;
8821 }
8822
Zhou Song12c29502019-03-16 10:37:18 +08008823 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
8824 if (ret >= 0) {
8825 val = atoi(value);
8826 adev->swb_speech_mode = val;
8827 }
8828
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008829 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
8830 if (ret >= 0) {
8831 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308832 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08008833 if (audio_is_output_device(val) &&
8834 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008835 ALOGV("cache new ext disp type and edid");
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008836 platform_get_controller_stream_from_params(parms, &controller, &stream);
8837 platform_set_ext_display_device_v2(adev->platform, controller, stream);
8838 ret = platform_get_ext_disp_type_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008839 if (ret < 0) {
8840 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05308841 } else {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008842 platform_cache_edid_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008843 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308844 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07008845 /*
8846 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
8847 * Per AudioPolicyManager, USB device is higher priority than WFD.
8848 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
8849 * If WFD use case occupies AFE proxy, it may result unintended behavior while
8850 * starting voice call on USB
8851 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008852 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308853 if (ret >= 0)
8854 audio_extn_usb_add_device(device, atoi(value));
8855
Zhou Song6f862822017-11-06 17:27:57 +08008856 if (!audio_extn_usb_is_tunnel_supported()) {
8857 ALOGV("detected USB connect .. disable proxy");
8858 adev->allow_afe_proxy_usage = false;
8859 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008860 }
8861 }
8862
8863 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
8864 if (ret >= 0) {
8865 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308866 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07008867 /*
8868 * The HDMI / Displayport disconnect handling has been moved to
8869 * audio extension to ensure that its parameters are not
8870 * invalidated prior to updating sysfs of the disconnect event
8871 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
8872 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308873 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008874 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308875 if (ret >= 0)
8876 audio_extn_usb_remove_device(device, atoi(value));
8877
Zhou Song6f862822017-11-06 17:27:57 +08008878 if (!audio_extn_usb_is_tunnel_supported()) {
8879 ALOGV("detected USB disconnect .. enable proxy");
8880 adev->allow_afe_proxy_usage = true;
8881 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008882 }
8883 }
8884
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008885 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08008886
8887 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08008888 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308889 struct audio_usecase *usecase;
8890 struct listnode *node;
8891 list_for_each(node, &adev->usecase_list) {
8892 usecase = node_to_item(node, struct audio_usecase, list);
Weiyin Jiangff56ff32020-05-08 14:32:21 +08008893 if ((usecase->stream.out == NULL) || (usecase->type != PCM_PLAYBACK))
8894 continue;
8895
8896 if (is_a2dp_out_device_type(&usecase->device_list)) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308897 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08008898 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308899 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08008900 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308901 audio_extn_a2dp_set_handoff_mode(true);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308902 ALOGD("Switching to speaker and muting the stream before select_devices");
8903 check_a2dp_restore_l(adev, usecase->stream.out, false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308904 //force device switch to re configure encoder
8905 select_devices(adev, usecase->id);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308906 ALOGD("Unmuting the stream after select_devices");
8907 usecase->stream.out->a2dp_compress_mute = false;
8908 out_set_compr_volume(&usecase->stream.out->stream, usecase->stream.out->volume_l, usecase->stream.out->volume_r);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308909 audio_extn_a2dp_set_handoff_mode(false);
8910 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308911 break;
Manisha Agarwal6a6fb9a2019-12-04 11:38:41 +05308912 } else if ((usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
8913 usecase->stream.out->a2dp_compress_mute) {
8914 pthread_mutex_unlock(&adev->lock);
8915 lock_output_stream(usecase->stream.out);
8916 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008917 reassign_device_list(&usecase->stream.out->device_list,
8918 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, "");
Manisha Agarwal6a6fb9a2019-12-04 11:38:41 +05308919 check_a2dp_restore_l(adev, usecase->stream.out, true);
8920 pthread_mutex_unlock(&usecase->stream.out->lock);
8921 break;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308922 }
8923 }
8924 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008925
8926 //handle vr audio setparam
8927 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8928 value, sizeof(value));
8929 if (ret >= 0) {
8930 ALOGI("Setting vr mode to be %s", value);
8931 if (!strncmp(value, "true", 4)) {
8932 adev->vr_audio_mode_enabled = true;
8933 ALOGI("Setting vr mode to true");
8934 } else if (!strncmp(value, "false", 5)) {
8935 adev->vr_audio_mode_enabled = false;
8936 ALOGI("Setting vr mode to false");
8937 } else {
8938 ALOGI("wrong vr mode set");
8939 }
8940 }
8941
Eric Laurent4b084132018-10-19 17:33:43 -07008942 //FIXME: to be replaced by proper video capture properties API
8943 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
8944 if (ret >= 0) {
8945 int camera_facing = CAMERA_FACING_BACK;
8946 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
8947 camera_facing = CAMERA_FACING_FRONT;
8948 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
8949 camera_facing = CAMERA_FACING_BACK;
8950 else {
8951 ALOGW("%s: invalid camera facing value: %s", __func__, value);
8952 goto done;
8953 }
8954 adev->camera_orientation =
8955 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
8956 struct audio_usecase *usecase;
8957 struct listnode *node;
8958 list_for_each(node, &adev->usecase_list) {
8959 usecase = node_to_item(node, struct audio_usecase, list);
8960 struct stream_in *in = usecase->stream.in;
8961 if (usecase->type == PCM_CAPTURE && in != NULL &&
8962 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
8963 select_devices(adev, in->usecase);
8964 }
8965 }
8966 }
8967
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308968 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008969done:
8970 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008971 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308972error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008973 ALOGV("%s: exit with code(%d)", __func__, status);
8974 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008975}
8976
8977static char* adev_get_parameters(const struct audio_hw_device *dev,
8978 const char *keys)
8979{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308980 ALOGD("%s:%s", __func__, keys);
8981
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008982 struct audio_device *adev = (struct audio_device *)dev;
8983 struct str_parms *reply = str_parms_create();
8984 struct str_parms *query = str_parms_create_str(keys);
8985 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05308986 char value[256] = {0};
8987 int ret = 0;
8988
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008989 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08008990 if (reply) {
8991 str_parms_destroy(reply);
8992 }
8993 if (query) {
8994 str_parms_destroy(query);
8995 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008996 ALOGE("adev_get_parameters: failed to create query or reply");
8997 return NULL;
8998 }
8999
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009000 //handle vr audio getparam
9001
9002 ret = str_parms_get_str(query,
9003 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9004 value, sizeof(value));
9005
9006 if (ret >= 0) {
9007 bool vr_audio_enabled = false;
9008 pthread_mutex_lock(&adev->lock);
9009 vr_audio_enabled = adev->vr_audio_mode_enabled;
9010 pthread_mutex_unlock(&adev->lock);
9011
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07009012 ALOGV("getting vr mode to %d", vr_audio_enabled);
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009013
9014 if (vr_audio_enabled) {
9015 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9016 "true");
9017 goto exit;
9018 } else {
9019 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9020 "false");
9021 goto exit;
9022 }
9023 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009024
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009025 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009026 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08009027 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08009028 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009029 platform_get_parameters(adev->platform, query, reply);
justinwengd5395152019-11-04 12:23:09 +08009030 audio_extn_ma_get_parameters(adev, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05309031 pthread_mutex_unlock(&adev->lock);
9032
Naresh Tannirud7205b62014-06-20 02:54:48 +05309033exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009034 str = str_parms_to_str(reply);
9035 str_parms_destroy(query);
9036 str_parms_destroy(reply);
9037
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07009038 ALOGV("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009039 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009040}
9041
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009042static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009043{
9044 return 0;
9045}
9046
9047static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
9048{
Haynes Mathew George5191a852013-09-11 14:19:36 -07009049 int ret;
9050 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08009051
9052 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
9053
Haynes Mathew George5191a852013-09-11 14:19:36 -07009054 pthread_mutex_lock(&adev->lock);
9055 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07009056 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07009057 pthread_mutex_unlock(&adev->lock);
9058 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009059}
9060
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009061static int adev_set_master_volume(struct audio_hw_device *dev __unused,
9062 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009063{
9064 return -ENOSYS;
9065}
9066
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009067static int adev_get_master_volume(struct audio_hw_device *dev __unused,
9068 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009069{
9070 return -ENOSYS;
9071}
9072
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009073static int adev_set_master_mute(struct audio_hw_device *dev __unused,
9074 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009075{
9076 return -ENOSYS;
9077}
9078
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009079static int adev_get_master_mute(struct audio_hw_device *dev __unused,
9080 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009081{
9082 return -ENOSYS;
9083}
9084
9085static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
9086{
9087 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07009088 struct listnode *node;
9089 struct audio_usecase *usecase = NULL;
9090 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08009091
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009092 pthread_mutex_lock(&adev->lock);
9093 if (adev->mode != mode) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309094 ALOGD("%s: mode %d , prev_mode %d \n", __func__, mode , adev->mode);
9095 adev->prev_mode = adev->mode; /* prev_mode is kept to handle voip concurrency*/
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009096 adev->mode = mode;
Weiyin Jiang96b96f72020-09-22 16:48:19 +08009097 if (mode == AUDIO_MODE_CALL_SCREEN) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309098 adev->current_call_output = adev->primary_output;
9099 voice_start_call(adev);
9100 } else if (voice_is_in_call_or_call_screen(adev) &&
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08009101 (mode == AUDIO_MODE_NORMAL ||
9102 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07009103 list_for_each(node, &adev->usecase_list) {
9104 usecase = node_to_item(node, struct audio_usecase, list);
9105 if (usecase->type == VOICE_CALL)
9106 break;
9107 }
9108 if (usecase &&
9109 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
9110 ret = audio_extn_usb_check_and_set_svc_int(usecase,
9111 true);
9112 if (ret != 0) {
9113 /* default service interval was successfully updated,
9114 reopen USB backend with new service interval */
9115 check_usecases_codec_backend(adev,
9116 usecase,
9117 usecase->out_snd_device);
9118 }
9119 }
9120
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009121 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07009122 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009123 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08009124 // restore device for other active usecases after stop call
9125 list_for_each(node, &adev->usecase_list) {
9126 usecase = node_to_item(node, struct audio_usecase, list);
9127 select_devices(adev, usecase->id);
9128 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009129 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009130 }
9131 pthread_mutex_unlock(&adev->lock);
9132 return 0;
9133}
9134
9135static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
9136{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009137 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08009138 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009139
9140 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08009141 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009142 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009143
Derek Chend2530072014-11-24 12:39:14 -08009144 if (adev->ext_hw_plugin)
9145 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009146
9147 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009148 pthread_mutex_unlock(&adev->lock);
9149
9150 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009151}
9152
9153static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
9154{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009155 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009156 return 0;
9157}
9158
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009159static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009160 const struct audio_config *config)
9161{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009162 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009163
Aalique Grahame22e49102018-12-18 14:23:57 -08009164 /* Don't know if USB HIFI in this context so use true to be conservative */
9165 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9166 true /*is_usb_hifi */) != 0)
9167 return 0;
9168
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009169 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
9170 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009171}
9172
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009173static bool adev_input_allow_hifi_record(struct audio_device *adev,
9174 audio_devices_t devices,
9175 audio_input_flags_t flags,
9176 audio_source_t source) {
9177 const bool allowed = true;
9178
9179 if (!audio_is_usb_in_device(devices))
9180 return !allowed;
9181
9182 switch (flags) {
9183 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009184 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07009185 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
9186 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009187 default:
9188 return !allowed;
9189 }
9190
9191 switch (source) {
9192 case AUDIO_SOURCE_DEFAULT:
9193 case AUDIO_SOURCE_MIC:
9194 case AUDIO_SOURCE_UNPROCESSED:
9195 break;
9196 default:
9197 return !allowed;
9198 }
9199
9200 switch (adev->mode) {
9201 case 0:
9202 break;
9203 default:
9204 return !allowed;
9205 }
9206
9207 return allowed;
9208}
9209
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009210static int adev_update_voice_comm_input_stream(struct stream_in *in,
9211 struct audio_config *config)
9212{
9213 bool valid_rate = (config->sample_rate == 8000 ||
9214 config->sample_rate == 16000 ||
9215 config->sample_rate == 32000 ||
9216 config->sample_rate == 48000);
9217 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
9218
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009219 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08009220 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009221 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9222 in->config = default_pcm_config_voip_copp;
9223 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
9224 DEFAULT_VOIP_BUF_DURATION_MS,
9225 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009226 } else {
9227 ALOGW("%s No valid input in voip, use defaults"
9228 "sample rate %u, channel mask 0x%X",
9229 __func__, config->sample_rate, in->channel_mask);
9230 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009231 in->config.rate = config->sample_rate;
9232 in->sample_rate = config->sample_rate;
9233 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009234 //XXX needed for voice_extn_compress_voip_open_input_stream
9235 in->config.rate = config->sample_rate;
9236 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
Shalini Manjunathaa763cc42019-08-23 15:13:46 +05309237 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009238 voice_extn_compress_voip_is_active(in->dev)) &&
9239 (voice_extn_compress_voip_is_format_supported(in->format)) &&
9240 valid_rate && valid_ch) {
9241 voice_extn_compress_voip_open_input_stream(in);
9242 // update rate entries to match config from AF
9243 in->config.rate = config->sample_rate;
9244 in->sample_rate = config->sample_rate;
9245 } else {
9246 ALOGW("%s compress voip not active, use defaults", __func__);
9247 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009248 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009249 return 0;
9250}
9251
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009252static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07009253 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009254 audio_devices_t devices,
9255 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009256 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309257 audio_input_flags_t flags,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009258 const char *address,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009259 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009260{
9261 struct audio_device *adev = (struct audio_device *)dev;
9262 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009263 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009264 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009265 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05309266 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009267 bool is_usb_dev = audio_is_usb_in_device(devices);
9268 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
9269 devices,
9270 flags,
9271 source);
Andy Hung94320602018-10-29 18:31:12 -07009272 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
9273 " sample_rate %u, channel_mask %#x, format %#x",
9274 __func__, flags, is_usb_dev, may_use_hifi_record,
9275 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309276
kunleizdff872d2018-08-20 14:40:33 +08009277 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08009278 is_usb_dev = false;
9279 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
9280 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
9281 __func__, devices);
9282 }
9283
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009284 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009285
9286 if (!(is_usb_dev && may_use_hifi_record)) {
9287 if (config->sample_rate == 0)
9288 config->sample_rate = 48000;
9289 if (config->channel_mask == AUDIO_CHANNEL_NONE)
9290 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9291 if (config->format == AUDIO_FORMAT_DEFAULT)
9292 config->format = AUDIO_FORMAT_PCM_16_BIT;
9293
9294 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
9295
Aalique Grahame22e49102018-12-18 14:23:57 -08009296 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9297 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009298 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05309299 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009300
Rahul Sharma99770982019-03-06 17:05:26 +05309301 pthread_mutex_lock(&adev->lock);
9302 if (in_get_stream(adev, handle) != NULL) {
9303 ALOGW("%s, input stream already opened", __func__);
9304 ret = -EEXIST;
9305 }
9306 pthread_mutex_unlock(&adev->lock);
9307 if (ret)
9308 return ret;
9309
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009310 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009311
9312 if (!in) {
9313 ALOGE("failed to allocate input stream");
9314 return -ENOMEM;
9315 }
9316
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309317 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05309318 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
9319 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009320 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07009321 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009322
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009323 in->stream.common.get_sample_rate = in_get_sample_rate;
9324 in->stream.common.set_sample_rate = in_set_sample_rate;
9325 in->stream.common.get_buffer_size = in_get_buffer_size;
9326 in->stream.common.get_channels = in_get_channels;
9327 in->stream.common.get_format = in_get_format;
9328 in->stream.common.set_format = in_set_format;
9329 in->stream.common.standby = in_standby;
9330 in->stream.common.dump = in_dump;
9331 in->stream.common.set_parameters = in_set_parameters;
9332 in->stream.common.get_parameters = in_get_parameters;
9333 in->stream.common.add_audio_effect = in_add_audio_effect;
9334 in->stream.common.remove_audio_effect = in_remove_audio_effect;
9335 in->stream.set_gain = in_set_gain;
9336 in->stream.read = in_read;
9337 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08009338 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309339 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07009340 in->stream.set_microphone_direction = in_set_microphone_direction;
9341 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07009342 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009343
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009344 list_init(&in->device_list);
9345 update_device_list(&in->device_list, devices, address, true);
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009346 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009347 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009348 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009349 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009350 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07009351 in->bit_width = 16;
9352 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07009353 in->direction = MIC_DIRECTION_UNSPECIFIED;
9354 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08009355 list_init(&in->aec_list);
9356 list_init(&in->ns_list);
Phil Burkd898ba62019-06-20 12:49:01 -07009357 in->mmap_shared_memory_fd = -1; // not open
Haynes Mathew George46740472017-10-27 18:40:12 -07009358
Andy Hung94320602018-10-29 18:31:12 -07009359 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08009360 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
9361 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
9362 /* Force channel config requested to mono if incall
9363 record is being requested for only uplink/downlink */
9364 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
9365 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9366 ret = -EINVAL;
9367 goto err_open;
9368 }
9369 }
9370
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009371 if (is_usb_dev && may_use_hifi_record) {
9372 /* HiFi record selects an appropriate format, channel, rate combo
9373 depending on sink capabilities*/
9374 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
9375 &config->format,
9376 &in->supported_formats[0],
9377 MAX_SUPPORTED_FORMATS,
9378 &config->channel_mask,
9379 &in->supported_channel_masks[0],
9380 MAX_SUPPORTED_CHANNEL_MASKS,
9381 &config->sample_rate,
9382 &in->supported_sample_rates[0],
9383 MAX_SUPPORTED_SAMPLE_RATES);
9384 if (ret != 0) {
9385 ret = -EINVAL;
9386 goto err_open;
9387 }
9388 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009389 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309390 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05309391 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
9392 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
9393 in->config.format = PCM_FORMAT_S32_LE;
9394 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309395 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
9396 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
9397 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
9398 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
9399 bool ret_error = false;
9400 in->bit_width = 24;
9401 /* 24 bit is restricted to UNPROCESSED source only,also format supported
9402 from HAL is 24_packed and 8_24
9403 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
9404 24_packed return error indicating supported format is 24_packed
9405 *> In case of any other source requesting 24 bit or float return error
9406 indicating format supported is 16 bit only.
9407
9408 on error flinger will retry with supported format passed
9409 */
9410 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
9411 (source != AUDIO_SOURCE_CAMCORDER)) {
9412 config->format = AUDIO_FORMAT_PCM_16_BIT;
9413 if (config->sample_rate > 48000)
9414 config->sample_rate = 48000;
9415 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07009416 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
9417 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309418 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
9419 ret_error = true;
9420 }
9421
9422 if (ret_error) {
9423 ret = -EINVAL;
9424 goto err_open;
9425 }
9426 }
9427
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009428 in->channel_mask = config->channel_mask;
9429 in->format = config->format;
9430
9431 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309432
9433 if (in->source == AUDIO_SOURCE_FM_TUNER) {
9434 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
9435 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
9436 else {
9437 ret = -EINVAL;
9438 goto err_open;
9439 }
9440 }
9441
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009442 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Deeraj Somanfa377bf2019-02-06 12:57:59 +05309443 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
9444 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009445 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
9446 is_low_latency = true;
9447#if LOW_LATENCY_CAPTURE_USE_CASE
Revathi Uddarajud9f23d92020-07-27 10:55:06 +05309448 if ((flags & AUDIO_INPUT_FLAG_VOIP_TX) != 0)
9449 in->usecase = USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY;
9450 else
9451 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009452#endif
9453 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08009454 if (!in->realtime) {
9455 in->config = pcm_config_audio_capture;
9456 frame_size = audio_stream_in_frame_size(&in->stream);
9457 buffer_size = get_input_buffer_size(config->sample_rate,
9458 config->format,
9459 channel_count,
9460 is_low_latency);
9461 in->config.period_size = buffer_size / frame_size;
9462 in->config.rate = config->sample_rate;
9463 in->af_period_multiplier = 1;
9464 } else {
9465 // period size is left untouched for rt mode playback
9466 in->config = pcm_config_audio_capture_rt;
9467 in->af_period_multiplier = af_period_multiplier;
9468 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009469 }
9470
9471 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
9472 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
9473 in->realtime = 0;
9474 in->usecase = USECASE_AUDIO_RECORD_MMAP;
9475 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07009476 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009477 in->stream.start = in_start;
9478 in->stream.stop = in_stop;
9479 in->stream.create_mmap_buffer = in_create_mmap_buffer;
9480 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009481 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
Haynes Mathew George46740472017-10-27 18:40:12 -07009482 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009483 in->usecase = USECASE_AUDIO_RECORD_HIFI;
9484 in->config = pcm_config_audio_capture;
9485 frame_size = audio_stream_in_frame_size(&in->stream);
9486 buffer_size = get_input_buffer_size(config->sample_rate,
9487 config->format,
9488 channel_count,
9489 false /*is_low_latency*/);
9490 in->config.period_size = buffer_size / frame_size;
9491 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009492 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07009493 switch (config->format) {
9494 case AUDIO_FORMAT_PCM_32_BIT:
9495 in->bit_width = 32;
9496 break;
9497 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
9498 case AUDIO_FORMAT_PCM_8_24_BIT:
9499 in->bit_width = 24;
9500 break;
9501 default:
9502 in->bit_width = 16;
9503 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009504 } else if (is_single_device_type_equal(&in->device_list,
9505 AUDIO_DEVICE_IN_TELEPHONY_RX) ||
9506 is_single_device_type_equal(&in->device_list,
9507 AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009508 if (config->sample_rate == 0)
9509 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9510 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
9511 config->sample_rate != 8000) {
9512 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9513 ret = -EINVAL;
9514 goto err_open;
9515 }
9516 if (config->format == AUDIO_FORMAT_DEFAULT)
9517 config->format = AUDIO_FORMAT_PCM_16_BIT;
9518 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
9519 config->format = AUDIO_FORMAT_PCM_16_BIT;
9520 ret = -EINVAL;
9521 goto err_open;
9522 }
9523
9524 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
Zhou Song62ea0282020-03-22 19:53:01 +08009525 if (adev->ha_proxy_enable &&
9526 is_single_device_type_equal(&in->device_list,
9527 AUDIO_DEVICE_IN_TELEPHONY_RX))
9528 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY2;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009529 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009530 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08009531 in->af_period_multiplier = 1;
Revathi Uddarajud9f23d92020-07-27 10:55:06 +05309532 } else if (in->realtime) {
9533 in->config = pcm_config_audio_capture_rt;
9534 in->config.format = pcm_format_from_audio_format(config->format);
9535 in->af_period_multiplier = af_period_multiplier;
Aalique Grahame22e49102018-12-18 14:23:57 -08009536 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
9537 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
9538 (config->sample_rate == 8000 ||
9539 config->sample_rate == 16000 ||
9540 config->sample_rate == 32000 ||
9541 config->sample_rate == 48000) &&
9542 channel_count == 1) {
9543 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9544 in->config = pcm_config_audio_capture;
9545 frame_size = audio_stream_in_frame_size(&in->stream);
9546 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
9547 config->sample_rate,
9548 config->format,
9549 channel_count, false /*is_low_latency*/);
9550 in->config.period_size = buffer_size / frame_size;
9551 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
9552 in->config.rate = config->sample_rate;
9553 in->af_period_multiplier = 1;
Haynes Mathew George46740472017-10-27 18:40:12 -07009554 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05309555 int ret_val;
9556 pthread_mutex_lock(&adev->lock);
9557 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
9558 in, config, &channel_mask_updated);
9559 pthread_mutex_unlock(&adev->lock);
9560
9561 if (!ret_val) {
9562 if (channel_mask_updated == true) {
9563 ALOGD("%s: return error to retry with updated channel mask (%#x)",
9564 __func__, config->channel_mask);
9565 ret = -EINVAL;
9566 goto err_open;
9567 }
9568 ALOGD("%s: created multi-channel session succesfully",__func__);
9569 } else if (audio_extn_compr_cap_enabled() &&
9570 audio_extn_compr_cap_format_supported(config->format) &&
9571 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
9572 audio_extn_compr_cap_init(in);
9573 } else if (audio_extn_cin_applicable_stream(in)) {
Deeraj Soman14230922019-01-30 16:39:30 +05309574 ret = audio_extn_cin_configure_input_stream(in, config);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309575 if (ret)
9576 goto err_open;
9577 } else {
9578 in->config = pcm_config_audio_capture;
9579 in->config.rate = config->sample_rate;
9580 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309581 in->format = config->format;
9582 frame_size = audio_stream_in_frame_size(&in->stream);
9583 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07009584 config->format,
9585 channel_count,
9586 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02009587 /* prevent division-by-zero */
9588 if (frame_size == 0) {
9589 ALOGE("%s: Error frame_size==0", __func__);
9590 ret = -EINVAL;
9591 goto err_open;
9592 }
9593
Revathi Uddarajud2634032017-12-07 14:42:34 +05309594 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08009595 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009596
Revathi Uddarajud2634032017-12-07 14:42:34 +05309597 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9598 /* optionally use VOIP usecase depending on config(s) */
9599 ret = adev_update_voice_comm_input_stream(in, config);
9600 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009601
Revathi Uddarajud2634032017-12-07 14:42:34 +05309602 if (ret) {
9603 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
9604 goto err_open;
9605 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009606 }
Jaideep Sharmad305a4a2020-02-27 14:29:04 +05309607
9608 /* assign concurrent capture usecase if record has to caried out from
9609 * actual hardware input source */
9610 if (audio_extn_is_concurrent_capture_enabled() &&
9611 !audio_is_virtual_input_source(in->source)) {
Samyak Jainc37062f2019-04-25 18:41:06 +05309612 /* Acquire lock to avoid two concurrent use cases initialized to
9613 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +08009614
Samyak Jainc37062f2019-04-25 18:41:06 +05309615 if (in->usecase == USECASE_AUDIO_RECORD) {
9616 pthread_mutex_lock(&adev->lock);
9617 if (!(adev->pcm_record_uc_state)) {
9618 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
9619 adev->pcm_record_uc_state = 1;
9620 pthread_mutex_unlock(&adev->lock);
9621 } else {
9622 pthread_mutex_unlock(&adev->lock);
9623 /* Assign compress record use case for second record */
9624 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
9625 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
9626 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
9627 if (audio_extn_cin_applicable_stream(in)) {
9628 in->sample_rate = config->sample_rate;
Deeraj Soman14230922019-01-30 16:39:30 +05309629 ret = audio_extn_cin_configure_input_stream(in, config);
Samyak Jainc37062f2019-04-25 18:41:06 +05309630 if (ret)
9631 goto err_open;
9632 }
9633 }
9634 }
kunleiz28c73e72019-03-27 17:24:04 +08009635 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009636 }
Ramjee Singh82fd0c12019-08-21 16:31:33 +05309637 if (audio_extn_ssr_get_stream() != in)
9638 in->config.channels = channel_count;
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009639
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009640 in->sample_rate = in->config.rate;
9641
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309642 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
9643 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009644 &in->device_list, flags, in->format,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009645 in->sample_rate, in->bit_width,
9646 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05309647 register_format(in->format, in->supported_formats);
9648 register_channel_mask(in->channel_mask, in->supported_channel_masks);
9649 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309650
Aalique Grahame22e49102018-12-18 14:23:57 -08009651 in->error_log = error_log_create(
9652 ERROR_LOG_ENTRIES,
9653 1000000000 /* aggregate consecutive identical errors within one second */);
9654
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009655 /* This stream could be for sound trigger lab,
9656 get sound trigger pcm if present */
9657 audio_extn_sound_trigger_check_and_get_session(in);
9658
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309659 lock_input_stream(in);
9660 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
9661 pthread_mutex_lock(&adev->lock);
9662 in->card_status = adev->card_status;
9663 pthread_mutex_unlock(&adev->lock);
9664 pthread_mutex_unlock(&in->lock);
9665
Aalique Grahame22e49102018-12-18 14:23:57 -08009666 stream_app_type_cfg_init(&in->app_type_cfg);
9667
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009668 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -08009669
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009670 ret = io_streams_map_insert(adev, &in->stream.common,
9671 handle, AUDIO_PATCH_HANDLE_NONE);
9672 if (ret != 0)
9673 goto err_open;
9674
Derek Chenf939fb72018-11-13 13:34:41 -08009675 streams_input_ctxt_t *in_ctxt = (streams_input_ctxt_t *)
9676 calloc(1, sizeof(streams_input_ctxt_t));
9677 if (in_ctxt == NULL) {
9678 ALOGE("%s fail to allocate input ctxt", __func__);
9679 ret = -ENOMEM;
9680 goto err_open;
9681 }
9682 in_ctxt->input = in;
9683
9684 pthread_mutex_lock(&adev->lock);
9685 list_add_tail(&adev->active_inputs_list, &in_ctxt->list);
9686 pthread_mutex_unlock(&adev->lock);
9687
Eric Laurent994a6932013-07-17 11:51:42 -07009688 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009689 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009690
9691err_open:
Samyak Jainc37062f2019-04-25 18:41:06 +05309692 if (in->usecase == USECASE_AUDIO_RECORD) {
9693 pthread_mutex_lock(&adev->lock);
9694 adev->pcm_record_uc_state = 0;
9695 pthread_mutex_unlock(&adev->lock);
9696 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009697 free(in);
9698 *stream_in = NULL;
9699 return ret;
9700}
9701
9702static void adev_close_input_stream(struct audio_hw_device *dev,
9703 struct audio_stream_in *stream)
9704{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009705 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009706 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009707 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309708
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309709 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08009710
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009711 if (in == NULL) {
9712 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
9713 return;
9714 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009715 io_streams_map_remove(adev, in->capture_handle);
9716
kunleiz70e57612018-12-28 17:50:23 +08009717 /* must deregister from sndmonitor first to prevent races
9718 * between the callback and close_stream
9719 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309720 audio_extn_snd_mon_unregister_listener(stream);
9721
kunleiz70e57612018-12-28 17:50:23 +08009722 /* Disable echo reference if there are no active input, hfp call
9723 * and sound trigger while closing input stream
9724 */
Eric Laurent637e2d42018-11-15 12:24:31 -08009725 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +08009726 !audio_extn_hfp_is_active(adev) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009727 !audio_extn_sound_trigger_check_ec_ref_enable()) {
9728 struct listnode out_devices;
9729 list_init(&out_devices);
9730 platform_set_echo_reference(adev, false, &out_devices);
9731 } else
kunleiz70e57612018-12-28 17:50:23 +08009732 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05309733
Weiyin Jiang2995f662019-04-17 14:25:12 +08009734 error_log_destroy(in->error_log);
9735 in->error_log = NULL;
9736
Pallavid7c7a272018-01-16 11:22:55 +05309737
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009738 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309739 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009740 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309741 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009742 if (ret != 0)
9743 ALOGE("%s: Compress voip input cannot be closed, error:%d",
9744 __func__, ret);
9745 } else
9746 in_standby(&stream->common);
9747
Revathi Uddarajud2634032017-12-07 14:42:34 +05309748 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05309749 if (in->usecase == USECASE_AUDIO_RECORD) {
9750 adev->pcm_record_uc_state = 0;
9751 }
9752
Kunlei Zhang5d5d8d92020-02-26 15:00:59 +08009753 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9754 adev->enable_voicerx = false;
9755 }
9756
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07009757 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009758 audio_extn_ssr_deinit();
9759 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009760
Garmond Leunge2433c32017-09-28 21:51:22 -07009761 if (audio_extn_ffv_get_stream() == in) {
9762 audio_extn_ffv_stream_deinit();
9763 }
9764
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309765 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07009766 audio_extn_compr_cap_format_supported(in->config.format))
9767 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05309768
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05309769 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05309770 audio_extn_cin_free_input_stream_resources(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009771
Mingming Yinfd7607b2016-01-22 12:48:44 -08009772 if (in->is_st_session) {
9773 ALOGV("%s: sound trigger pcm stop lab", __func__);
9774 audio_extn_sound_trigger_stop_lab(in);
9775 }
Derek Chenf939fb72018-11-13 13:34:41 -08009776 streams_input_ctxt_t *in_ctxt = in_get_stream(adev, in->capture_handle);
9777 if (in_ctxt != NULL) {
9778 list_remove(&in_ctxt->list);
9779 free(in_ctxt);
9780 } else {
9781 ALOGW("%s, input stream already closed", __func__);
9782 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009783 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309784 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009785 return;
9786}
9787
Aalique Grahame22e49102018-12-18 14:23:57 -08009788/* verifies input and output devices and their capabilities.
9789 *
9790 * This verification is required when enabling extended bit-depth or
9791 * sampling rates, as not all qcom products support it.
9792 *
9793 * Suitable for calling only on initialization such as adev_open().
9794 * It fills the audio_device use_case_table[] array.
9795 *
9796 * Has a side-effect that it needs to configure audio routing / devices
9797 * in order to power up the devices and read the device parameters.
9798 * It does not acquire any hw device lock. Should restore the devices
9799 * back to "normal state" upon completion.
9800 */
9801static int adev_verify_devices(struct audio_device *adev)
9802{
9803 /* enumeration is a bit difficult because one really wants to pull
9804 * the use_case, device id, etc from the hidden pcm_device_table[].
9805 * In this case there are the following use cases and device ids.
9806 *
9807 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
9808 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
9809 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
9810 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
9811 * [USECASE_AUDIO_RECORD] = {0, 0},
9812 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
9813 * [USECASE_VOICE_CALL] = {2, 2},
9814 *
9815 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
9816 * USECASE_VOICE_CALL omitted, but possible for either input or output.
9817 */
9818
9819 /* should be the usecases enabled in adev_open_input_stream() */
9820 static const int test_in_usecases[] = {
9821 USECASE_AUDIO_RECORD,
9822 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
9823 };
9824 /* should be the usecases enabled in adev_open_output_stream()*/
9825 static const int test_out_usecases[] = {
9826 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
9827 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
9828 };
9829 static const usecase_type_t usecase_type_by_dir[] = {
9830 PCM_PLAYBACK,
9831 PCM_CAPTURE,
9832 };
9833 static const unsigned flags_by_dir[] = {
9834 PCM_OUT,
9835 PCM_IN,
9836 };
9837
9838 size_t i;
9839 unsigned dir;
9840 const unsigned card_id = adev->snd_card;
9841
9842 for (dir = 0; dir < 2; ++dir) {
9843 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
9844 const unsigned flags_dir = flags_by_dir[dir];
9845 const size_t testsize =
9846 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
9847 const int *testcases =
9848 dir ? test_in_usecases : test_out_usecases;
9849 const audio_devices_t audio_device =
9850 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
9851
9852 for (i = 0; i < testsize; ++i) {
9853 const audio_usecase_t audio_usecase = testcases[i];
9854 int device_id;
9855 struct pcm_params **pparams;
9856 struct stream_out out;
9857 struct stream_in in;
9858 struct audio_usecase uc_info;
9859 int retval;
9860
9861 pparams = &adev->use_case_table[audio_usecase];
9862 pcm_params_free(*pparams); /* can accept null input */
9863 *pparams = NULL;
9864
9865 /* find the device ID for the use case (signed, for error) */
9866 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
9867 if (device_id < 0)
9868 continue;
9869
9870 /* prepare structures for device probing */
9871 memset(&uc_info, 0, sizeof(uc_info));
9872 uc_info.id = audio_usecase;
9873 uc_info.type = usecase_type;
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009874 list_init(&uc_info.device_list);
Aalique Grahame22e49102018-12-18 14:23:57 -08009875 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -08009876 memset(&in, 0, sizeof(in));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009877 list_init(&in.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009878 update_device_list(&in.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009879 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
9880 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -08009881 }
9882 memset(&out, 0, sizeof(out));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009883 list_init(&out.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009884 update_device_list(&out.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009885 uc_info.stream.out = &out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009886 update_device_list(&uc_info.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009887 uc_info.in_snd_device = SND_DEVICE_NONE;
9888 uc_info.out_snd_device = SND_DEVICE_NONE;
9889 list_add_tail(&adev->usecase_list, &uc_info.list);
9890
9891 /* select device - similar to start_(in/out)put_stream() */
9892 retval = select_devices(adev, audio_usecase);
9893 if (retval >= 0) {
9894 *pparams = pcm_params_get(card_id, device_id, flags_dir);
9895#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -07009896 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -08009897 if (*pparams) {
9898 ALOGV("%s: (%s) card %d device %d", __func__,
9899 dir ? "input" : "output", card_id, device_id);
9900 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
9901 } else {
9902 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
9903 }
9904#endif
9905 }
9906
9907 /* deselect device - similar to stop_(in/out)put_stream() */
9908 /* 1. Get and set stream specific mixer controls */
9909 retval = disable_audio_route(adev, &uc_info);
9910 /* 2. Disable the rx device */
9911 retval = disable_snd_device(adev,
9912 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
9913 list_remove(&uc_info.list);
9914 }
9915 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009916 return 0;
9917}
9918
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009919int update_patch(unsigned int num_sources,
9920 const struct audio_port_config *sources,
9921 unsigned int num_sinks,
9922 const struct audio_port_config *sinks,
9923 audio_patch_handle_t handle,
9924 struct audio_patch_info *p_info,
9925 patch_type_t patch_type, bool new_patch)
9926{
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07009927 ALOGV("%s: enter", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009928
9929 if (p_info == NULL) {
9930 ALOGE("%s: Invalid patch pointer", __func__);
9931 return -EINVAL;
9932 }
9933
9934 if (new_patch) {
9935 p_info->patch = (struct audio_patch *) calloc(1, sizeof(struct audio_patch));
9936 if (p_info->patch == NULL) {
9937 ALOGE("%s: Could not allocate patch", __func__);
9938 return -ENOMEM;
9939 }
9940 }
9941
9942 p_info->patch->id = handle;
9943 p_info->patch->num_sources = num_sources;
9944 p_info->patch->num_sinks = num_sinks;
9945
9946 for (int i = 0; i < num_sources; i++)
9947 p_info->patch->sources[i] = sources[i];
9948 for (int i = 0; i < num_sinks; i++)
9949 p_info->patch->sinks[i] = sinks[i];
9950
9951 p_info->patch_type = patch_type;
9952 return 0;
9953}
9954
9955audio_patch_handle_t generate_patch_handle()
9956{
9957 static audio_patch_handle_t patch_handle = AUDIO_PATCH_HANDLE_NONE;
9958 if (++patch_handle < 0)
9959 patch_handle = AUDIO_PATCH_HANDLE_NONE + 1;
9960 return patch_handle;
9961}
9962
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309963int adev_create_audio_patch(struct audio_hw_device *dev,
9964 unsigned int num_sources,
9965 const struct audio_port_config *sources,
9966 unsigned int num_sinks,
9967 const struct audio_port_config *sinks,
9968 audio_patch_handle_t *handle)
9969{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009970 int ret = 0;
9971 struct audio_device *adev = (struct audio_device *)dev;
9972 struct audio_patch_info *p_info = NULL;
9973 patch_type_t patch_type = PATCH_NONE;
9974 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
9975 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
9976 struct audio_stream_info *s_info = NULL;
9977 struct audio_stream *stream = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009978 struct listnode devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009979 audio_devices_t device_type = AUDIO_DEVICE_NONE;
9980 bool new_patch = false;
9981 char addr[AUDIO_DEVICE_MAX_ADDRESS_LEN];
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309982
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009983 ALOGD("%s: enter: num sources %d, num_sinks %d, handle %d", __func__,
9984 num_sources, num_sinks, *handle);
9985
9986 if (num_sources == 0 || num_sources > AUDIO_PATCH_PORTS_MAX ||
9987 num_sinks == 0 || num_sinks > AUDIO_PATCH_PORTS_MAX) {
9988 ALOGE("%s: Invalid patch arguments", __func__);
9989 ret = -EINVAL;
9990 goto done;
9991 }
9992
9993 if (num_sources > 1) {
9994 ALOGE("%s: Multiple sources are not supported", __func__);
9995 ret = -EINVAL;
9996 goto done;
9997 }
9998
9999 if (sources == NULL || sinks == NULL) {
10000 ALOGE("%s: Invalid sources or sinks port config", __func__);
10001 ret = -EINVAL;
10002 goto done;
10003 }
10004
10005 ALOGV("%s: source role %d, source type %d", __func__,
10006 sources[0].type, sources[0].role);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010007 list_init(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010008
10009 // Populate source/sink information and fetch stream info
10010 switch (sources[0].type) {
10011 case AUDIO_PORT_TYPE_DEVICE: // Patch for audio capture or loopback
10012 device_type = sources[0].ext.device.type;
10013 strlcpy(&addr[0], &sources[0].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010014 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010015 if (sinks[0].type == AUDIO_PORT_TYPE_MIX) {
10016 patch_type = PATCH_CAPTURE;
10017 io_handle = sinks[0].ext.mix.handle;
10018 input_source = sinks[0].ext.mix.usecase.source;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010019 ALOGD("%s: Capture patch from device %x to mix %d",
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010020 __func__, device_type, io_handle);
10021 } else {
10022 // Device to device patch is not implemented.
10023 // This space will need changes if audio HAL
10024 // handles device to device patches in the future.
10025 patch_type = PATCH_DEVICE_LOOPBACK;
10026 }
10027 break;
10028 case AUDIO_PORT_TYPE_MIX: // Patch for audio playback
10029 io_handle = sources[0].ext.mix.handle;
10030 for (int i = 0; i < num_sinks; i++) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010031 device_type = sinks[i].ext.device.type;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010032 strlcpy(&addr[0], &sinks[i].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010033 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010034 }
10035 patch_type = PATCH_PLAYBACK;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010036 ALOGD("%s: Playback patch from mix handle %d to device %x",
10037 __func__, io_handle, get_device_types(&devices));
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010038 break;
10039 case AUDIO_PORT_TYPE_SESSION:
10040 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010041 ALOGE("%s: Unsupported source type %d", __func__, sources[0].type);
10042 ret = -EINVAL;
10043 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010044 }
10045
10046 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010047
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010048 // Generate patch info and update patch
10049 if (*handle == AUDIO_PATCH_HANDLE_NONE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010050 *handle = generate_patch_handle();
10051 p_info = (struct audio_patch_info *)
10052 calloc(1, sizeof(struct audio_patch_info));
10053 if (p_info == NULL) {
10054 ALOGE("%s: Failed to allocate memory", __func__);
10055 pthread_mutex_unlock(&adev->lock);
10056 ret = -ENOMEM;
10057 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010058 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010059 new_patch = true;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010060 } else {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010061 p_info = fetch_patch_info_l(adev, *handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010062 if (p_info == NULL) {
10063 ALOGE("%s: Unable to fetch patch for received patch handle %d",
10064 __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010065 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010066 ret = -EINVAL;
10067 goto done;
10068 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010069 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010070 update_patch(num_sources, sources, num_sinks, sinks,
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010071 *handle, p_info, patch_type, new_patch);
10072
10073 // Fetch stream info of associated mix for playback or capture patches
10074 if (p_info->patch_type == PATCH_PLAYBACK ||
10075 p_info->patch_type == PATCH_CAPTURE) {
10076 s_info = hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10077 if (s_info == NULL) {
10078 ALOGE("%s: Failed to obtain stream info", __func__);
10079 if (new_patch)
10080 free(p_info);
10081 pthread_mutex_unlock(&adev->lock);
10082 ret = -EINVAL;
10083 goto done;
10084 }
10085 ALOGV("%s: Fetched stream info with io_handle %d", __func__, io_handle);
10086 s_info->patch_handle = *handle;
10087 stream = s_info->stream;
10088 }
10089 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010090
10091 // Update routing for stream
10092 if (stream != NULL) {
10093 if (p_info->patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010094 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010095 else if (p_info->patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010096 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010097 if (ret < 0) {
10098 pthread_mutex_lock(&adev->lock);
10099 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10100 if (new_patch)
10101 free(p_info);
10102 pthread_mutex_unlock(&adev->lock);
10103 ALOGE("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10104 goto done;
10105 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010106 }
10107
10108 // Add new patch to patch map
10109 if (!ret && new_patch) {
10110 pthread_mutex_lock(&adev->lock);
10111 hashmapPut(adev->patch_map, (void *) (intptr_t) *handle, (void *) p_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010112 ALOGD("%s: Added a new patch with handle %d", __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010113 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010114 }
10115
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010116done:
10117 audio_extn_hw_loopback_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010118 num_sources,
10119 sources,
10120 num_sinks,
10121 sinks,
10122 handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010123 audio_extn_auto_hal_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010124 num_sources,
10125 sources,
10126 num_sinks,
10127 sinks,
10128 handle);
10129 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010130}
10131
10132int adev_release_audio_patch(struct audio_hw_device *dev,
10133 audio_patch_handle_t handle)
10134{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010135 struct audio_device *adev = (struct audio_device *) dev;
10136 int ret = 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010137 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010138 struct audio_stream *stream = NULL;
Derek Chenf939fb72018-11-13 13:34:41 -080010139
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010140 if (handle == AUDIO_PATCH_HANDLE_NONE) {
10141 ALOGE("%s: Invalid patch handle %d", __func__, handle);
10142 ret = -EINVAL;
10143 goto done;
10144 }
10145
10146 ALOGD("%s: Remove patch with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010147 pthread_mutex_lock(&adev->lock);
10148 struct audio_patch_info *p_info = fetch_patch_info_l(adev, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010149 if (p_info == NULL) {
10150 ALOGE("%s: Patch info not found with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010151 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010152 ret = -EINVAL;
10153 goto done;
10154 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010155 struct audio_patch *patch = p_info->patch;
10156 if (patch == NULL) {
10157 ALOGE("%s: Patch not found for handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010158 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010159 ret = -EINVAL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010160 goto done;
10161 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010162 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10163 switch (patch->sources[0].type) {
10164 case AUDIO_PORT_TYPE_MIX:
10165 io_handle = patch->sources[0].ext.mix.handle;
10166 break;
10167 case AUDIO_PORT_TYPE_DEVICE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010168 if (p_info->patch_type == PATCH_CAPTURE)
10169 io_handle = patch->sinks[0].ext.mix.handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010170 break;
10171 case AUDIO_PORT_TYPE_SESSION:
10172 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010173 pthread_mutex_unlock(&adev->lock);
10174 ret = -EINVAL;
10175 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010176 }
10177
10178 // Remove patch and reset patch handle in stream info
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010179 patch_type_t patch_type = p_info->patch_type;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010180 patch_map_remove_l(adev, handle);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010181 if (patch_type == PATCH_PLAYBACK ||
10182 patch_type == PATCH_CAPTURE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010183 struct audio_stream_info *s_info =
10184 hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10185 if (s_info == NULL) {
10186 ALOGE("%s: stream for io_handle %d is not available", __func__, io_handle);
10187 pthread_mutex_unlock(&adev->lock);
10188 goto done;
10189 }
10190 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10191 stream = s_info->stream;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010192 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010193 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010194
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010195 if (stream != NULL) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010196 struct listnode devices;
10197 list_init(&devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010198 if (patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010199 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010200 else if (patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010201 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010202 }
10203
10204 if (ret < 0)
10205 ALOGW("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10206
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010207done:
10208 audio_extn_hw_loopback_release_audio_patch(dev, handle);
10209 audio_extn_auto_hal_release_audio_patch(dev, handle);
10210
10211 ALOGV("%s: Successfully released patch %d", __func__, handle);
Derek Chenf939fb72018-11-13 13:34:41 -080010212 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010213}
10214
10215int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
10216{
Derek Chenf13dd492018-11-13 14:53:51 -080010217 int ret = 0;
10218
10219 ret = audio_extn_hw_loopback_get_audio_port(dev, config);
10220 ret |= audio_extn_auto_hal_get_audio_port(dev, config);
10221 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010222}
10223
10224int adev_set_audio_port_config(struct audio_hw_device *dev,
10225 const struct audio_port_config *config)
10226{
Derek Chenf13dd492018-11-13 14:53:51 -080010227 int ret = 0;
10228
10229 ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
10230 ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
10231 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010232}
10233
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -070010234static int adev_dump(const audio_hw_device_t *device __unused,
10235 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010236{
10237 return 0;
10238}
10239
10240static int adev_close(hw_device_t *device)
10241{
Aalique Grahame22e49102018-12-18 14:23:57 -080010242 size_t i;
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010243 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -070010244
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010245 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -070010246 return 0;
10247
10248 pthread_mutex_lock(&adev_init_lock);
10249
10250 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +053010251 if (audio_extn_spkr_prot_is_enabled())
10252 audio_extn_spkr_prot_deinit();
Jaideep Sharmaa2b49672019-09-10 20:37:03 +053010253 audio_extn_battery_properties_listener_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010254 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010255 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -080010256 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010257 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -080010258 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010259 audio_extn_utils_release_streams_cfg_lists(
10260 &adev->streams_output_cfg_list,
10261 &adev->streams_input_cfg_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010262 if (audio_extn_qap_is_enabled())
10263 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010264 if (audio_extn_qaf_is_enabled())
10265 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -070010266 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +080010267 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -070010268 free(adev->snd_dev_ref_cnt);
10269 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010270 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
10271 pcm_params_free(adev->use_case_table[i]);
10272 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010273 if (adev->adm_deinit)
10274 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010275 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010276 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010277 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010278 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010279 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010280 if (adev->device_cfg_params) {
10281 free(adev->device_cfg_params);
10282 adev->device_cfg_params = NULL;
10283 }
Derek Chend2530072014-11-24 12:39:14 -080010284 if(adev->ext_hw_plugin)
10285 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -080010286 audio_extn_auto_hal_deinit();
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010287 free_map(adev->patch_map);
10288 free_map(adev->io_streams_map);
Kiran Kandi910e1862013-10-29 13:29:42 -070010289 free(device);
10290 adev = NULL;
10291 }
10292 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +053010293 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010294 return 0;
10295}
10296
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010297/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
10298 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
10299 * just that it _might_ work.
10300 */
10301static int period_size_is_plausible_for_low_latency(int period_size)
10302{
10303 switch (period_size) {
10304 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -070010305 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010306 case 240:
10307 case 320:
10308 case 480:
10309 return 1;
10310 default:
10311 return 0;
10312 }
10313}
10314
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010315static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
10316{
10317 bool is_snd_card_status = false;
10318 bool is_ext_device_status = false;
10319 char value[32];
10320 int card = -1;
10321 card_status_t status;
10322
10323 if (cookie != adev || !parms)
10324 return;
10325
10326 if (!parse_snd_card_status(parms, &card, &status)) {
10327 is_snd_card_status = true;
10328 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
10329 is_ext_device_status = true;
10330 } else {
10331 // not a valid event
10332 return;
10333 }
10334
10335 pthread_mutex_lock(&adev->lock);
10336 if (card == adev->snd_card || is_ext_device_status) {
10337 if (is_snd_card_status && adev->card_status != status) {
10338 adev->card_status = status;
10339 platform_snd_card_update(adev->platform, status);
10340 audio_extn_fm_set_parameters(adev, parms);
Derek Chend6f371d2019-03-01 13:45:58 -080010341 audio_extn_auto_hal_set_parameters(adev, parms);
Zhou Song4f43e352019-07-02 00:32:23 +080010342 if (status == CARD_STATUS_OFFLINE)
10343 audio_extn_sco_reset_configuration();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010344 } else if (is_ext_device_status) {
10345 platform_set_parameters(adev->platform, parms);
10346 }
10347 }
10348 pthread_mutex_unlock(&adev->lock);
10349 return;
10350}
10351
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010352/* out and adev lock held */
10353static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
10354{
10355 struct audio_usecase *uc_info;
10356 float left_p;
10357 float right_p;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010358 struct listnode devices;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010359
10360 uc_info = get_usecase_from_list(adev, out->usecase);
10361 if (uc_info == NULL) {
10362 ALOGE("%s: Could not find the usecase (%d) in the list",
10363 __func__, out->usecase);
10364 return -EINVAL;
10365 }
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010366 list_init(&devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010367
10368 ALOGD("%s: enter: usecase(%d: %s)", __func__,
10369 out->usecase, use_case_table[out->usecase]);
10370
10371 if (restore) {
10372 // restore A2DP device for active usecases and unmute if required
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010373 if (is_a2dp_out_device_type(&out->device_list)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010374 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
Zhou Songe5225132019-09-26 15:33:36 +080010375 if (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)
10376 select_devices(adev, uc_info->id);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010377 pthread_mutex_lock(&out->compr_mute_lock);
10378 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Manisha Agarwalc2188fb2019-05-27 10:00:29 +053010379 (out->a2dp_compress_mute) && (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010380 out->a2dp_compress_mute = false;
10381 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
10382 }
10383 pthread_mutex_unlock(&out->compr_mute_lock);
10384 }
10385 } else {
Zhou Songc576a452019-09-09 14:17:40 +080010386 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
10387 // mute compress stream if suspended
10388 pthread_mutex_lock(&out->compr_mute_lock);
10389 if (!out->a2dp_compress_mute && !out->standby) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010390 ALOGD("%s: selecting speaker and muting stream", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010391 assign_devices(&devices, &out->device_list);
10392 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010393 left_p = out->volume_l;
10394 right_p = out->volume_r;
10395 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10396 compress_pause(out->compr);
10397 out_set_compr_volume(&out->stream, (float)0, (float)0);
10398 out->a2dp_compress_mute = true;
10399 select_devices(adev, out->usecase);
10400 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10401 compress_resume(out->compr);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010402 assign_devices(&out->device_list, &devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010403 out->volume_l = left_p;
10404 out->volume_r = right_p;
10405 }
Zhou Songc576a452019-09-09 14:17:40 +080010406 pthread_mutex_unlock(&out->compr_mute_lock);
10407 } else {
10408 // tear down a2dp path for non offloaded streams
10409 if (audio_extn_a2dp_source_is_suspended())
10410 out_standby_l(&out->stream.common);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010411 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010412 }
10413 ALOGV("%s: exit", __func__);
10414 return 0;
10415}
10416
10417int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
10418{
10419 int ret = 0;
10420
10421 lock_output_stream(out);
10422 pthread_mutex_lock(&adev->lock);
10423
10424 ret = check_a2dp_restore_l(adev, out, restore);
10425
10426 pthread_mutex_unlock(&adev->lock);
10427 pthread_mutex_unlock(&out->lock);
10428 return ret;
10429}
10430
Haynes Mathew George01156f92018-04-13 15:29:54 -070010431void adev_on_battery_status_changed(bool charging)
10432{
10433 pthread_mutex_lock(&adev->lock);
10434 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
10435 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +080010436 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -070010437 pthread_mutex_unlock(&adev->lock);
10438}
10439
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010440static int adev_open(const hw_module_t *module, const char *name,
10441 hw_device_t **device)
10442{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010443 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -080010444 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010445 char mixer_ctl_name[128] = {0};
10446 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010447
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080010448 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010449 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
10450
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010451 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -070010452 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010453 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -070010454 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010455 ALOGD("%s: returning existing instance of adev", __func__);
10456 ALOGD("%s: exit", __func__);
10457 pthread_mutex_unlock(&adev_init_lock);
10458 return 0;
10459 }
10460
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010461 adev = calloc(1, sizeof(struct audio_device));
10462
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -070010463 if (!adev) {
10464 pthread_mutex_unlock(&adev_init_lock);
10465 return -ENOMEM;
10466 }
10467
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -070010468 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
10469
Weiyin Jiange6ce6312019-01-28 18:28:22 +080010470 // register audio ext hidl at the earliest
10471 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053010472#ifdef DYNAMIC_LOG_ENABLED
10473 register_for_dynamic_logging("hal");
10474#endif
10475
Derek Chenf939fb72018-11-13 13:34:41 -080010476 /* default audio HAL major version */
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010477 uint32_t maj_version = 3;
Derek Chenf939fb72018-11-13 13:34:41 -080010478 if(property_get("vendor.audio.hal.maj.version", value, NULL))
10479 maj_version = atoi(value);
10480
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010481 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -080010482 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010483 adev->device.common.module = (struct hw_module_t *)module;
10484 adev->device.common.close = adev_close;
10485
10486 adev->device.init_check = adev_init_check;
10487 adev->device.set_voice_volume = adev_set_voice_volume;
10488 adev->device.set_master_volume = adev_set_master_volume;
10489 adev->device.get_master_volume = adev_get_master_volume;
10490 adev->device.set_master_mute = adev_set_master_mute;
10491 adev->device.get_master_mute = adev_get_master_mute;
10492 adev->device.set_mode = adev_set_mode;
10493 adev->device.set_mic_mute = adev_set_mic_mute;
10494 adev->device.get_mic_mute = adev_get_mic_mute;
10495 adev->device.set_parameters = adev_set_parameters;
10496 adev->device.get_parameters = adev_get_parameters;
10497 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
10498 adev->device.open_output_stream = adev_open_output_stream;
10499 adev->device.close_output_stream = adev_close_output_stream;
10500 adev->device.open_input_stream = adev_open_input_stream;
10501 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010502 adev->device.create_audio_patch = adev_create_audio_patch;
10503 adev->device.release_audio_patch = adev_release_audio_patch;
10504 adev->device.get_audio_port = adev_get_audio_port;
10505 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010506 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +053010507 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010508
10509 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010510 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -080010511 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010512 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010513 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -080010514 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -070010515 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +053010516 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -070010517 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -070010518 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -070010519 /* Init audio and voice feature */
10520 audio_extn_feature_init();
10521 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070010522 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -080010523 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -080010524 list_init(&adev->active_inputs_list);
10525 list_init(&adev->active_outputs_list);
Rahul Sharma99770982019-03-06 17:05:26 +053010526 list_init(&adev->audio_patch_record_list);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010527 adev->io_streams_map = hashmapCreate(AUDIO_IO_PORTS_MAX, audio_extn_utils_hash_fn,
10528 audio_extn_utils_hash_eq);
10529 if (!adev->io_streams_map) {
10530 ALOGE("%s: Could not create io streams map", __func__);
10531 ret = -ENOMEM;
10532 goto adev_open_err;
10533 }
10534 adev->patch_map = hashmapCreate(AUDIO_PATCH_PORTS_MAX, audio_extn_utils_hash_fn,
10535 audio_extn_utils_hash_eq);
10536 if (!adev->patch_map) {
10537 ALOGE("%s: Could not create audio patch map", __func__);
10538 ret = -ENOMEM;
10539 goto adev_open_err;
10540 }
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -080010541 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -070010542 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +053010543 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +053010544 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +053010545 adev->perf_lock_opts[0] = 0x101;
10546 adev->perf_lock_opts[1] = 0x20E;
10547 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010548 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -070010549 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010550 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010551 adev->adm_routing_changed = false;
Revathi Uddarajub26e3932020-06-10 14:51:02 +053010552 adev->a2dp_started = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +053010553
Zhou Song68ebc352019-12-05 17:11:15 +080010554 audio_extn_perf_lock_init();
10555
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010556 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -070010557 adev->platform = platform_init(adev);
10558 if (!adev->platform) {
Eric Laurentb23d5282013-05-14 15:27:20 -070010559 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010560 ret = -EINVAL;
10561 goto adev_open_err;
Eric Laurentb23d5282013-05-14 15:27:20 -070010562 }
Eric Laurentc4aef752013-09-12 17:45:53 -070010563
Aalique Grahame22e49102018-12-18 14:23:57 -080010564 adev->extspk = audio_extn_extspk_init(adev);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010565 if (audio_extn_qap_is_enabled()) {
10566 ret = audio_extn_qap_init(adev);
10567 if (ret < 0) {
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010568 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010569 goto adev_open_err;
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010570 }
10571 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
10572 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
10573 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010574
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010575 if (audio_extn_qaf_is_enabled()) {
10576 ret = audio_extn_qaf_init(adev);
10577 if (ret < 0) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010578 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010579 goto adev_open_err;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010580 }
10581
10582 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
10583 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
10584 }
10585
Derek Chenae7b0342019-02-08 15:17:04 -080010586 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -080010587 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
10588
Eric Laurentc4aef752013-09-12 17:45:53 -070010589 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
10590 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
10591 if (adev->visualizer_lib == NULL) {
10592 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
10593 } else {
10594 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
10595 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010596 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010597 "visualizer_hal_start_output");
10598 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010599 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010600 "visualizer_hal_stop_output");
10601 }
10602 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +053010603 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010604 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -080010605 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +080010606 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010607 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010608 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -070010609
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010610 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
10611 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
10612 if (adev->offload_effects_lib == NULL) {
10613 ALOGE("%s: DLOPEN failed for %s", __func__,
10614 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10615 } else {
10616 ALOGV("%s: DLOPEN successful for %s", __func__,
10617 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10618 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +053010619 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010620 "offload_effects_bundle_hal_start_output");
10621 adev->offload_effects_stop_output =
10622 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
10623 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080010624 adev->offload_effects_set_hpx_state =
10625 (int (*)(bool))dlsym(adev->offload_effects_lib,
10626 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +053010627 adev->offload_effects_get_parameters =
10628 (void (*)(struct str_parms *, struct str_parms *))
10629 dlsym(adev->offload_effects_lib,
10630 "offload_effects_bundle_get_parameters");
10631 adev->offload_effects_set_parameters =
10632 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
10633 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010634 }
10635 }
10636
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010637 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
10638 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
10639 if (adev->adm_lib == NULL) {
10640 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
10641 } else {
10642 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
10643 adev->adm_init = (adm_init_t)
10644 dlsym(adev->adm_lib, "adm_init");
10645 adev->adm_deinit = (adm_deinit_t)
10646 dlsym(adev->adm_lib, "adm_deinit");
10647 adev->adm_register_input_stream = (adm_register_input_stream_t)
10648 dlsym(adev->adm_lib, "adm_register_input_stream");
10649 adev->adm_register_output_stream = (adm_register_output_stream_t)
10650 dlsym(adev->adm_lib, "adm_register_output_stream");
10651 adev->adm_deregister_stream = (adm_deregister_stream_t)
10652 dlsym(adev->adm_lib, "adm_deregister_stream");
10653 adev->adm_request_focus = (adm_request_focus_t)
10654 dlsym(adev->adm_lib, "adm_request_focus");
10655 adev->adm_abandon_focus = (adm_abandon_focus_t)
10656 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010657 adev->adm_set_config = (adm_set_config_t)
10658 dlsym(adev->adm_lib, "adm_set_config");
10659 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
10660 dlsym(adev->adm_lib, "adm_request_focus_v2");
10661 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
10662 dlsym(adev->adm_lib, "adm_is_noirq_avail");
10663 adev->adm_on_routing_change = (adm_on_routing_change_t)
10664 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010665 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
10666 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010667 }
10668 }
10669
Aalique Grahame22e49102018-12-18 14:23:57 -080010670 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010671 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +080010672 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -080010673 //initialize this to false for now,
10674 //this will be set to true through set param
10675 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010676
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -070010677 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010678 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -080010679
10680 if (k_enable_extended_precision)
10681 adev_verify_devices(adev);
10682
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010683 adev->dsp_bit_width_enforce_mode =
10684 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010685
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010686 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
10687 &adev->streams_output_cfg_list,
10688 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070010689
Kiran Kandi910e1862013-10-29 13:29:42 -070010690 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010691
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010692 int trial;
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010693 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010694 trial = atoi(value);
10695 if (period_size_is_plausible_for_low_latency(trial)) {
10696 pcm_config_low_latency.period_size = trial;
10697 pcm_config_low_latency.start_threshold = trial / 4;
10698 pcm_config_low_latency.avail_min = trial / 4;
10699 configured_low_latency_capture_period_size = trial;
10700 }
10701 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010702 if ((property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) ||
10703 (property_get("audio_hal.in_period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010704 trial = atoi(value);
10705 if (period_size_is_plausible_for_low_latency(trial)) {
10706 configured_low_latency_capture_period_size = trial;
10707 }
10708 }
10709
Vignesh Kulothungan7d374312018-02-21 17:12:00 -080010710 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
10711
Eric Laurent4b084132018-10-19 17:33:43 -070010712 adev->camera_orientation = CAMERA_DEFAULT;
10713
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010714 if (property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010715 af_period_multiplier = atoi(value);
10716 if (af_period_multiplier < 0)
10717 af_period_multiplier = 2;
10718 else if (af_period_multiplier > 4)
10719 af_period_multiplier = 4;
10720
10721 ALOGV("new period_multiplier = %d", af_period_multiplier);
10722 }
10723
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010724 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010725
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -070010726 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Zhou Song62ea0282020-03-22 19:53:01 +080010727 adev->ha_proxy_enable = property_get_bool("persist.vendor.audio.ha_proxy.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010728 pthread_mutex_unlock(&adev_init_lock);
10729
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010730 if (adev->adm_init)
10731 adev->adm_data = adev->adm_init();
10732
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010733 qahwi_init(*device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010734 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010735
10736 audio_extn_snd_mon_init();
10737 pthread_mutex_lock(&adev->lock);
10738 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
10739 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -070010740 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
10741 /*
10742 * if the battery state callback happens before charging can be queried,
10743 * it will be guarded with the adev->lock held in the cb function and so
10744 * the callback value will reflect the latest state
10745 */
10746 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010747 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +080010748 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -070010749 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +080010750 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010751 /* Allocate memory for Device config params */
10752 adev->device_cfg_params = (struct audio_device_config_param*)
10753 calloc(platform_get_max_codec_backend(),
10754 sizeof(struct audio_device_config_param));
10755 if (adev->device_cfg_params == NULL)
10756 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010757
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010758 /*
10759 * Check if new PSPD matrix mixer control is supported. If not
10760 * supported, then set flag so that old mixer ctrl is sent while
10761 * sending pspd coefficients on older kernel version. Query mixer
10762 * control for default pcm id and channel value one.
10763 */
10764 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
10765 "AudStr %d ChMixer Weight Ch %d", 0, 1);
10766
10767 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
10768 if (!ctl) {
10769 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
10770 __func__, mixer_ctl_name);
10771 adev->use_old_pspd_mix_ctrl = true;
10772 }
10773
Eric Laurent994a6932013-07-17 11:51:42 -070010774 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010775 return 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010776
10777adev_open_err:
10778 free_map(adev->patch_map);
10779 free_map(adev->io_streams_map);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010780 free(adev->snd_dev_ref_cnt);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010781 pthread_mutex_destroy(&adev->lock);
10782 free(adev);
10783 adev = NULL;
10784 *device = NULL;
10785 pthread_mutex_unlock(&adev_init_lock);
10786 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010787}
10788
10789static struct hw_module_methods_t hal_module_methods = {
10790 .open = adev_open,
10791};
10792
10793struct audio_module HAL_MODULE_INFO_SYM = {
10794 .common = {
10795 .tag = HARDWARE_MODULE_TAG,
10796 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
10797 .hal_api_version = HARDWARE_HAL_API_VERSION,
10798 .id = AUDIO_HARDWARE_MODULE_ID,
10799 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -080010800 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010801 .methods = &hal_module_methods,
10802 },
10803};