blob: e8e71dae8779434eccac937d2e664868f6e9f6e9 [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",
Varun Balaraje49253e2017-07-06 19:48:56 +0530402 /* For Interactive Audio Streams */
403 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
404 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
405 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
406 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
407 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
408 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
409 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
410 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700411
Aniket Kumar Lata7fd86e12018-02-20 19:26:10 -0800412 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture",
413
Derek Chenf6318be2017-06-12 17:16:24 -0400414 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
415
416 [USECASE_AUDIO_PLAYBACK_MEDIA] = "media-playback",
417 [USECASE_AUDIO_PLAYBACK_SYS_NOTIFICATION] = "sys-notification-playback",
418 [USECASE_AUDIO_PLAYBACK_NAV_GUIDANCE] = "nav-guidance-playback",
419 [USECASE_AUDIO_PLAYBACK_PHONE] = "phone-playback",
Derek Chen1bcdc6b2020-02-06 22:44:53 -0800420 [USECASE_AUDIO_PLAYBACK_FRONT_PASSENGER] = "front-passenger-playback",
Derek Chendf05eea2019-08-01 13:57:49 -0700421 [USECASE_AUDIO_PLAYBACK_REAR_SEAT] = "rear-seat-playback",
Rahul Sharma99770982019-03-06 17:05:26 +0530422 [USECASE_AUDIO_FM_TUNER_EXT] = "fm-tuner-ext",
Eric Laurentb23d5282013-05-14 15:27:20 -0700423};
424
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700425static const audio_usecase_t offload_usecases[] = {
426 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700427 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
428 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
429 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
430 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
431 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
432 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
433 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
434 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700435};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800436
Varun Balaraje49253e2017-07-06 19:48:56 +0530437static const audio_usecase_t interactive_usecases[] = {
438 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
439 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
440 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
441 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
442 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
443 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
444 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
445 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
446};
447
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800448#define STRING_TO_ENUM(string) { #string, string }
449
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800450struct string_to_enum {
451 const char *name;
452 uint32_t value;
453};
454
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700455static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800456 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800457 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
458 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
459 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700460 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800461 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
462 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800463 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700464 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
465 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
466 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
467 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
468 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
469 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
470 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
471 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
472 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
473 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
474 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800475};
476
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700477static const struct string_to_enum formats_name_to_enum_table[] = {
478 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
479 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
480 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700481 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
482 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
483 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700484 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800485 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
486 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700487 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800488};
489
490//list of all supported sample rates by HDMI specification.
491static const int out_hdmi_sample_rates[] = {
492 32000, 44100, 48000, 88200, 96000, 176400, 192000,
493};
494
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700495static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800496 STRING_TO_ENUM(32000),
497 STRING_TO_ENUM(44100),
498 STRING_TO_ENUM(48000),
499 STRING_TO_ENUM(88200),
500 STRING_TO_ENUM(96000),
501 STRING_TO_ENUM(176400),
502 STRING_TO_ENUM(192000),
Mingshu pange8aedf12019-10-25 15:38:27 +0800503 STRING_TO_ENUM(352800),
504 STRING_TO_ENUM(384000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700505};
506
Carter Hsu2e429db2019-05-14 18:50:52 +0800507struct in_effect_list {
508 struct listnode list;
509 effect_handle_t handle;
510};
511
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700512static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700513static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700514static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700515//cache last MBDRC cal step level
516static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700517
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530518static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
519static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Arun Mirpuri5d170872019-03-26 13:21:31 -0700520static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800521static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530522static int out_set_pcm_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530523
Derek Chen6f293672019-04-01 01:40:24 -0700524static void adev_snd_mon_cb(void *cookie, struct str_parms *parms);
525static void in_snd_mon_cb(void * stream, struct str_parms * parms);
526static void out_snd_mon_cb(void * stream, struct str_parms * parms);
527
Zhou Song331c8e52019-08-26 14:16:12 +0800528static int configure_btsco_sample_rate(snd_device_t snd_device);
529
Vatsal Buchac09ae062018-11-14 13:25:08 +0530530#ifdef AUDIO_FEATURE_ENABLED_GCOV
531extern void __gcov_flush();
532static void enable_gcov()
533{
534 __gcov_flush();
535}
536#else
537static void enable_gcov()
538{
539}
540#endif
541
justinweng20fb6d82019-02-21 18:49:00 -0700542static int in_set_microphone_direction(const struct audio_stream_in *stream,
543 audio_microphone_direction_t dir);
544static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom);
545
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700546static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
547 int flags __unused)
548{
549 int dir = 0;
550 switch (uc_id) {
551 case USECASE_AUDIO_RECORD_LOW_LATENCY:
552 dir = 1;
553 case USECASE_AUDIO_PLAYBACK_ULL:
554 break;
555 default:
556 return false;
557 }
558
559 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
560 PCM_PLAYBACK : PCM_CAPTURE);
561 if (adev->adm_is_noirq_avail)
562 return adev->adm_is_noirq_avail(adev->adm_data,
563 adev->snd_card, dev_id, dir);
564 return false;
565}
566
567static void register_out_stream(struct stream_out *out)
568{
569 struct audio_device *adev = out->dev;
570 if (is_offload_usecase(out->usecase) ||
571 !adev->adm_register_output_stream)
572 return;
573
574 // register stream first for backward compatibility
575 adev->adm_register_output_stream(adev->adm_data,
576 out->handle,
577 out->flags);
578
579 if (!adev->adm_set_config)
580 return;
581
582 if (out->realtime)
583 adev->adm_set_config(adev->adm_data,
584 out->handle,
585 out->pcm, &out->config);
586}
587
588static void register_in_stream(struct stream_in *in)
589{
590 struct audio_device *adev = in->dev;
591 if (!adev->adm_register_input_stream)
592 return;
593
594 adev->adm_register_input_stream(adev->adm_data,
595 in->capture_handle,
596 in->flags);
597
598 if (!adev->adm_set_config)
599 return;
600
601 if (in->realtime)
602 adev->adm_set_config(adev->adm_data,
603 in->capture_handle,
604 in->pcm,
605 &in->config);
606}
607
608static void request_out_focus(struct stream_out *out, long ns)
609{
610 struct audio_device *adev = out->dev;
611
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700612 if (adev->adm_request_focus_v2)
613 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
614 else if (adev->adm_request_focus)
615 adev->adm_request_focus(adev->adm_data, out->handle);
616}
617
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700618static int request_in_focus(struct stream_in *in, long ns)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700619{
620 struct audio_device *adev = in->dev;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700621 int ret = 0;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700622
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700623 if (adev->adm_request_focus_v2_1)
624 ret = adev->adm_request_focus_v2_1(adev->adm_data, in->capture_handle, ns);
625 else if (adev->adm_request_focus_v2)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700626 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
627 else if (adev->adm_request_focus)
628 adev->adm_request_focus(adev->adm_data, in->capture_handle);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700629
630 return ret;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700631}
632
633static void release_out_focus(struct stream_out *out)
634{
635 struct audio_device *adev = out->dev;
636
637 if (adev->adm_abandon_focus)
638 adev->adm_abandon_focus(adev->adm_data, out->handle);
639}
640
641static void release_in_focus(struct stream_in *in)
642{
643 struct audio_device *adev = in->dev;
644 if (adev->adm_abandon_focus)
645 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
646}
647
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530648static int parse_snd_card_status(struct str_parms *parms, int *card,
649 card_status_t *status)
650{
651 char value[32]={0};
652 char state[32]={0};
653
654 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
655 if (ret < 0)
656 return -1;
657
658 // sscanf should be okay as value is of max length 32.
659 // same as sizeof state.
660 if (sscanf(value, "%d,%s", card, state) < 2)
661 return -1;
662
663 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
664 CARD_STATUS_OFFLINE;
665 return 0;
666}
667
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700668static inline void adjust_frames_for_device_delay(struct stream_out *out,
669 uint32_t *dsp_frames) {
670 // Adjustment accounts for A2dp encoder latency with offload usecases
671 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -0800672 if (is_a2dp_out_device_type(&out->device_list)) {
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700673 unsigned long offset =
674 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
675 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
676 }
677}
678
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700679static inline bool free_entry(void *key __unused,
680 void *value, void *context __unused)
681{
682 free(value);
683 return true;
684}
685
686static inline void free_map(Hashmap *map)
687{
688 if (map) {
689 hashmapForEach(map, free_entry, (void *) NULL);
690 hashmapFree(map);
691 }
692}
693
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800694static inline void patch_map_remove_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700695 audio_patch_handle_t patch_handle)
696{
697 if (patch_handle == AUDIO_PATCH_HANDLE_NONE)
698 return;
699
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700700 struct audio_patch_info *p_info =
701 hashmapGet(adev->patch_map, (void *) (intptr_t) patch_handle);
702 if (p_info) {
703 ALOGV("%s: Remove patch %d", __func__, patch_handle);
704 hashmapRemove(adev->patch_map, (void *) (intptr_t) patch_handle);
705 free(p_info->patch);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700706 free(p_info);
707 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700708}
709
710static inline int io_streams_map_insert(struct audio_device *adev,
711 struct audio_stream *stream,
712 audio_io_handle_t handle,
713 audio_patch_handle_t patch_handle)
714{
715 struct audio_stream_info *s_info =
716 (struct audio_stream_info *) calloc(1, sizeof(struct audio_stream_info));
717
718 if (s_info == NULL) {
719 ALOGE("%s: Could not allocate stream info", __func__);
720 return -ENOMEM;
721 }
722 s_info->stream = stream;
723 s_info->patch_handle = patch_handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700724
725 pthread_mutex_lock(&adev->lock);
726 struct audio_stream_info *stream_info =
727 hashmapPut(adev->io_streams_map, (void *) (intptr_t) handle, (void *) s_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700728 if (stream_info != NULL)
729 free(stream_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800730 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700731 ALOGD("%s: Added stream in io_streams_map with handle %d", __func__, handle);
732 return 0;
733}
734
735static inline void io_streams_map_remove(struct audio_device *adev,
736 audio_io_handle_t handle)
737{
738 pthread_mutex_lock(&adev->lock);
739 struct audio_stream_info *s_info =
740 hashmapRemove(adev->io_streams_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700741 if (s_info == NULL)
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800742 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700743 ALOGD("%s: Removed stream with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800744 patch_map_remove_l(adev, s_info->patch_handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700745 free(s_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800746done:
747 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700748 return;
749}
750
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800751static struct audio_patch_info* fetch_patch_info_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700752 audio_patch_handle_t handle)
753{
754 struct audio_patch_info *p_info = NULL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700755 p_info = (struct audio_patch_info *)
756 hashmapGet(adev->patch_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700757 return p_info;
758}
759
vivek mehtaa76401a2015-04-24 14:12:15 -0700760__attribute__ ((visibility ("default")))
761bool audio_hw_send_gain_dep_calibration(int level) {
762 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700763 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700764
765 pthread_mutex_lock(&adev_init_lock);
766
767 if (adev != NULL && adev->platform != NULL) {
768 pthread_mutex_lock(&adev->lock);
769 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700770
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530771 // cache level info for any of the use case which
772 // was not started.
773 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700774
vivek mehtaa76401a2015-04-24 14:12:15 -0700775 pthread_mutex_unlock(&adev->lock);
776 } else {
777 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
778 }
779
780 pthread_mutex_unlock(&adev_init_lock);
781
782 return ret_val;
783}
784
Ashish Jain5106d362016-05-11 19:23:33 +0530785static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
786{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800787 bool gapless_enabled = false;
788 const char *mixer_ctl_name = "Compress Gapless Playback";
789 struct mixer_ctl *ctl;
790
791 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700792 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530793
794 /*Disable gapless if its AV playback*/
795 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800796
797 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
798 if (!ctl) {
799 ALOGE("%s: Could not get ctl for mixer cmd - %s",
800 __func__, mixer_ctl_name);
801 return -EINVAL;
802 }
803
804 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
805 ALOGE("%s: Could not set gapless mode %d",
806 __func__, gapless_enabled);
807 return -EINVAL;
808 }
809 return 0;
810}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700811
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700812__attribute__ ((visibility ("default")))
813int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
814 int table_size) {
815 int ret_val = 0;
816 ALOGV("%s: enter ... ", __func__);
817
818 pthread_mutex_lock(&adev_init_lock);
819 if (adev == NULL) {
820 ALOGW("%s: adev is NULL .... ", __func__);
821 goto done;
822 }
823
824 pthread_mutex_lock(&adev->lock);
825 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
826 pthread_mutex_unlock(&adev->lock);
827done:
828 pthread_mutex_unlock(&adev_init_lock);
829 ALOGV("%s: exit ... ", __func__);
830 return ret_val;
831}
832
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800833bool audio_hw_send_qdsp_parameter(int stream_type, float vol, bool active)
Aalique Grahame22e49102018-12-18 14:23:57 -0800834{
835 bool ret = false;
836 ALOGV("%s: enter ...", __func__);
837
838 pthread_mutex_lock(&adev_init_lock);
839
840 if (adev != NULL && adev->platform != NULL) {
841 pthread_mutex_lock(&adev->lock);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800842 ret = audio_extn_qdsp_set_state(adev, stream_type, vol, active);
Aalique Grahame22e49102018-12-18 14:23:57 -0800843 pthread_mutex_unlock(&adev->lock);
844 }
845
846 pthread_mutex_unlock(&adev_init_lock);
847
848 ALOGV("%s: exit with ret %d", __func__, ret);
849 return ret;
850}
Aalique Grahame22e49102018-12-18 14:23:57 -0800851
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700852static bool is_supported_format(audio_format_t format)
853{
Eric Laurent86e17132013-09-12 17:49:30 -0700854 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530855 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530856 format == AUDIO_FORMAT_AAC_LC ||
857 format == AUDIO_FORMAT_AAC_HE_V1 ||
858 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530859 format == AUDIO_FORMAT_AAC_ADTS_LC ||
860 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
861 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530862 format == AUDIO_FORMAT_AAC_LATM_LC ||
863 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
864 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530865 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
866 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530867 format == AUDIO_FORMAT_PCM_FLOAT ||
868 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700869 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530870 format == AUDIO_FORMAT_AC3 ||
871 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700872 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530873 format == AUDIO_FORMAT_DTS ||
874 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800875 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530876 format == AUDIO_FORMAT_ALAC ||
877 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530878 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530879 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800880 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530881 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700882 format == AUDIO_FORMAT_APTX ||
883 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800884 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700885
886 return false;
887}
888
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700889static inline bool is_mmap_usecase(audio_usecase_t uc_id)
890{
891 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
Zhou Song62ea0282020-03-22 19:53:01 +0800892 (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY2) ||
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700893 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
894}
895
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700896static inline bool is_valid_volume(float left, float right)
897{
898 return ((left >= 0.0f && right >= 0.0f) ? true : false);
899}
900
Avinash Vaish71a8b972014-07-24 15:36:33 +0530901static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
902 struct audio_usecase *uc_info)
903{
904 struct listnode *node;
905 struct audio_usecase *usecase;
906
907 if (uc_info == NULL)
908 return -EINVAL;
909
910 /* Re-route all voice usecases on the shared backend other than the
911 specified usecase to new snd devices */
912 list_for_each(node, &adev->usecase_list) {
913 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800914 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530915 enable_audio_route(adev, usecase);
916 }
917 return 0;
918}
919
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530920static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530921{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530922 ALOGV("%s", __func__);
923 audio_route_apply_and_update_path(adev->audio_route,
924 "asrc-mode");
925 adev->asrc_mode_enabled = true;
926}
927
928static void disable_asrc_mode(struct audio_device *adev)
929{
930 ALOGV("%s", __func__);
931 audio_route_reset_and_update_path(adev->audio_route,
932 "asrc-mode");
933 adev->asrc_mode_enabled = false;
934}
935
936/*
937 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
938 * 44.1 or Native DSD backends are enabled for any of current use case.
939 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
940 * - Disable current mix path use case(Headphone backend) and re-enable it with
941 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
942 * e.g. Naitve DSD or Headphone 44.1 -> + 48
943 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530944static void check_and_set_asrc_mode(struct audio_device *adev,
945 struct audio_usecase *uc_info,
946 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530947{
948 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530949 int i, num_new_devices = 0;
950 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
951 /*
952 *Split snd device for new combo use case
953 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
954 */
955 if (platform_split_snd_device(adev->platform,
956 snd_device,
957 &num_new_devices,
958 split_new_snd_devices) == 0) {
959 for (i = 0; i < num_new_devices; i++)
960 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
961 } else {
962 int new_backend_idx = platform_get_backend_index(snd_device);
963 if (((new_backend_idx == HEADPHONE_BACKEND) ||
964 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
965 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
966 !adev->asrc_mode_enabled) {
967 struct listnode *node = NULL;
968 struct audio_usecase *uc = NULL;
969 struct stream_out *curr_out = NULL;
970 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
971 int i, num_devices, ret = 0;
972 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530973
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530974 list_for_each(node, &adev->usecase_list) {
975 uc = node_to_item(node, struct audio_usecase, list);
976 curr_out = (struct stream_out*) uc->stream.out;
977 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
978 /*
979 *Split snd device for existing combo use case
980 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
981 */
982 ret = platform_split_snd_device(adev->platform,
983 uc->out_snd_device,
984 &num_devices,
985 split_snd_devices);
986 if (ret < 0 || num_devices == 0) {
987 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
988 split_snd_devices[0] = uc->out_snd_device;
989 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800990 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530991 for (i = 0; i < num_devices; i++) {
992 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
993 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
994 if((new_backend_idx == HEADPHONE_BACKEND) &&
995 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
996 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
997 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
998 __func__);
999 enable_asrc_mode(adev);
1000 break;
1001 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
1002 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
1003 (usecase_backend_idx == HEADPHONE_BACKEND)) {
1004 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
1005 __func__);
1006 disable_audio_route(adev, uc);
1007 disable_snd_device(adev, uc->out_snd_device);
1008 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
1009 if (new_backend_idx == DSD_NATIVE_BACKEND)
1010 audio_route_apply_and_update_path(adev->audio_route,
1011 "hph-true-highquality-mode");
1012 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
1013 (curr_out->bit_width >= 24))
1014 audio_route_apply_and_update_path(adev->audio_route,
1015 "hph-highquality-mode");
1016 enable_asrc_mode(adev);
1017 enable_snd_device(adev, uc->out_snd_device);
1018 enable_audio_route(adev, uc);
1019 break;
1020 }
1021 }
1022 // reset split devices count
1023 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -08001024 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301025 if (adev->asrc_mode_enabled)
1026 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301027 }
1028 }
1029 }
1030}
1031
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001032static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
1033 struct audio_effect_config effect_config,
1034 unsigned int param_value)
1035{
1036 char mixer_ctl_name[] = "Audio Effect";
1037 struct mixer_ctl *ctl;
1038 long set_values[6];
Eric Laurent637e2d42018-11-15 12:24:31 -08001039 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001040
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001041 if (in == NULL) {
1042 ALOGE("%s: active input stream is NULL", __func__);
1043 return -EINVAL;
1044 }
1045
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001046 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1047 if (!ctl) {
1048 ALOGE("%s: Could not get mixer ctl - %s",
1049 __func__, mixer_ctl_name);
1050 return -EINVAL;
1051 }
1052
1053 set_values[0] = 1; //0:Rx 1:Tx
1054 set_values[1] = in->app_type_cfg.app_type;
1055 set_values[2] = (long)effect_config.module_id;
1056 set_values[3] = (long)effect_config.instance_id;
1057 set_values[4] = (long)effect_config.param_id;
1058 set_values[5] = param_value;
1059
1060 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
1061
1062 return 0;
1063
1064}
1065
1066static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
1067 int effect_type, unsigned int *param_value)
1068{
1069 int ret = 0;
1070 struct audio_effect_config other_effect_config;
1071 struct audio_usecase *usecase = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08001072 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001073
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001074 if (in == NULL) {
1075 ALOGE("%s: active input stream is NULL", __func__);
1076 return -EINVAL;
1077 }
1078
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001079 usecase = get_usecase_from_list(adev, in->usecase);
1080 if (!usecase)
1081 return -EINVAL;
1082
1083 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
1084 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
1085 if (ret < 0) {
1086 ALOGE("%s Failed to get effect params %d", __func__, ret);
1087 return ret;
1088 }
1089
1090 if (module_id == other_effect_config.module_id) {
1091 //Same module id for AEC/NS. Values need to be combined
1092 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
1093 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
1094 *param_value |= other_effect_config.param_value;
1095 }
1096 }
1097
1098 return ret;
1099}
1100
1101static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
Gangadhar Sb0210342019-02-22 17:39:41 +05301102{
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001103 struct audio_effect_config effect_config;
1104 struct audio_usecase *usecase = NULL;
1105 int ret = 0;
1106 unsigned int param_value = 0;
Eric Laurent637e2d42018-11-15 12:24:31 -08001107 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001108
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001109 if(!voice_extn_is_dynamic_ecns_enabled())
1110 return ENOSYS;
1111
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001112 if (!in) {
1113 ALOGE("%s: Invalid input stream", __func__);
1114 return -EINVAL;
1115 }
1116
1117 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
1118
1119 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +08001120 if (usecase == NULL) {
1121 ALOGE("%s: Could not find the usecase (%d) in the list",
1122 __func__, in->usecase);
1123 return -EINVAL;
1124 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001125
1126 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
1127 if (ret < 0) {
1128 ALOGE("%s Failed to get module id %d", __func__, ret);
1129 return ret;
1130 }
1131 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
1132 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
1133
1134 if(enable)
1135 param_value = effect_config.param_value;
1136
1137 /*Special handling for AEC & NS effects Param values need to be
1138 updated if module ids are same*/
1139
1140 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
1141 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
1142 if (ret < 0)
1143 return ret;
1144 }
1145
1146 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
1147
1148 return ret;
1149}
1150
1151static void check_and_enable_effect(struct audio_device *adev)
1152{
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001153 if(!voice_extn_is_dynamic_ecns_enabled())
1154 return;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001155
Eric Laurent637e2d42018-11-15 12:24:31 -08001156 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001157
Eric Laurent637e2d42018-11-15 12:24:31 -08001158 if (in != NULL && !in->standby) {
1159 if (in->enable_aec)
1160 enable_disable_effect(adev, EFFECT_AEC, true);
1161
1162 if (in->enable_ns &&
1163 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1164 enable_disable_effect(adev, EFFECT_NS, true);
1165 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001166 }
1167}
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001168
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001169int pcm_ioctl(struct pcm *pcm, int request, ...)
1170{
1171 va_list ap;
1172 void * arg;
1173 int pcm_fd = *(int*)pcm;
1174
1175 va_start(ap, request);
1176 arg = va_arg(ap, void *);
1177 va_end(ap);
1178
1179 return ioctl(pcm_fd, request, arg);
1180}
1181
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001182int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001183 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001184{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001185 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001186 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +05301187 struct stream_out *out = NULL;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301188 struct stream_in *in = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001189 struct listnode out_devices;
Soumya Managoli6993b762018-06-28 16:04:57 +05301190 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001191
1192 if (usecase == NULL)
1193 return -EINVAL;
1194
1195 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
1196
Carter Hsu2e429db2019-05-14 18:50:52 +08001197 if (usecase->type == PCM_CAPTURE) {
1198 struct stream_in *in = usecase->stream.in;
1199 struct audio_usecase *uinfo;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001200 snd_device = usecase->in_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001201
1202 if (in) {
1203 if (in->enable_aec || in->enable_ec_port) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001204 list_init(&out_devices);
1205 update_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "", true);
Carter Hsu2e429db2019-05-14 18:50:52 +08001206 struct listnode *node;
1207 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1208 USECASE_AUDIO_PLAYBACK_VOIP);
1209 if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001210 assign_devices(&out_devices,
1211 &voip_usecase->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001212 } else if (adev->primary_output &&
1213 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001214 assign_devices(&out_devices,
1215 &adev->primary_output->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001216 } else {
1217 list_for_each(node, &adev->usecase_list) {
1218 uinfo = node_to_item(node, struct audio_usecase, list);
1219 if (uinfo->type != PCM_CAPTURE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001220 assign_devices(&out_devices,
1221 &uinfo->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001222 break;
1223 }
1224 }
1225 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001226
1227 platform_set_echo_reference(adev, true, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001228 in->ec_opened = true;
1229 }
1230 }
Guodong Huf5e614d2019-06-24 18:42:03 +08001231 } else if ((usecase->type == TRANSCODE_LOOPBACK_TX) || ((usecase->type == PCM_HFP_CALL) &&
1232 ((usecase->id == USECASE_AUDIO_HFP_SCO) || (usecase->id == USECASE_AUDIO_HFP_SCO_WB)) &&
1233 (usecase->in_snd_device == SND_DEVICE_IN_VOICE_SPEAKER_MIC_HFP_MMSECNS))) {
Carter Hsu2e429db2019-05-14 18:50:52 +08001234 snd_device = usecase->in_snd_device;
1235 } else {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001236 snd_device = usecase->out_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001237 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001238
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001239#ifdef DS1_DOLBY_DAP_ENABLED
1240 audio_extn_dolby_set_dmid(adev);
1241 audio_extn_dolby_set_endpoint(adev);
1242#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001243 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001244 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301245 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001246 audio_extn_utils_send_app_type_cfg(adev, usecase);
Jasmine Cha4dcc1092019-03-04 18:12:47 +08001247 if (audio_extn_is_maxx_audio_enabled())
1248 audio_extn_ma_set_device(usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301249 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +05301250 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1251 out = usecase->stream.out;
1252 if (out && out->compr)
1253 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1254 }
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301255
1256 if (usecase->type == PCM_CAPTURE) {
1257 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001258 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301259 ALOGD("%s: set custom mtmx params v1", __func__);
1260 audio_extn_set_custom_mtmx_params_v1(adev, usecase, true);
1261 }
1262 } else {
1263 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
1264 }
Manish Dewangan58229382017-02-02 15:48:41 +05301265
Andy Hung756ecc12018-10-19 17:47:12 -07001266 // we shouldn't truncate mixer_path
1267 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1268 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1269 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001270 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001271 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301272 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1273 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1274 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1275 if (parms) {
1276 audio_extn_fm_set_parameters(adev, parms);
1277 str_parms_destroy(parms);
1278 }
1279 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001280 ALOGV("%s: exit", __func__);
1281 return 0;
1282}
1283
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001284int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001285 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001286{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001287 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001288 char mixer_path[MIXER_PATH_MAX_LENGTH];
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301289 struct stream_in *in = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001290
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301291 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001292 return -EINVAL;
1293
1294 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301295 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001296 snd_device = usecase->in_snd_device;
1297 else
1298 snd_device = usecase->out_snd_device;
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001299
1300 /* disable island and power mode on supported device for voice call */
1301 if (usecase->type == VOICE_CALL) {
1302 if (usecase->in_snd_device != SND_DEVICE_NONE) {
1303 if (platform_get_island_cfg_on_device(adev->platform, usecase->in_snd_device) &&
1304 platform_get_power_mode_on_device(adev->platform, usecase->in_snd_device)) {
1305 platform_set_island_cfg_on_device(adev, usecase->in_snd_device, false);
1306 platform_set_power_mode_on_device(adev, usecase->in_snd_device, false);
1307 platform_reset_island_power_status(adev->platform, usecase->in_snd_device);
1308 ALOGD("%s: disable island cfg and power mode in voice tx path",
1309 __func__);
1310 }
1311 }
1312 if (usecase->out_snd_device != SND_DEVICE_NONE) {
1313 if (platform_get_island_cfg_on_device(adev->platform, usecase->out_snd_device) &&
1314 platform_get_power_mode_on_device(adev->platform, usecase->out_snd_device)) {
1315 platform_set_island_cfg_on_device(adev, usecase->out_snd_device, false);
1316 platform_set_power_mode_on_device(adev, usecase->out_snd_device, false);
1317 platform_reset_island_power_status(adev->platform, usecase->out_snd_device);
1318 ALOGD("%s: disable island cfg and power mode in voice rx path",
1319 __func__);
1320 }
1321 }
1322 }
1323
Andy Hung756ecc12018-10-19 17:47:12 -07001324 // we shouldn't truncate mixer_path
1325 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1326 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1327 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001328 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001329 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001330 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Carter Hsu2e429db2019-05-14 18:50:52 +08001331 if (usecase->type == PCM_CAPTURE) {
1332 struct stream_in *in = usecase->stream.in;
1333 if (in && in->ec_opened) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001334 struct listnode out_devices;
1335 list_init(&out_devices);
1336 platform_set_echo_reference(in->dev, false, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001337 in->ec_opened = false;
1338 }
1339 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001340 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301341 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301342
1343 if (usecase->type == PCM_CAPTURE) {
1344 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001345 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301346 ALOGD("%s: reset custom mtmx params v1", __func__);
1347 audio_extn_set_custom_mtmx_params_v1(adev, usecase, false);
1348 }
1349 } else {
1350 audio_extn_set_custom_mtmx_params_v2(adev, usecase, false);
1351 }
1352
Weiyin Jiang298ffd92019-06-03 14:29:30 +08001353 if ((usecase->type == PCM_PLAYBACK) &&
1354 (usecase->stream.out != NULL))
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05301355 usecase->stream.out->pspd_coeff_sent = false;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301356
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001357 ALOGV("%s: exit", __func__);
1358 return 0;
1359}
1360
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001361int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001362 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001363{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301364 int i, num_devices = 0;
1365 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001366 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1367
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001368 if (snd_device < SND_DEVICE_MIN ||
1369 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001370 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001371 return -EINVAL;
1372 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001373
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001374 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001375 ALOGE("%s: Invalid sound device returned", __func__);
1376 return -EINVAL;
1377 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001378
1379 adev->snd_dev_ref_cnt[snd_device]++;
1380
1381 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1382 (platform_split_snd_device(adev->platform,
1383 snd_device,
1384 &num_devices,
1385 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001386 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001387 __func__, snd_device, device_name);
Aniket Kumar Latabce0be62019-07-11 14:20:23 -07001388 /* Set backend config for A2DP to ensure slimbus configuration
1389 is correct if A2DP is already active and backend is closed
1390 and re-opened */
1391 if (snd_device == SND_DEVICE_OUT_BT_A2DP)
1392 audio_extn_a2dp_set_source_backend_cfg();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001393 return 0;
1394 }
1395
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001396 if (audio_extn_spkr_prot_is_enabled())
1397 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001398
Aalique Grahame22e49102018-12-18 14:23:57 -08001399 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1400
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001401 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1402 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001403 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1404 goto err;
1405 }
1406 audio_extn_dev_arbi_acquire(snd_device);
1407 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001408 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001409 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001410 goto err;
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001411 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001412 } else if (platform_split_snd_device(adev->platform,
1413 snd_device,
1414 &num_devices,
1415 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301416 for (i = 0; i < num_devices; i++) {
1417 enable_snd_device(adev, new_snd_devices[i]);
1418 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001419 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001420 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001421 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301422
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001423 /* enable island and power mode on supported device */
1424 if (platform_get_island_cfg_on_device(adev->platform, snd_device) &&
1425 platform_get_power_mode_on_device(adev->platform, snd_device)) {
1426 platform_set_island_cfg_on_device(adev, snd_device, true);
1427 platform_set_power_mode_on_device(adev, snd_device, true);
1428 ALOGD("%s: enable island cfg and power mode on: %s",
1429 __func__, device_name);
1430 }
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301431
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301432 if (SND_DEVICE_OUT_BT_A2DP == snd_device) {
1433 if (audio_extn_a2dp_start_playback() < 0) {
1434 ALOGE(" fail to configure A2dp Source control path ");
1435 goto err;
1436 } else {
1437 adev->a2dp_started = true;
1438 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001439 }
Florian Pfister1a84f312018-07-19 14:38:18 +02001440
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001441 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1442 (audio_extn_a2dp_start_capture() < 0)) {
1443 ALOGE(" fail to configure A2dp Sink control path ");
1444 goto err;
1445 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301446
Mingshu Pang7be5b1d2020-03-04 15:24:38 +08001447 if ((SND_DEVICE_OUT_BT_SCO_SWB == snd_device) ||
1448 (SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC == snd_device) ||
1449 (SND_DEVICE_IN_BT_SCO_MIC_SWB == snd_device)) {
1450 if (!adev->bt_sco_on || (audio_extn_sco_start_configuration() < 0)) {
1451 ALOGE(" fail to configure sco control path ");
1452 goto err;
1453 }
Zhou Song12c29502019-03-16 10:37:18 +08001454 }
1455
Zhou Song331c8e52019-08-26 14:16:12 +08001456 configure_btsco_sample_rate(snd_device);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001457 /* due to the possibility of calibration overwrite between listen
1458 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001459 audio_extn_sound_trigger_update_device_status(snd_device,
1460 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301461 audio_extn_listen_update_device_status(snd_device,
1462 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001463 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001464 audio_extn_sound_trigger_update_device_status(snd_device,
1465 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301466 audio_extn_listen_update_device_status(snd_device,
1467 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001468 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001469 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001470 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001471 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301472
1473 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1474 !adev->native_playback_enabled &&
1475 audio_is_true_native_stream_active(adev)) {
1476 ALOGD("%s: %d: napb: enabling native mode in hardware",
1477 __func__, __LINE__);
1478 audio_route_apply_and_update_path(adev->audio_route,
1479 "true-native-mode");
1480 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301481 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301482 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1483 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001484 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001485 ALOGD("%s: init ec ref loopback", __func__);
1486 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1487 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001488 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001489 return 0;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001490err:
1491 adev->snd_dev_ref_cnt[snd_device]--;
1492 return -EINVAL;;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001493}
1494
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001495int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001496 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001497{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301498 int i, num_devices = 0;
1499 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001500 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1501
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001502 if (snd_device < SND_DEVICE_MIN ||
1503 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001504 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001505 return -EINVAL;
1506 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001507
1508 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1509 ALOGE("%s: Invalid sound device returned", __func__);
1510 return -EINVAL;
1511 }
1512
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001513 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1514 ALOGE("%s: device ref cnt is already 0", __func__);
1515 return -EINVAL;
1516 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001517
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001518 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001519
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001520
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001521 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001522 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301523
Aalique Grahame22e49102018-12-18 14:23:57 -08001524 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1525
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001526 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1527 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001528 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001529
1530 // when speaker device is disabled, reset swap.
1531 // will be renabled on usecase start
1532 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001533 } else if (platform_split_snd_device(adev->platform,
1534 snd_device,
1535 &num_devices,
1536 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301537 for (i = 0; i < num_devices; i++) {
1538 disable_snd_device(adev, new_snd_devices[i]);
1539 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001540 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001541 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001542 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001543 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001544
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301545 if (snd_device == SND_DEVICE_OUT_BT_A2DP) {
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301546 audio_extn_a2dp_stop_playback();
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301547 adev->a2dp_started = false;
1548 } else if (snd_device == SND_DEVICE_IN_BT_A2DP)
Florian Pfister1a84f312018-07-19 14:38:18 +02001549 audio_extn_a2dp_stop_capture();
Zhou Songd6d71752019-05-21 18:08:51 +08001550 else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001551 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
Ashish Jain81eb2a82015-05-13 10:52:34 +05301552 adev->is_channel_status_set = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001553 else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301554 adev->native_playback_enabled) {
1555 ALOGD("%s: %d: napb: disabling native mode in hardware",
1556 __func__, __LINE__);
1557 audio_route_reset_and_update_path(adev->audio_route,
1558 "true-native-mode");
1559 adev->native_playback_enabled = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001560 } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301561 adev->asrc_mode_enabled) {
1562 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301563 disable_asrc_mode(adev);
1564 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001565 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301566 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001567 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001568 ALOGD("%s: deinit ec ref loopback", __func__);
1569 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1570 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001571
1572 audio_extn_utils_release_snd_device(snd_device);
1573 } else {
1574 if (platform_split_snd_device(adev->platform,
1575 snd_device,
1576 &num_devices,
1577 new_snd_devices) == 0) {
1578 for (i = 0; i < num_devices; i++) {
1579 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1580 }
1581 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001582 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001583
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001584 return 0;
1585}
1586
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001587/*
1588 legend:
1589 uc - existing usecase
1590 new_uc - new usecase
1591 d1, d11, d2 - SND_DEVICE enums
1592 a1, a2 - corresponding ANDROID device enums
1593 B1, B2 - backend strings
1594
1595case 1
1596 uc->dev d1 (a1) B1
1597 new_uc->dev d1 (a1), d2 (a2) B1, B2
1598
1599 resolution: disable and enable uc->dev on d1
1600
1601case 2
1602 uc->dev d1 (a1) B1
1603 new_uc->dev d11 (a1) B1
1604
1605 resolution: need to switch uc since d1 and d11 are related
1606 (e.g. speaker and voice-speaker)
1607 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1608
1609case 3
1610 uc->dev d1 (a1) B1
1611 new_uc->dev d2 (a2) B2
1612
1613 resolution: no need to switch uc
1614
1615case 4
1616 uc->dev d1 (a1) B1
1617 new_uc->dev d2 (a2) B1
1618
1619 resolution: disable enable uc-dev on d2 since backends match
1620 we cannot enable two streams on two different devices if they
1621 share the same backend. e.g. if offload is on speaker device using
1622 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1623 using the same backend, offload must also be switched to voice-handset.
1624
1625case 5
1626 uc->dev d1 (a1) B1
1627 new_uc->dev d1 (a1), d2 (a2) B1
1628
1629 resolution: disable enable uc-dev on d2 since backends match
1630 we cannot enable two streams on two different devices if they
1631 share the same backend.
1632
1633case 6
1634 uc->dev d1 (a1) B1
1635 new_uc->dev d2 (a1) B2
1636
1637 resolution: no need to switch
1638
1639case 7
1640 uc->dev d1 (a1), d2 (a2) B1, B2
1641 new_uc->dev d1 (a1) B1
1642
1643 resolution: no need to switch
1644
Zhou Song4ba65882018-07-09 14:48:07 +08001645case 8
1646 uc->dev d1 (a1) B1
1647 new_uc->dev d11 (a1), d2 (a2) B1, B2
1648 resolution: compared to case 1, for this case, d1 and d11 are related
1649 then need to do the same as case 2 to siwtch to new uc
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301650
1651case 9
1652 uc->dev d1 (a1), d2(a2) B1 B2
1653 new_uc->dev d1 (a1), d22 (a2) B1, B2
1654 resolution: disable enable uc-dev on d2 since backends match
1655 we cannot enable two streams on two different devices if they
1656 share the same backend. This is special case for combo use case
1657 with a2dp and sco devices which uses same backend.
1658 e.g. speaker-a2dp and speaker-btsco
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001659*/
1660static snd_device_t derive_playback_snd_device(void * platform,
1661 struct audio_usecase *uc,
1662 struct audio_usecase *new_uc,
1663 snd_device_t new_snd_device)
1664{
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001665 struct listnode a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001666
1667 snd_device_t d1 = uc->out_snd_device;
1668 snd_device_t d2 = new_snd_device;
1669
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001670 list_init(&a1);
1671 list_init(&a2);
1672
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301673 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301674 case TRANSCODE_LOOPBACK_RX :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001675 assign_devices(&a1, &uc->stream.inout->out_config.device_list);
1676 assign_devices(&a2, &new_uc->stream.inout->out_config.device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301677 break;
1678 default :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001679 assign_devices(&a1, &uc->stream.out->device_list);
1680 assign_devices(&a2, &new_uc->stream.out->device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301681 break;
1682 }
1683
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001684 // Treat as a special case when a1 and a2 are not disjoint
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001685 if (!compare_devices(&a1, &a2) &&
1686 compare_devices_for_any_match(&a1 ,&a2)) {
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001687 snd_device_t d3[2];
1688 int num_devices = 0;
1689 int ret = platform_split_snd_device(platform,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001690 list_length(&a1) > 1 ? d1 : d2,
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001691 &num_devices,
1692 d3);
1693 if (ret < 0) {
1694 if (ret != -ENOSYS) {
1695 ALOGW("%s failed to split snd_device %d",
1696 __func__,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001697 list_length(&a1) > 1 ? d1 : d2);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001698 }
1699 goto end;
1700 }
1701
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001702 if (platform_check_backends_match(d3[0], d3[1])) {
1703 return d2; // case 5
1704 } else {
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301705 if ((list_length(&a1) > 1) && (list_length(&a2) > 1) &&
1706 platform_check_backends_match(d1, d2))
1707 return d2; //case 9
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001708 if (list_length(&a1) > 1)
Samyak Jaind826b502019-07-17 16:16:42 +05301709 return d1; //case 7
Garmond Leungb9eeba42018-09-18 11:10:41 -07001710 // check if d1 is related to any of d3's
1711 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001712 return d1; // case 1
1713 else
1714 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001715 }
1716 } else {
1717 if (platform_check_backends_match(d1, d2)) {
1718 return d2; // case 2, 4
1719 } else {
1720 return d1; // case 6, 3
1721 }
1722 }
1723
1724end:
1725 return d2; // return whatever was calculated before.
1726}
1727
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001728static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301729 struct audio_usecase *uc_info,
1730 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001731{
1732 struct listnode *node;
1733 struct audio_usecase *usecase;
1734 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301735 snd_device_t uc_derive_snd_device;
1736 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001737 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1738 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001739 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301740 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001741 /*
1742 * This function is to make sure that all the usecases that are active on
1743 * the hardware codec backend are always routed to any one device that is
1744 * handled by the hardware codec.
1745 * For example, if low-latency and deep-buffer usecases are currently active
1746 * on speaker and out_set_parameters(headset) is received on low-latency
1747 * output, then we have to make sure deep-buffer is also switched to headset,
1748 * because of the limitation that both the devices cannot be enabled
1749 * at the same time as they share the same backend.
1750 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001751 /*
1752 * This call is to check if we need to force routing for a particular stream
1753 * If there is a backend configuration change for the device when a
1754 * new stream starts, then ADM needs to be closed and re-opened with the new
1755 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001756 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001757 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001758 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1759 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301760 /* For a2dp device reconfigure all active sessions
1761 * with new AFE encoder format based on a2dp state
1762 */
1763 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301764 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device ||
1765 SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP == snd_device) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301766 audio_extn_a2dp_is_force_device_switch()) {
1767 force_routing = true;
1768 force_restart_session = true;
1769 }
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001770
1771 /*
1772 * Island cfg and power mode config needs to set before AFE port start.
1773 * Set force routing in case of voice device was enable before.
1774 */
1775 if (uc_info->type == VOICE_CALL &&
1776 voice_extn_is_voice_power_mode_supported() &&
1777 platform_check_and_update_island_power_status(adev->platform,
1778 uc_info,
1779 snd_device)) {
1780 force_routing = true;
1781 ALOGD("%s:becf: force routing %d for power mode supported device",
1782 __func__, force_routing);
1783 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301784 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1785
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001786 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001787 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001788 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001789 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1790 switch_device[i] = false;
1791
1792 list_for_each(node, &adev->usecase_list) {
1793 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001794
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301795 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1796 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301797 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301798 platform_get_snd_device_name(usecase->out_snd_device),
1799 platform_check_backends_match(snd_device, usecase->out_snd_device));
Rahul Sharma99770982019-03-06 17:05:26 +05301800 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
1801 (usecase->type != PCM_PASSTHROUGH)) {
Ashish Jain6a65b352017-03-21 17:24:40 +05301802 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1803 usecase, uc_info, snd_device);
1804 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001805 (is_codec_backend_out_device_type(&usecase->device_list) ||
1806 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1807 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_DEVICE) ||
1808 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_HEADSET) ||
1809 is_a2dp_out_device_type(&usecase->device_list) ||
1810 is_sco_out_device_type(&usecase->device_list)) &&
Ashish Jain6a65b352017-03-21 17:24:40 +05301811 ((force_restart_session) ||
1812 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301813 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1814 __func__, use_case_table[usecase->id],
1815 platform_get_snd_device_name(usecase->out_snd_device));
1816 disable_audio_route(adev, usecase);
1817 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301818 /* Enable existing usecase on derived playback device */
1819 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301820 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301821 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001822 }
1823 }
1824
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301825 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1826 num_uc_to_switch);
1827
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001828 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001829 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001830
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301831 /* Make sure the previous devices to be disabled first and then enable the
1832 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001833 list_for_each(node, &adev->usecase_list) {
1834 usecase = node_to_item(node, struct audio_usecase, list);
1835 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001836 /* Check if output sound device to be switched can be split and if any
1837 of the split devices match with derived sound device */
1838 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1839 &num_devices, split_snd_devices) == 0) {
1840 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
1841 for (i = 0; i < num_devices; i++) {
1842 /* Disable devices that do not match with derived sound device */
1843 if (split_snd_devices[i] != derive_snd_device[usecase->id])
1844 disable_snd_device(adev, split_snd_devices[i]);
1845 }
1846 } else {
1847 disable_snd_device(adev, usecase->out_snd_device);
1848 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001849 }
1850 }
1851
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001852 list_for_each(node, &adev->usecase_list) {
1853 usecase = node_to_item(node, struct audio_usecase, list);
1854 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001855 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1856 &num_devices, split_snd_devices) == 0) {
1857 /* Enable derived sound device only if it does not match with
1858 one of the split sound devices. This is because the matching
1859 sound device was not disabled */
1860 bool should_enable = true;
1861 for (i = 0; i < num_devices; i++) {
1862 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
1863 should_enable = false;
1864 break;
1865 }
1866 }
1867 if (should_enable)
1868 enable_snd_device(adev, derive_snd_device[usecase->id]);
1869 } else {
1870 enable_snd_device(adev, derive_snd_device[usecase->id]);
1871 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001872 }
1873 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001874
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001875 /* Re-route all the usecases on the shared backend other than the
1876 specified usecase to new snd devices */
1877 list_for_each(node, &adev->usecase_list) {
1878 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301879 /* Update the out_snd_device only before enabling the audio route */
1880 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301881 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301882 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301883 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301884 use_case_table[usecase->id],
1885 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001886 /* Update voc calibration before enabling VoIP route */
1887 if (usecase->type == VOIP_CALL)
1888 status = platform_switch_voice_call_device_post(adev->platform,
Eric Laurent637e2d42018-11-15 12:24:31 -08001889 usecase->out_snd_device,
1890 platform_get_input_snd_device(
1891 adev->platform, NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05301892 &uc_info->device_list,
1893 usecase->type));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301894 enable_audio_route(adev, usecase);
Sujin Panicker390724d2019-04-26 10:43:36 +05301895 if (usecase->stream.out && usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
kunleiz46c47dd2018-03-19 16:28:09 +08001896 out_set_voip_volume(&usecase->stream.out->stream,
1897 usecase->stream.out->volume_l,
1898 usecase->stream.out->volume_r);
1899 }
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301900 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001901 }
1902 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001903 }
1904}
1905
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301906static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001907 struct audio_usecase *uc_info,
1908 snd_device_t snd_device)
1909{
1910 struct listnode *node;
1911 struct audio_usecase *usecase;
1912 bool switch_device[AUDIO_USECASE_MAX];
1913 int i, num_uc_to_switch = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001914 int backend_check_cond = is_codec_backend_out_device_type(&uc_info->device_list);
kunleiz5cd52b82016-11-07 17:22:52 +08001915 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001916
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301917 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1918 snd_device);
1919 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301920
1921 /*
1922 * Make sure out devices is checked against out codec backend device and
1923 * also in devices against in codec backend. Checking out device against in
1924 * codec backend or vice versa causes issues.
1925 */
1926 if (uc_info->type == PCM_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001927 backend_check_cond = is_codec_backend_in_device_type(&uc_info->device_list);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001928
1929 /*
1930 * Island cfg and power mode config needs to set before AFE port start.
1931 * Set force routing in case of voice device was enable before.
1932 */
1933
1934 if (uc_info->type == VOICE_CALL &&
1935 voice_extn_is_voice_power_mode_supported() &&
1936 platform_check_and_update_island_power_status(adev->platform,
1937 uc_info,
1938 snd_device)) {
1939 force_routing = true;
1940 ALOGD("%s:becf: force routing %d for power mode supported device",
1941 __func__, force_routing);
1942 }
1943
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001944 /*
1945 * This function is to make sure that all the active capture usecases
1946 * are always routed to the same input sound device.
1947 * For example, if audio-record and voice-call usecases are currently
1948 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1949 * is received for voice call then we have to make sure that audio-record
1950 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1951 * because of the limitation that two devices cannot be enabled
1952 * at the same time if they share the same backend.
1953 */
1954 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1955 switch_device[i] = false;
1956
1957 list_for_each(node, &adev->usecase_list) {
1958 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301959 /*
1960 * TODO: Enhance below condition to handle BT sco/USB multi recording
1961 */
Jaideep Sharma477917f2020-03-13 18:13:33 +05301962
1963 bool capture_uc_needs_routing = usecase->type != PCM_PLAYBACK && (usecase != uc_info &&
1964 (usecase->in_snd_device != snd_device || force_routing));
1965 bool call_proxy_snd_device = platform_is_call_proxy_snd_device(snd_device) ||
1966 platform_is_call_proxy_snd_device(usecase->in_snd_device);
1967 if (capture_uc_needs_routing && !call_proxy_snd_device &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001968 ((backend_check_cond &&
1969 (is_codec_backend_in_device_type(&usecase->device_list) ||
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08001970 (usecase->type == VOIP_CALL))) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08001971 ((uc_info->type == VOICE_CALL &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001972 is_single_device_type_equal(&usecase->device_list,
1973 AUDIO_DEVICE_IN_VOICE_CALL)) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08001974 platform_check_backends_match(snd_device,\
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001975 usecase->in_snd_device))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001976 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05301977 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..",
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001978 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001979 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001980 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001981 switch_device[usecase->id] = true;
1982 num_uc_to_switch++;
1983 }
1984 }
1985
1986 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001987 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001988
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301989 /* Make sure the previous devices to be disabled first and then enable the
1990 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001991 list_for_each(node, &adev->usecase_list) {
1992 usecase = node_to_item(node, struct audio_usecase, list);
1993 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001994 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001995 }
1996 }
1997
1998 list_for_each(node, &adev->usecase_list) {
1999 usecase = node_to_item(node, struct audio_usecase, list);
2000 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002001 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002002 }
2003 }
2004
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002005 /* Re-route all the usecases on the shared backend other than the
2006 specified usecase to new snd devices */
2007 list_for_each(node, &adev->usecase_list) {
2008 usecase = node_to_item(node, struct audio_usecase, list);
2009 /* Update the in_snd_device only before enabling the audio route */
2010 if (switch_device[usecase->id] ) {
2011 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08002012 if (usecase->type != VOICE_CALL) {
2013 /* Update voc calibration before enabling VoIP route */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302014 if (usecase->type == VOIP_CALL) {
2015 snd_device_t voip_snd_device;
2016 voip_snd_device = platform_get_output_snd_device(adev->platform,
2017 uc_info->stream.out,
2018 usecase->type);
kunleiz5cd52b82016-11-07 17:22:52 +08002019 status = platform_switch_voice_call_device_post(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302020 voip_snd_device,
kunleiz5cd52b82016-11-07 17:22:52 +08002021 usecase->in_snd_device);
Jaideep Sharma477917f2020-03-13 18:13:33 +05302022 }
Avinash Vaish71a8b972014-07-24 15:36:33 +05302023 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08002024 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002025 }
2026 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002027 }
2028}
2029
Mingming Yin3a941d42016-02-17 18:08:05 -08002030static void reset_hdmi_sink_caps(struct stream_out *out) {
2031 int i = 0;
2032
2033 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
2034 out->supported_channel_masks[i] = 0;
2035 }
2036 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
2037 out->supported_formats[i] = 0;
2038 }
2039 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
2040 out->supported_sample_rates[i] = 0;
2041 }
2042}
2043
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002044/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08002045static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002046{
Mingming Yin3a941d42016-02-17 18:08:05 -08002047 int ret = 0, i = 0, j = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002048 int channels = platform_edid_get_max_channels_v2(out->dev->platform,
2049 out->extconn.cs.controller,
2050 out->extconn.cs.stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002051
Mingming Yin3a941d42016-02-17 18:08:05 -08002052 reset_hdmi_sink_caps(out);
2053
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002054 /* Cache ext disp type */
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002055 ret = platform_get_ext_disp_type_v2(adev->platform,
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002056 out->extconn.cs.controller,
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002057 out->extconn.cs.stream);
2058 if(ret < 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002059 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07002060 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002061 }
2062
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002063 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002064 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08002065 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002066 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08002067 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
2068 case 6:
2069 ALOGV("%s: HDMI supports 5.1 channels", __func__);
2070 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
2071 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
2072 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
2073 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
2074 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002075 break;
2076 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08002077 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002078 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002079 break;
2080 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002081
2082 // check channel format caps
2083 i = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002084 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_AC3,
2085 out->extconn.cs.controller,
2086 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002087 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
2088 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
2089 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
2090 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
2091 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
2092 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
2093 }
2094
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002095 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD,
2096 out->extconn.cs.controller,
2097 out->extconn.cs.stream)) {
Ben Romberger1aaaf862017-04-06 17:49:46 -07002098 ALOGV(":%s HDMI supports TRUE HD format", __func__);
2099 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
2100 }
2101
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002102 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS,
2103 out->extconn.cs.controller,
2104 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002105 ALOGV(":%s HDMI supports DTS format", __func__);
2106 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
2107 }
2108
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002109 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS_HD,
2110 out->extconn.cs.controller,
2111 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002112 ALOGV(":%s HDMI supports DTS HD format", __func__);
2113 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
2114 }
2115
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002116 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_IEC61937,
2117 out->extconn.cs.controller,
2118 out->extconn.cs.stream)) {
Naresh Tanniru928f0862017-04-07 16:44:23 -07002119 ALOGV(":%s HDMI supports IEC61937 format", __func__);
2120 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
2121 }
2122
Mingming Yin3a941d42016-02-17 18:08:05 -08002123
2124 // check sample rate caps
2125 i = 0;
2126 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002127 if (platform_is_edid_supported_sample_rate_v2(out->dev->platform, out_hdmi_sample_rates[j],
2128 out->extconn.cs.controller,
2129 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002130 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
2131 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
2132 }
2133 }
2134
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002135 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002136}
2137
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002138static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
2139 uint32_t *supported_sample_rates __unused,
2140 uint32_t max_rates __unused)
2141{
2142 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
2143 supported_sample_rates,
2144 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05302145 ssize_t i = 0;
2146
2147 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002148 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
2149 supported_sample_rates[i]);
2150 }
2151 return count;
2152}
2153
2154static inline int read_usb_sup_channel_masks(bool is_playback,
2155 audio_channel_mask_t *supported_channel_masks,
2156 uint32_t max_masks)
2157{
2158 int channels = audio_extn_usb_get_max_channels(is_playback);
2159 int channel_count;
2160 uint32_t num_masks = 0;
2161 if (channels > MAX_HIFI_CHANNEL_COUNT)
2162 channels = MAX_HIFI_CHANNEL_COUNT;
2163
2164 if (is_playback) {
Eric Laurent68a87112019-05-01 18:07:29 -07002165 // start from 2 channels as framework currently doesn't support mono.
2166 if (channels >= FCC_2) {
2167 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(FCC_2);
2168 }
2169 for (channel_count = FCC_2;
2170 channel_count <= channels && num_masks < max_masks;
2171 ++channel_count) {
2172 supported_channel_masks[num_masks++] =
2173 audio_channel_mask_for_index_assignment_from_count(channel_count);
2174 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002175 } else {
vincenttewf51c94e2019-05-07 10:28:53 +08002176 // For capture we report all supported channel masks from 1 channel up.
2177 channel_count = MIN_CHANNEL_COUNT;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002178 // audio_channel_in_mask_from_count() does the right conversion to either positional or
2179 // indexed mask
Eric Laurent68a87112019-05-01 18:07:29 -07002180 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
2181 audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
2182 if (channel_count <= FCC_2) {
2183 mask = audio_channel_in_mask_from_count(channel_count);
2184 supported_channel_masks[num_masks++] = mask;
2185 }
2186 const audio_channel_mask_t index_mask =
2187 audio_channel_mask_for_index_assignment_from_count(channel_count);
2188 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
2189 supported_channel_masks[num_masks++] = index_mask;
2190 }
2191 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002192 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302193
vincenttewf51c94e2019-05-07 10:28:53 +08002194 for (size_t i = 0; i < num_masks; ++i) {
2195 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
2196 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302197 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002198 return num_masks;
2199}
2200
2201static inline int read_usb_sup_formats(bool is_playback __unused,
2202 audio_format_t *supported_formats,
2203 uint32_t max_formats __unused)
2204{
2205 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
2206 switch (bitwidth) {
2207 case 24:
2208 // XXX : usb.c returns 24 for s24 and s24_le?
2209 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
2210 break;
2211 case 32:
2212 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
2213 break;
2214 case 16:
2215 default :
2216 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
2217 break;
2218 }
2219 ALOGV("%s: %s supported format %d", __func__,
2220 is_playback ? "P" : "C", bitwidth);
2221 return 1;
2222}
2223
2224static inline int read_usb_sup_params_and_compare(bool is_playback,
2225 audio_format_t *format,
2226 audio_format_t *supported_formats,
2227 uint32_t max_formats,
2228 audio_channel_mask_t *mask,
2229 audio_channel_mask_t *supported_channel_masks,
2230 uint32_t max_masks,
2231 uint32_t *rate,
2232 uint32_t *supported_sample_rates,
2233 uint32_t max_rates) {
2234 int ret = 0;
2235 int num_formats;
2236 int num_masks;
2237 int num_rates;
2238 int i;
2239
2240 num_formats = read_usb_sup_formats(is_playback, supported_formats,
2241 max_formats);
2242 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
2243 max_masks);
2244
2245 num_rates = read_usb_sup_sample_rates(is_playback,
2246 supported_sample_rates, max_rates);
2247
2248#define LUT(table, len, what, dflt) \
2249 for (i=0; i<len && (table[i] != what); i++); \
2250 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
2251
2252 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
2253 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
2254 LUT(supported_sample_rates, num_rates, *rate, 0);
2255
2256#undef LUT
2257 return ret < 0 ? -EINVAL : 0; // HACK TBD
2258}
2259
Alexy Josephb1379942016-01-29 15:49:38 -08002260audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002261 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002262{
2263 struct audio_usecase *usecase;
2264 struct listnode *node;
2265
2266 list_for_each(node, &adev->usecase_list) {
2267 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002268 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002269 ALOGV("%s: usecase id %d", __func__, usecase->id);
2270 return usecase->id;
2271 }
2272 }
2273 return USECASE_INVALID;
2274}
2275
Alexy Josephb1379942016-01-29 15:49:38 -08002276struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002277 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002278{
2279 struct audio_usecase *usecase;
2280 struct listnode *node;
2281
2282 list_for_each(node, &adev->usecase_list) {
2283 usecase = node_to_item(node, struct audio_usecase, list);
2284 if (usecase->id == uc_id)
2285 return usecase;
2286 }
2287 return NULL;
2288}
2289
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302290/*
2291 * is a true native playback active
2292 */
2293bool audio_is_true_native_stream_active(struct audio_device *adev)
2294{
2295 bool active = false;
2296 int i = 0;
2297 struct listnode *node;
2298
2299 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
2300 ALOGV("%s:napb: not in true mode or non hdphones device",
2301 __func__);
2302 active = false;
2303 goto exit;
2304 }
2305
2306 list_for_each(node, &adev->usecase_list) {
2307 struct audio_usecase *uc;
2308 uc = node_to_item(node, struct audio_usecase, list);
2309 struct stream_out *curr_out =
2310 (struct stream_out*) uc->stream.out;
2311
2312 if (curr_out && PCM_PLAYBACK == uc->type) {
2313 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
2314 "(%d) device %s", __func__, i++, use_case_table[uc->id],
2315 uc->id, curr_out->sample_rate,
2316 curr_out->bit_width,
2317 platform_get_snd_device_name(uc->out_snd_device));
2318
2319 if (is_offload_usecase(uc->id) &&
2320 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
2321 active = true;
2322 ALOGD("%s:napb:native stream detected", __func__);
2323 }
2324 }
2325 }
2326exit:
2327 return active;
2328}
2329
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002330uint32_t adev_get_dsp_bit_width_enforce_mode()
2331{
2332 if (adev == NULL) {
2333 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
2334 return 0;
2335 }
2336 return adev->dsp_bit_width_enforce_mode;
2337}
2338
2339static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
2340{
2341 char value[PROPERTY_VALUE_MAX];
2342 int trial;
2343 uint32_t dsp_bit_width_enforce_mode = 0;
2344
2345 if (!mixer) {
2346 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
2347 __func__);
2348 return 0;
2349 }
2350
2351 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
2352 value, NULL) > 0) {
2353 trial = atoi(value);
2354 switch (trial) {
2355 case 16:
2356 dsp_bit_width_enforce_mode = 16;
2357 break;
2358 case 24:
2359 dsp_bit_width_enforce_mode = 24;
2360 break;
2361 case 32:
2362 dsp_bit_width_enforce_mode = 32;
2363 break;
2364 default:
2365 dsp_bit_width_enforce_mode = 0;
2366 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
2367 break;
2368 }
2369 }
2370
2371 return dsp_bit_width_enforce_mode;
2372}
2373
2374static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
2375 uint32_t enforce_mode,
2376 bool enable)
2377{
2378 struct mixer_ctl *ctl = NULL;
2379 const char *mixer_ctl_name = "ASM Bit Width";
2380 uint32_t asm_bit_width_mode = 0;
2381
2382 if (enforce_mode == 0) {
2383 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
2384 return;
2385 }
2386
2387 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
2388 if (!ctl) {
2389 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2390 __func__, mixer_ctl_name);
2391 return;
2392 }
2393
2394 if (enable)
2395 asm_bit_width_mode = enforce_mode;
2396 else
2397 asm_bit_width_mode = 0;
2398
2399 ALOGV("%s DSP bit width feature status is %d width=%d",
2400 __func__, enable, asm_bit_width_mode);
2401 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2402 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2403 asm_bit_width_mode);
2404
2405 return;
2406}
2407
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302408/*
2409 * if native DSD playback active
2410 */
2411bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2412{
2413 bool active = false;
2414 struct listnode *node = NULL;
2415 struct audio_usecase *uc = NULL;
2416 struct stream_out *curr_out = NULL;
2417
2418 list_for_each(node, &adev->usecase_list) {
2419 uc = node_to_item(node, struct audio_usecase, list);
2420 curr_out = (struct stream_out*) uc->stream.out;
2421
2422 if (curr_out && PCM_PLAYBACK == uc->type &&
2423 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2424 active = true;
2425 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302426 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302427 }
2428 }
2429 return active;
2430}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302431
2432static bool force_device_switch(struct audio_usecase *usecase)
2433{
2434 bool ret = false;
2435 bool is_it_true_mode = false;
2436
Zhou Song30f2c3e2018-02-08 14:02:15 +08002437 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302438 usecase->type == TRANSCODE_LOOPBACK_RX ||
2439 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002440 return false;
2441 }
2442
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002443 if(usecase->stream.out == NULL) {
2444 ALOGE("%s: stream.out is NULL", __func__);
2445 return false;
2446 }
2447
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302448 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002449 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002450 (compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADSET) ||
2451 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADPHONE))) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302452 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2453 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2454 (!is_it_true_mode && adev->native_playback_enabled)){
2455 ret = true;
2456 ALOGD("napb: time to toggle native mode");
2457 }
2458 }
2459
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302460 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302461 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2462 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002463 if(is_a2dp_out_device_type(&usecase->stream.out->device_list) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302464 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302465 ALOGD("Force a2dp device switch to update new encoder config");
2466 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002467 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302468
Florian Pfister1a84f312018-07-19 14:38:18 +02002469 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302470 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2471 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002472 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302473 return ret;
2474}
2475
Aalique Grahame22e49102018-12-18 14:23:57 -08002476static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2477{
2478 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2479}
2480
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302481bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2482{
2483 bool ret=false;
2484 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
Zhou Song5657f492019-08-07 11:30:39 +08002485 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
2486 out_snd_device == SND_DEVICE_OUT_BT_SCO_SWB) ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302487 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2488 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
Zhou Song5657f492019-08-07 11:30:39 +08002489 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302490 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
Mingshu Pang16093502020-04-20 11:21:16 +08002491 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC ||
2492 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC)
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302493 ret = true;
2494
2495 return ret;
2496}
2497
2498bool is_a2dp_device(snd_device_t out_snd_device)
2499{
2500 bool ret=false;
2501 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2502 ret = true;
2503
2504 return ret;
2505}
2506
2507bool is_bt_soc_on(struct audio_device *adev)
2508{
2509 struct mixer_ctl *ctl;
2510 char *mixer_ctl_name = "BT SOC status";
2511 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2512 bool bt_soc_status = true;
2513 if (!ctl) {
2514 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2515 __func__, mixer_ctl_name);
2516 /*This is to ensure we dont break targets which dont have the kernel change*/
2517 return true;
2518 }
2519 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2520 ALOGD("BT SOC status: %d",bt_soc_status);
2521 return bt_soc_status;
2522}
2523
Zhou Song331c8e52019-08-26 14:16:12 +08002524static int configure_btsco_sample_rate(snd_device_t snd_device)
2525{
2526 struct mixer_ctl *ctl = NULL;
2527 struct mixer_ctl *ctl_sr_rx = NULL, *ctl_sr_tx = NULL, *ctl_sr = NULL;
2528 char *rate_str = NULL;
2529 bool is_rx_dev = true;
2530
2531 if (is_btsco_device(snd_device, snd_device)) {
2532 ctl_sr_tx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate TX");
2533 ctl_sr_rx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate RX");
2534 if (!ctl_sr_tx || !ctl_sr_rx) {
2535 ctl_sr = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate");
2536 if (!ctl_sr)
2537 return -ENOSYS;
2538 }
2539
2540 switch (snd_device) {
2541 case SND_DEVICE_OUT_BT_SCO:
2542 rate_str = "KHZ_8";
2543 break;
2544 case SND_DEVICE_IN_BT_SCO_MIC_NREC:
2545 case SND_DEVICE_IN_BT_SCO_MIC:
2546 rate_str = "KHZ_8";
2547 is_rx_dev = false;
2548 break;
2549 case SND_DEVICE_OUT_BT_SCO_WB:
2550 rate_str = "KHZ_16";
2551 break;
2552 case SND_DEVICE_IN_BT_SCO_MIC_WB_NREC:
2553 case SND_DEVICE_IN_BT_SCO_MIC_WB:
2554 rate_str = "KHZ_16";
2555 is_rx_dev = false;
2556 break;
2557 default:
2558 return 0;
2559 }
2560
2561 ctl = (ctl_sr == NULL) ? (is_rx_dev ? ctl_sr_rx : ctl_sr_tx) : ctl_sr;
2562 if (mixer_ctl_set_enum_by_string(ctl, rate_str) != 0)
2563 return -ENOSYS;
2564 }
2565 return 0;
2566}
2567
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302568int out_standby_l(struct audio_stream *stream);
2569
Eric Laurent637e2d42018-11-15 12:24:31 -08002570struct stream_in *adev_get_active_input(const struct audio_device *adev)
2571{
2572 struct listnode *node;
2573 struct stream_in *last_active_in = NULL;
2574
2575 /* Get last added active input.
2576 * TODO: We may use a priority mechanism to pick highest priority active source */
2577 list_for_each(node, &adev->usecase_list)
2578 {
2579 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2580 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL)
2581 last_active_in = usecase->stream.in;
2582 }
2583
2584 return last_active_in;
2585}
2586
2587struct stream_in *get_voice_communication_input(const struct audio_device *adev)
2588{
2589 struct listnode *node;
2590
2591 /* First check active inputs with voice communication source and then
2592 * any input if audio mode is in communication */
2593 list_for_each(node, &adev->usecase_list)
2594 {
2595 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2596 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
2597 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
2598 return usecase->stream.in;
2599 }
2600 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION)
2601 return adev_get_active_input(adev);
2602
2603 return NULL;
2604}
2605
Carter Hsu2e429db2019-05-14 18:50:52 +08002606/*
2607 * Aligned with policy.h
2608 */
2609static inline int source_priority(int inputSource)
2610{
2611 switch (inputSource) {
2612 case AUDIO_SOURCE_VOICE_COMMUNICATION:
2613 return 9;
2614 case AUDIO_SOURCE_CAMCORDER:
2615 return 8;
2616 case AUDIO_SOURCE_VOICE_PERFORMANCE:
2617 return 7;
2618 case AUDIO_SOURCE_UNPROCESSED:
2619 return 6;
2620 case AUDIO_SOURCE_MIC:
2621 return 5;
2622 case AUDIO_SOURCE_ECHO_REFERENCE:
2623 return 4;
2624 case AUDIO_SOURCE_FM_TUNER:
2625 return 3;
2626 case AUDIO_SOURCE_VOICE_RECOGNITION:
2627 return 2;
2628 case AUDIO_SOURCE_HOTWORD:
2629 return 1;
2630 default:
2631 break;
2632 }
2633 return 0;
2634}
2635
2636static struct stream_in *get_priority_input(struct audio_device *adev)
2637{
2638 struct listnode *node;
2639 struct audio_usecase *usecase;
2640 int last_priority = 0, priority;
2641 struct stream_in *priority_in = NULL;
2642 struct stream_in *in;
2643
2644 list_for_each(node, &adev->usecase_list) {
2645 usecase = node_to_item(node, struct audio_usecase, list);
2646 if (usecase->type == PCM_CAPTURE) {
2647 in = usecase->stream.in;
2648 if (!in)
2649 continue;
2650 priority = source_priority(in->source);
2651
2652 if (priority > last_priority) {
2653 last_priority = priority;
2654 priority_in = in;
2655 }
2656 }
2657 }
2658 return priority_in;
2659}
2660
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002661int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002662{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002663 snd_device_t out_snd_device = SND_DEVICE_NONE;
2664 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002665 struct audio_usecase *usecase = NULL;
2666 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002667 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002668 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302669 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002670 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002671 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002672
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302673 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2674
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002675 usecase = get_usecase_from_list(adev, uc_id);
2676 if (usecase == NULL) {
2677 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2678 return -EINVAL;
2679 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002680
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002681 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002682 (usecase->type == VOIP_CALL) ||
2683 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302684 if(usecase->stream.out == NULL) {
2685 ALOGE("%s: stream.out is NULL", __func__);
2686 return -EINVAL;
2687 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002688 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS)) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002689 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev,
2690 uc_id);
2691 in_snd_device = audio_extn_auto_hal_get_input_snd_device(adev,
2692 uc_id);
2693 } else {
2694 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302695 usecase->stream.out, usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002696 in_snd_device = platform_get_input_snd_device(adev->platform,
2697 NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302698 &usecase->stream.out->device_list,
2699 usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002700 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002701 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302702 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302703 if (usecase->stream.inout == NULL) {
2704 ALOGE("%s: stream.inout is NULL", __func__);
2705 return -EINVAL;
2706 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002707 assign_devices(&stream_out.device_list, &usecase->stream.inout->out_config.device_list);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302708 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2709 stream_out.format = usecase->stream.inout->out_config.format;
2710 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
Jaideep Sharma477917f2020-03-13 18:13:33 +05302711 out_snd_device = platform_get_output_snd_device(adev->platform, &stream_out, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002712 assign_devices(&usecase->device_list,
2713 &usecase->stream.inout->out_config.device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302714 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2715 if (usecase->stream.inout == NULL) {
2716 ALOGE("%s: stream.inout is NULL", __func__);
2717 return -EINVAL;
2718 }
Manisha Agarwal03297972020-04-17 15:36:55 +05302719 struct listnode out_devices;
2720 list_init(&out_devices);
2721 in_snd_device = platform_get_input_snd_device(adev->platform, NULL,
2722 &out_devices, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002723 assign_devices(&usecase->device_list,
2724 &usecase->stream.inout->in_config.device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002725 } else {
2726 /*
2727 * If the voice call is active, use the sound devices of voice call usecase
2728 * so that it would not result any device switch. All the usecases will
2729 * be switched to new device when select_devices() is called for voice call
2730 * usecase. This is to avoid switching devices for voice call when
2731 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002732 * choose voice call device only if the use case device is
2733 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002734 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002735 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002736 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002737 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002738 if ((vc_usecase) && ((is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2739 is_codec_backend_out_device_type(&usecase->device_list)) ||
2740 (is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2741 is_codec_backend_in_device_type(&usecase->device_list)) ||
2742 is_single_device_type_equal(&vc_usecase->device_list,
2743 AUDIO_DEVICE_OUT_HEARING_AID) ||
2744 is_single_device_type_equal(&usecase->device_list,
Robert Lee8a6aaf32019-09-20 16:40:19 +08002745 AUDIO_DEVICE_IN_VOICE_CALL) ||
2746 (is_single_device_type_equal(&usecase->device_list,
2747 AUDIO_DEVICE_IN_USB_HEADSET) &&
2748 is_single_device_type_equal(&vc_usecase->device_list,
2749 AUDIO_DEVICE_OUT_USB_HEADSET)))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002750 in_snd_device = vc_usecase->in_snd_device;
2751 out_snd_device = vc_usecase->out_snd_device;
2752 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002753 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002754 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002755 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002756 if ((voip_usecase != NULL) &&
2757 (usecase->type == PCM_PLAYBACK) &&
2758 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002759 out_snd_device_backend_match = platform_check_backends_match(
2760 voip_usecase->out_snd_device,
2761 platform_get_output_snd_device(
2762 adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302763 usecase->stream.out, usecase->type));
yidongh02ef86f2017-04-21 15:36:04 +08002764 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002765 if ((voip_usecase) && (is_codec_backend_out_device_type(&voip_usecase->device_list) &&
2766 (is_codec_backend_out_device_type(&usecase->device_list) ||
2767 is_codec_backend_in_device_type(&usecase->device_list)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002768 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002769 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002770 in_snd_device = voip_usecase->in_snd_device;
2771 out_snd_device = voip_usecase->out_snd_device;
2772 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002773 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002774 hfp_ucid = audio_extn_hfp_get_usecase();
2775 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002776 if ((hfp_usecase) && is_codec_backend_out_device_type(&hfp_usecase->device_list)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002777 in_snd_device = hfp_usecase->in_snd_device;
2778 out_snd_device = hfp_usecase->out_snd_device;
2779 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002780 }
2781 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302782 if (usecase->stream.out == NULL) {
2783 ALOGE("%s: stream.out is NULL", __func__);
2784 return -EINVAL;
2785 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002786 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002787 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002788 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002789 struct stream_out *voip_out = adev->primary_output;
2790 struct stream_in *voip_in = get_voice_communication_input(adev);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002791 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS))
Guodong Hu267bdf82019-08-12 19:22:32 +08002792 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev, uc_id);
2793 else
2794 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302795 usecase->stream.out,
2796 usecase->type);
kunleizdcf967a2018-08-07 17:09:11 +08002797 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizdcf967a2018-08-07 17:09:11 +08002798
Eric Laurent637e2d42018-11-15 12:24:31 -08002799 if (voip_usecase)
2800 voip_out = voip_usecase->stream.out;
2801
2802 if (usecase->stream.out == voip_out && voip_in != NULL)
2803 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002804 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002805 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302806 if (usecase->stream.in == NULL) {
2807 ALOGE("%s: stream.in is NULL", __func__);
2808 return -EINVAL;
2809 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002810 assign_devices(&usecase->device_list, &usecase->stream.in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002811 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002812 if (in_snd_device == SND_DEVICE_NONE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002813 struct listnode out_devices;
Eric Laurent637e2d42018-11-15 12:24:31 -08002814 struct stream_in *voip_in = get_voice_communication_input(adev);
Carter Hsu2e429db2019-05-14 18:50:52 +08002815 struct stream_in *priority_in = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08002816
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002817 list_init(&out_devices);
Eric Laurent637e2d42018-11-15 12:24:31 -08002818 if (voip_in != NULL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002819 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
2820 USECASE_AUDIO_PLAYBACK_VOIP);
2821
Carter Hsu2e429db2019-05-14 18:50:52 +08002822 usecase->stream.in->enable_ec_port = false;
2823
Zhou Song62ea0282020-03-22 19:53:01 +08002824 bool is_ha_usecase = adev->ha_proxy_enable ?
2825 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY2 :
2826 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY;
2827 if (is_ha_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002828 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_TELEPHONY_TX, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002829 } else if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002830 assign_devices(&out_devices, &voip_usecase->stream.out->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002831 } else if (adev->primary_output &&
2832 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002833 assign_devices(&out_devices, &adev->primary_output->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002834 } else {
2835 /* forcing speaker o/p device to get matching i/p pair
2836 in case o/p is not routed from same primary HAL */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002837 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002838 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002839 priority_in = voip_in;
2840 } else {
2841 /* get the input with the highest priority source*/
2842 priority_in = get_priority_input(adev);
2843
2844 if (!priority_in)
2845 priority_in = usecase->stream.in;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002846 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002847
Eric Laurent637e2d42018-11-15 12:24:31 -08002848 in_snd_device = platform_get_input_snd_device(adev->platform,
Carter Hsu2e429db2019-05-14 18:50:52 +08002849 priority_in,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302850 &out_devices,
2851 usecase->type);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002852 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002853 }
2854 }
2855
2856 if (out_snd_device == usecase->out_snd_device &&
2857 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302858
2859 if (!force_device_switch(usecase))
2860 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002861 }
2862
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002863 if (!compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS) &&
Guodong Hu267bdf82019-08-12 19:22:32 +08002864 ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002865 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready()))) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002866 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2867 return 0;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302868 }
2869
Aalique Grahame22e49102018-12-18 14:23:57 -08002870 if (out_snd_device != SND_DEVICE_NONE &&
2871 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
2872 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2873 __func__,
2874 use_case_table[uc_id],
2875 adev->last_logged_snd_device[uc_id][0],
2876 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
2877 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
2878 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
2879 -1,
2880 out_snd_device,
2881 platform_get_snd_device_name(out_snd_device),
2882 platform_get_snd_device_acdb_id(out_snd_device));
2883 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
2884 }
2885 if (in_snd_device != SND_DEVICE_NONE &&
2886 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
2887 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2888 __func__,
2889 use_case_table[uc_id],
2890 adev->last_logged_snd_device[uc_id][1],
2891 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
2892 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
2893 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
2894 -1,
2895 in_snd_device,
2896 platform_get_snd_device_name(in_snd_device),
2897 platform_get_snd_device_acdb_id(in_snd_device));
2898 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
2899 }
2900
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002901
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002902 /*
2903 * Limitation: While in call, to do a device switch we need to disable
2904 * and enable both RX and TX devices though one of them is same as current
2905 * device.
2906 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002907 if ((usecase->type == VOICE_CALL) &&
2908 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2909 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002910 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002911 }
2912
2913 if (((usecase->type == VOICE_CALL) ||
2914 (usecase->type == VOIP_CALL)) &&
2915 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2916 /* Disable sidetone only if voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302917 if (voice_is_call_state_active_in_call(adev) ||
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002918 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002919 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002920
2921 /* Disable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302922 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002923 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002924 }
2925
Aalique Grahame22e49102018-12-18 14:23:57 -08002926 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
2927 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02002928 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302929 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08002930 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
2931 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
2932 else
2933 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302934 }
2935
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002936 /* Disable current sound devices */
2937 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002938 disable_audio_route(adev, usecase);
2939 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002940 }
2941
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002942 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002943 disable_audio_route(adev, usecase);
2944 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002945 }
2946
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002947 /* Applicable only on the targets that has external modem.
2948 * New device information should be sent to modem before enabling
2949 * the devices to reduce in-call device switch time.
2950 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002951 if ((usecase->type == VOICE_CALL) &&
2952 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2953 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002954 status = platform_switch_voice_call_enable_device_config(adev->platform,
2955 out_snd_device,
2956 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002957 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002958
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002959 /* Enable new sound devices */
2960 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002961 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302962 if (platform_check_codec_asrc_support(adev->platform))
2963 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002964 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002965 }
2966
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002967 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302968 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002969 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002970 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002971
Avinash Vaish71a8b972014-07-24 15:36:33 +05302972 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002973 status = platform_switch_voice_call_device_post(adev->platform,
2974 out_snd_device,
2975 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05302976 enable_audio_route_for_voice_usecases(adev, usecase);
2977 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002978
sangwoo170731f2013-06-08 15:36:36 +09002979 usecase->in_snd_device = in_snd_device;
2980 usecase->out_snd_device = out_snd_device;
2981
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302982 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2983 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302984 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002985 if ((24 == usecase->stream.out->bit_width) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002986 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_SPEAKER)) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002987 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2988 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2989 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2990 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2991 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2992 /*
2993 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2994 * configured device sample rate, if not update the COPP rate to be equal to the
2995 * device sample rate, else open COPP at stream sample rate
2996 */
2997 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
2998 usecase->stream.out->sample_rate,
2999 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05303000 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
Preetam Singh Ranawat590d0432019-09-30 14:39:47 +05303001 out_snd_device != SND_DEVICE_OUT_HEADPHONES &&
3002 out_snd_device != SND_DEVICE_OUT_HEADPHONES_HIFI_FILTER &&
Ashish Jain4826f6c2017-02-06 13:33:20 +05303003 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003004 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
3005 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
3006 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3007 }
Weiyin Jiangcdece202019-07-08 16:13:16 +08003008 }
3009 enable_audio_route(adev, usecase);
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003010
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08003011 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08003012
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003013 /* If input stream is already running then effect needs to be
3014 applied on the new input device that's being enabled here. */
Eric Laurent637e2d42018-11-15 12:24:31 -08003015 if (in_snd_device != SND_DEVICE_NONE)
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003016 check_and_enable_effect(adev);
3017
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003018 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003019 /* Enable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303020 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003021 voice_check_and_update_aanc_path(adev, out_snd_device, true);
3022
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003023 /* Enable sidetone only if other voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303024 if (voice_is_call_state_active_in_call(adev) ||
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003025 voice_extn_compress_voip_is_started(adev))
3026 voice_set_sidetone(adev, out_snd_device, true);
3027 }
3028
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003029 /* Applicable only on the targets that has external modem.
3030 * Enable device command should be sent to modem only after
3031 * enabling voice call mixer controls
3032 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07003033 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003034 status = platform_switch_voice_call_usecase_route_post(adev->platform,
3035 out_snd_device,
3036 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303037
3038 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003039 struct stream_in *in = adev_get_active_input(adev);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303040 if (usecase->type == VOIP_CALL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003041 if (in != NULL && !in->standby) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303042 if (is_bt_soc_on(adev) == false){
3043 ALOGD("BT SCO MIC disconnected while in connection");
Eric Laurent637e2d42018-11-15 12:24:31 -08003044 if (in->pcm != NULL)
3045 pcm_stop(in->pcm);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303046 }
3047 }
3048 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
3049 && usecase->stream.out->started) {
3050 if (is_bt_soc_on(adev) == false) {
3051 ALOGD("BT SCO/A2DP disconnected while in connection");
3052 out_standby_l(&usecase->stream.out->stream.common);
3053 }
3054 }
3055 } else if ((usecase->stream.out != NULL) &&
3056 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05303057 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
3058 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Weiyin Jiang0d373242019-07-25 13:18:17 +08003059 (usecase->type != PCM_CAPTURE) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303060 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 }
3067
Yung Ti Su70cb8242018-06-22 17:38:47 +08003068 if (usecase->type != PCM_CAPTURE && usecase == voip_usecase) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003069 struct stream_out *voip_out = voip_usecase->stream.out;
3070 audio_extn_utils_send_app_type_gain(adev,
3071 voip_out->app_type_cfg.app_type,
3072 &voip_out->app_type_cfg.gain[0]);
3073 }
3074
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303075 ALOGD("%s: done",__func__);
3076
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003077 return status;
3078}
3079
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003080static int stop_input_stream(struct stream_in *in)
3081{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303082 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003083 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05303084
3085 if (in == NULL) {
3086 ALOGE("%s: stream_in ptr is NULL", __func__);
3087 return -EINVAL;
3088 }
3089
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003090 struct audio_device *adev = in->dev;
Carter Hsu2e429db2019-05-14 18:50:52 +08003091 struct stream_in *priority_in = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003092
Eric Laurent994a6932013-07-17 11:51:42 -07003093 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003094 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003095 uc_info = get_usecase_from_list(adev, in->usecase);
3096 if (uc_info == NULL) {
3097 ALOGE("%s: Could not find the usecase (%d) in the list",
3098 __func__, in->usecase);
3099 return -EINVAL;
3100 }
3101
Carter Hsu2e429db2019-05-14 18:50:52 +08003102 priority_in = get_priority_input(adev);
3103
Derek Chenea197282019-01-07 17:35:01 -08003104 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3105 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003106
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003107 /* Close in-call recording streams */
3108 voice_check_and_stop_incall_rec_usecase(adev, in);
3109
Eric Laurent150dbfe2013-02-27 14:31:02 -08003110 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003111 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003112
3113 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003114 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003115
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003116 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303117 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_PRIMARY);
3118
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003119 list_remove(&uc_info->list);
3120 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003121
Carter Hsu2e429db2019-05-14 18:50:52 +08003122 if (priority_in == in) {
3123 priority_in = get_priority_input(adev);
3124 if (priority_in)
3125 select_devices(adev, priority_in->usecase);
3126 }
3127
Vatsal Buchac09ae062018-11-14 13:25:08 +05303128 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07003129 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003130 return ret;
3131}
3132
3133int start_input_stream(struct stream_in *in)
3134{
3135 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08003136 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003137 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05303138
3139 if (in == NULL) {
3140 ALOGE("%s: stream_in ptr is NULL", __func__);
3141 return -EINVAL;
3142 }
3143
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003144 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07003145 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07003146 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003147
Mingming Yin2664a5b2015-09-03 10:53:11 -07003148 if (get_usecase_from_list(adev, usecase) == NULL)
3149 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303150 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
3151 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003152
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303153 if (CARD_STATUS_OFFLINE == in->card_status||
3154 CARD_STATUS_OFFLINE == adev->card_status) {
3155 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303156 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303157 goto error_config;
3158 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303159
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003160 if (is_sco_in_device_type(&in->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303161 if (!adev->bt_sco_on) {
3162 ALOGE("%s: SCO profile is not ready, return error", __func__);
3163 ret = -EIO;
3164 goto error_config;
3165 }
3166 }
3167
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003168 /* Check if source matches incall recording usecase criteria */
3169 ret = voice_check_and_set_incall_rec_usecase(adev, in);
3170 if (ret)
3171 goto error_config;
3172 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07003173 ALOGV("%s: usecase(%d)", __func__, in->usecase);
3174
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303175 if (audio_extn_cin_attached_usecase(in))
3176 audio_extn_cin_acquire_usecase(in);
3177
Mingming Yin2664a5b2015-09-03 10:53:11 -07003178 if (get_usecase_from_list(adev, in->usecase) != NULL) {
3179 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
3180 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08003181 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07003182 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003183
Eric Laurentb23d5282013-05-14 15:27:20 -07003184 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003185 if (in->pcm_device_id < 0) {
3186 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
3187 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08003188 ret = -EINVAL;
3189 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003190 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003191
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003192 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003193
3194 if (!uc_info) {
3195 ret = -ENOMEM;
3196 goto error_config;
3197 }
3198
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003199 uc_info->id = in->usecase;
3200 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003201 uc_info->stream.in = in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003202 list_init(&uc_info->device_list);
3203 assign_devices(&uc_info->device_list, &in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003204 uc_info->in_snd_device = SND_DEVICE_NONE;
3205 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003206
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003207 list_add_tail(&adev->usecase_list, &uc_info->list);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003208 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303209 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3210 adev->perf_lock_opts,
3211 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003212 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003213
Derek Chenea197282019-01-07 17:35:01 -08003214 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3215 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003216
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05303217 android_atomic_acquire_cas(true, false, &(in->capture_stopped));
3218
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303219 if (audio_extn_cin_attached_usecase(in)) {
Manish Dewangan46e07982018-12-13 18:18:59 +05303220 ret = audio_extn_cin_open_input_stream(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303221 if (ret)
3222 goto error_open;
3223 else
3224 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003225 }
3226
Haynes Mathew George16081042017-05-31 17:16:49 -07003227 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003228 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003229 ALOGE("%s: pcm stream not ready", __func__);
3230 goto error_open;
3231 }
3232 ret = pcm_start(in->pcm);
3233 if (ret < 0) {
3234 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3235 goto error_open;
3236 }
3237 } else {
3238 unsigned int flags = PCM_IN | PCM_MONOTONIC;
3239 unsigned int pcm_open_retry_count = 0;
3240
Zhou Song62ea0282020-03-22 19:53:01 +08003241 if ((in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) ||
3242 (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003243 flags |= PCM_MMAP | PCM_NOIRQ;
3244 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
3245 } else if (in->realtime) {
3246 flags |= PCM_MMAP | PCM_NOIRQ;
3247 }
3248
Garmond Leunge2433c32017-09-28 21:51:22 -07003249 if (audio_extn_ffv_get_stream() == in) {
3250 ALOGD("%s: ffv stream, update pcm config", __func__);
3251 audio_extn_ffv_update_pcm_config(&config);
3252 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003253 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3254 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3255
3256 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003257 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07003258 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07003259 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003260 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303261 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303262 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3263 adev->card_status = CARD_STATUS_OFFLINE;
3264 in->card_status = CARD_STATUS_OFFLINE;
3265 ret = -EIO;
3266 goto error_open;
3267 }
3268
Haynes Mathew George16081042017-05-31 17:16:49 -07003269 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3270 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3271 if (in->pcm != NULL) {
3272 pcm_close(in->pcm);
3273 in->pcm = NULL;
3274 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003275 if (pcm_open_retry_count == 0) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003276 ret = -EIO;
3277 goto error_open;
3278 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003279 pcm_open_retry_count--;
Haynes Mathew George16081042017-05-31 17:16:49 -07003280 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3281 continue;
3282 }
3283 break;
3284 }
3285
3286 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003287 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07003288 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003289 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003290 if (ret < 0) {
3291 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3292 pcm_close(in->pcm);
3293 in->pcm = NULL;
3294 goto error_open;
3295 }
3296 register_in_stream(in);
3297 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003298 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07003299 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003300 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003301 if (ret < 0) {
3302 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003303 pcm_close(in->pcm);
3304 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003305 goto error_open;
3306 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003307 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003308 }
3309
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003310 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07003311 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
3312 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003313
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003314 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303315 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
3316
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303317done_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003318 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303319 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003320 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303321 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003322 return ret;
3323
3324error_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003325 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303326 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003327 stop_input_stream(in);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003328
Eric Laurentc8400632013-02-14 19:04:54 -08003329error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303330 /*
3331 * sleep 50ms to allow sufficient time for kernel
3332 * drivers to recover incases like SSR.
3333 */
3334 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003335 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303336 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003337 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003338}
3339
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003340void lock_input_stream(struct stream_in *in)
3341{
3342 pthread_mutex_lock(&in->pre_lock);
3343 pthread_mutex_lock(&in->lock);
3344 pthread_mutex_unlock(&in->pre_lock);
3345}
3346
3347void lock_output_stream(struct stream_out *out)
3348{
3349 pthread_mutex_lock(&out->pre_lock);
3350 pthread_mutex_lock(&out->lock);
3351 pthread_mutex_unlock(&out->pre_lock);
3352}
3353
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003354/* must be called with out->lock locked */
3355static int send_offload_cmd_l(struct stream_out* out, int command)
3356{
3357 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
3358
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003359 if (!cmd) {
3360 ALOGE("failed to allocate mem for command 0x%x", command);
3361 return -ENOMEM;
3362 }
3363
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003364 ALOGVV("%s %d", __func__, command);
3365
3366 cmd->cmd = command;
3367 list_add_tail(&out->offload_cmd_list, &cmd->node);
3368 pthread_cond_signal(&out->offload_cond);
3369 return 0;
3370}
3371
3372/* must be called iwth out->lock locked */
3373static void stop_compressed_output_l(struct stream_out *out)
3374{
3375 out->offload_state = OFFLOAD_STATE_IDLE;
3376 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003377 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003378 if (out->compr != NULL) {
3379 compress_stop(out->compr);
3380 while (out->offload_thread_blocked) {
3381 pthread_cond_wait(&out->cond, &out->lock);
3382 }
3383 }
3384}
3385
Varun Balaraje49253e2017-07-06 19:48:56 +05303386bool is_interactive_usecase(audio_usecase_t uc_id)
3387{
3388 unsigned int i;
3389 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
3390 if (uc_id == interactive_usecases[i])
3391 return true;
3392 }
3393 return false;
3394}
3395
3396static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
3397{
3398 audio_usecase_t ret_uc = USECASE_INVALID;
3399 unsigned int intract_uc_index;
3400 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3401
3402 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
3403 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
3404 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
3405 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
3406 ret_uc = interactive_usecases[intract_uc_index];
3407 break;
3408 }
3409 }
3410
3411 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
3412 return ret_uc;
3413}
3414
3415static void free_interactive_usecase(struct audio_device *adev,
3416 audio_usecase_t uc_id)
3417{
3418 unsigned int interact_uc_index;
3419 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3420
3421 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
3422 if (interactive_usecases[interact_uc_index] == uc_id) {
3423 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
3424 break;
3425 }
3426 }
3427 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
3428}
3429
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003430bool is_offload_usecase(audio_usecase_t uc_id)
3431{
3432 unsigned int i;
3433 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
3434 if (uc_id == offload_usecases[i])
3435 return true;
3436 }
3437 return false;
3438}
3439
Dhananjay Kumarac341582017-02-23 23:42:25 +05303440static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003441{
vivek mehta446c3962015-09-14 10:57:35 -07003442 audio_usecase_t ret_uc = USECASE_INVALID;
3443 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003444 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003445 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05303446 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07003447 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
3448 else
3449 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003450
vivek mehta446c3962015-09-14 10:57:35 -07003451 pthread_mutex_lock(&adev->lock);
3452 if (get_usecase_from_list(adev, ret_uc) != NULL)
3453 ret_uc = USECASE_INVALID;
3454 pthread_mutex_unlock(&adev->lock);
3455
3456 return ret_uc;
3457 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003458
3459 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003460 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3461 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3462 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3463 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003464 break;
3465 }
3466 }
vivek mehta446c3962015-09-14 10:57:35 -07003467
3468 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3469 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003470}
3471
3472static void free_offload_usecase(struct audio_device *adev,
3473 audio_usecase_t uc_id)
3474{
vivek mehta446c3962015-09-14 10:57:35 -07003475 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003476 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003477
3478 if (!adev->multi_offload_enable)
3479 return;
3480
3481 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3482 if (offload_usecases[offload_uc_index] == uc_id) {
3483 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003484 break;
3485 }
3486 }
3487 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3488}
3489
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003490static void *offload_thread_loop(void *context)
3491{
3492 struct stream_out *out = (struct stream_out *) context;
3493 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003494 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003495
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003496 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08003497 set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003498 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3499
3500 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003501 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003502 out->offload_state = OFFLOAD_STATE_IDLE;
3503 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003504 for (;;) {
3505 struct offload_cmd *cmd = NULL;
3506 stream_callback_event_t event;
3507 bool send_callback = false;
3508
3509 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3510 __func__, list_empty(&out->offload_cmd_list),
3511 out->offload_state);
3512 if (list_empty(&out->offload_cmd_list)) {
3513 ALOGV("%s SLEEPING", __func__);
3514 pthread_cond_wait(&out->offload_cond, &out->lock);
3515 ALOGV("%s RUNNING", __func__);
3516 continue;
3517 }
3518
3519 item = list_head(&out->offload_cmd_list);
3520 cmd = node_to_item(item, struct offload_cmd, node);
3521 list_remove(item);
3522
3523 ALOGVV("%s STATE %d CMD %d out->compr %p",
3524 __func__, out->offload_state, cmd->cmd, out->compr);
3525
3526 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3527 free(cmd);
3528 break;
3529 }
3530
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003531 // allow OFFLOAD_CMD_ERROR reporting during standby
3532 // this is needed to handle failures during compress_open
3533 // Note however that on a pause timeout, the stream is closed
3534 // and no offload usecase will be active. Therefore this
3535 // special case is needed for compress_open failures alone
3536 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3537 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003538 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003539 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003540 pthread_cond_signal(&out->cond);
3541 continue;
3542 }
3543 out->offload_thread_blocked = true;
3544 pthread_mutex_unlock(&out->lock);
3545 send_callback = false;
3546 switch(cmd->cmd) {
3547 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003548 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003549 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003550 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003551 send_callback = true;
3552 event = STREAM_CBK_EVENT_WRITE_READY;
3553 break;
3554 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003555 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303556 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003557 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303558 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003559 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303560 if (ret < 0)
3561 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303562 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303563 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003564 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003565 else
3566 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003567 if (-ENETRESET != ret && !(-EINTR == ret &&
3568 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303569 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303570 pthread_mutex_lock(&out->lock);
3571 out->send_new_metadata = 1;
3572 out->send_next_track_params = true;
3573 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303574 event = STREAM_CBK_EVENT_DRAIN_READY;
3575 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3576 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303577 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003578 break;
3579 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003580 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003581 ret = compress_drain(out->compr);
3582 ALOGD("copl(%p):out of compress_drain", out);
3583 // EINTR check avoids drain interruption due to SSR
3584 if (-ENETRESET != ret && !(-EINTR == ret &&
3585 CARD_STATUS_OFFLINE == out->card_status)) {
3586 send_callback = true;
3587 event = STREAM_CBK_EVENT_DRAIN_READY;
3588 } else
3589 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003590 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303591 case OFFLOAD_CMD_ERROR:
3592 ALOGD("copl(%p): sending error callback to AF", out);
3593 send_callback = true;
3594 event = STREAM_CBK_EVENT_ERROR;
3595 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003596 default:
3597 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3598 break;
3599 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003600 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003601 out->offload_thread_blocked = false;
3602 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003603 if (send_callback && out->client_callback) {
3604 ALOGVV("%s: sending client_callback event %d", __func__, event);
3605 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003606 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003607 free(cmd);
3608 }
3609
3610 pthread_cond_signal(&out->cond);
3611 while (!list_empty(&out->offload_cmd_list)) {
3612 item = list_head(&out->offload_cmd_list);
3613 list_remove(item);
3614 free(node_to_item(item, struct offload_cmd, node));
3615 }
3616 pthread_mutex_unlock(&out->lock);
3617
3618 return NULL;
3619}
3620
3621static int create_offload_callback_thread(struct stream_out *out)
3622{
3623 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3624 list_init(&out->offload_cmd_list);
3625 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3626 offload_thread_loop, out);
3627 return 0;
3628}
3629
3630static int destroy_offload_callback_thread(struct stream_out *out)
3631{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003632 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003633 stop_compressed_output_l(out);
3634 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3635
3636 pthread_mutex_unlock(&out->lock);
3637 pthread_join(out->offload_thread, (void **) NULL);
3638 pthread_cond_destroy(&out->offload_cond);
3639
3640 return 0;
3641}
3642
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003643static int stop_output_stream(struct stream_out *out)
3644{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303645 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003646 struct audio_usecase *uc_info;
3647 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003648 bool has_voip_usecase =
3649 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003650
Eric Laurent994a6932013-07-17 11:51:42 -07003651 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003652 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003653 uc_info = get_usecase_from_list(adev, out->usecase);
3654 if (uc_info == NULL) {
3655 ALOGE("%s: Could not find the usecase (%d) in the list",
3656 __func__, out->usecase);
3657 return -EINVAL;
3658 }
3659
Derek Chenea197282019-01-07 17:35:01 -08003660 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3661 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003662
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003663 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303664 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003665 if (adev->visualizer_stop_output != NULL)
3666 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003667
3668 audio_extn_dts_remove_state_notifier_node(out->usecase);
3669
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003670 if (adev->offload_effects_stop_output != NULL)
3671 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07003672 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3673 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3674 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003675 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003676
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003677 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3678 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003679 voice_set_device_mute_flag(adev, false);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003680 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003681
Eric Laurent150dbfe2013-02-27 14:31:02 -08003682 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003683 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003684
3685 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003686 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003687
Aalique Grahame22e49102018-12-18 14:23:57 -08003688 audio_extn_extspk_update(adev->extspk);
3689
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003690 if (is_offload_usecase(out->usecase)) {
3691 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3692 adev->dsp_bit_width_enforce_mode,
3693 false);
3694 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003695 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003696 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3697 false);
3698
3699 if (ret != 0)
3700 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3701 /* default service interval was successfully updated,
3702 reopen USB backend with new service interval */
3703 ret = 0;
3704 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003705
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003706 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303707 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003708 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303709 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003710 ALOGV("Disable passthrough , reset mixer to pcm");
3711 /* NO_PASSTHROUGH */
Meng Wang4c32fb42020-01-16 17:57:11 +08003712#ifdef AUDIO_GKI_ENABLED
3713 /* out->compr_config.codec->reserved[0] is for compr_passthr */
3714 out->compr_config.codec->reserved[0] = 0;
3715#else
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003716 out->compr_config.codec->compr_passthr = 0;
Meng Wang4c32fb42020-01-16 17:57:11 +08003717#endif
Mingming Yin21854652016-04-13 11:54:02 -07003718 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003719 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3720 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003721
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303722 /* Must be called after removing the usecase from list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003723 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL))
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303724 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303725
Manish Dewangan21a850a2017-08-14 12:03:55 +05303726 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003727 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3728 if (ret < 0)
3729 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3730 }
3731
juyuchen2d415992018-11-16 14:15:16 +08003732 /* 1) media + voip output routing to handset must route media back to
3733 speaker when voip stops.
3734 2) trigger voip input to reroute when voip output changes to
3735 hearing aid. */
Aalique Grahame22e49102018-12-18 14:23:57 -08003736 if (has_voip_usecase ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003737 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003738 struct listnode *node;
3739 struct audio_usecase *usecase;
3740 list_for_each(node, &adev->usecase_list) {
3741 usecase = node_to_item(node, struct audio_usecase, list);
juyuchen2d415992018-11-16 14:15:16 +08003742 if ((usecase->type == PCM_CAPTURE &&
3743 usecase->id != USECASE_AUDIO_RECORD_VOIP)
3744 || usecase == uc_info)
Aalique Grahame22e49102018-12-18 14:23:57 -08003745 continue;
3746
3747 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
3748 __func__, usecase->id, use_case_table[usecase->id],
3749 out->usecase, use_case_table[out->usecase]);
3750 select_devices(adev, usecase->id);
3751 }
3752 }
3753
Garmond Leung5fd0b552018-04-17 11:56:12 -07003754 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003755 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003756 return ret;
3757}
3758
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003759struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
3760 unsigned int flags, unsigned int pcm_open_retry_count,
3761 struct pcm_config *config)
3762{
3763 struct pcm* pcm = NULL;
3764
3765 while (1) {
3766 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
3767 if (pcm == NULL || !pcm_is_ready(pcm)) {
3768 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
3769 if (pcm != NULL) {
3770 pcm_close(pcm);
3771 pcm = NULL;
3772 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003773 if (pcm_open_retry_count == 0)
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003774 return NULL;
3775
Weiyin Jiang72197252019-10-09 11:49:32 +08003776 pcm_open_retry_count--;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003777 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3778 continue;
3779 }
3780 break;
3781 }
3782
3783 if (pcm_is_ready(pcm)) {
3784 int ret = pcm_prepare(pcm);
3785 if (ret < 0) {
3786 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3787 pcm_close(pcm);
3788 pcm = NULL;
3789 }
3790 }
3791
3792 return pcm;
3793}
3794
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003795int start_output_stream(struct stream_out *out)
3796{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003797 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003798 struct audio_usecase *uc_info;
3799 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003800 char mixer_ctl_name[128];
3801 struct mixer_ctl *ctl = NULL;
3802 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303803 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003804 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003805
Haynes Mathew George380745d2017-10-04 15:27:45 -07003806 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003807 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3808 ret = -EINVAL;
3809 goto error_config;
3810 }
3811
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003812 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303813 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003814 get_device_types(&out->device_list), is_haptic_usecase);
3815
3816 bool is_speaker_active = compare_device_type(&out->device_list,
3817 AUDIO_DEVICE_OUT_SPEAKER);
3818 bool is_speaker_safe_active = compare_device_type(&out->device_list,
3819 AUDIO_DEVICE_OUT_SPEAKER_SAFE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303820
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303821 if (CARD_STATUS_OFFLINE == out->card_status ||
3822 CARD_STATUS_OFFLINE == adev->card_status) {
3823 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303824 ret = -EIO;
Mingshu Pang5fc696f2020-02-28 12:32:00 +08003825 goto error_fatal;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303826 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303827
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003828 //Update incall music usecase to reflect correct voice session
3829 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3830 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
3831 if (ret != 0) {
3832 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3833 __func__, ret);
3834 goto error_config;
3835 }
3836 }
3837
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003838 if (is_a2dp_out_device_type(&out->device_list)) {
Florian Pfister1a84f312018-07-19 14:38:18 +02003839 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003840 if (is_speaker_active || is_speaker_safe_active) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303841 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303842 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303843 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3844 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3845 ret = -EAGAIN;
3846 goto error_config;
3847 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303848 }
3849 }
3850 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003851 if (is_sco_out_device_type(&out->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303852 if (!adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003853 if (is_speaker_active) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303854 //combo usecase just by pass a2dp
3855 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003856 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303857 } else {
3858 ALOGE("%s: SCO profile is not ready, return error", __func__);
3859 ret = -EAGAIN;
3860 goto error_config;
3861 }
3862 }
3863 }
3864
Eric Laurentb23d5282013-05-14 15:27:20 -07003865 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003866 if (out->pcm_device_id < 0) {
3867 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3868 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003869 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003870 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003871 }
3872
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003873 if (is_haptic_usecase) {
Meng Wang51d8c2a2020-04-27 15:23:21 +08003874 adev->haptic_pcm_device_id = platform_get_pcm_device_id(
3875 USECASE_AUDIO_PLAYBACK_HAPTICS, PCM_PLAYBACK);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003876 if (adev->haptic_pcm_device_id < 0) {
3877 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
3878 __func__, adev->haptic_pcm_device_id, out->usecase);
3879 ret = -EINVAL;
3880 goto error_config;
3881 }
3882 }
3883
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003884 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003885
3886 if (!uc_info) {
3887 ret = -ENOMEM;
3888 goto error_config;
3889 }
3890
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003891 uc_info->id = out->usecase;
3892 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003893 uc_info->stream.out = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003894 list_init(&uc_info->device_list);
3895 assign_devices(&uc_info->device_list, &out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003896 uc_info->in_snd_device = SND_DEVICE_NONE;
3897 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003898
3899 /* This must be called before adding this usecase to the list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003900 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003901 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3902 /* USB backend is not reopened immediately.
3903 This is eventually done as part of select_devices */
3904 }
3905
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003906 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003907
Wei Wangf7ca6c92017-11-21 14:51:20 -08003908 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303909 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3910 adev->perf_lock_opts,
3911 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303912
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003913 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303914 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303915 if (audio_extn_passthru_is_enabled() &&
3916 audio_extn_passthru_is_passthrough_stream(out)) {
3917 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303918 }
3919 }
3920
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003921 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003922 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303923 if (!a2dp_combo) {
3924 check_a2dp_restore_l(adev, out, false);
3925 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003926 struct listnode dev;
3927 list_init(&dev);
3928 assign_devices(&dev, &out->device_list);
3929 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
3930 reassign_device_list(&out->device_list,
3931 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aalique Grahame22e49102018-12-18 14:23:57 -08003932 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003933 reassign_device_list(&out->device_list,
3934 AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303935 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003936 assign_devices(&out->device_list, &dev);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303937 }
3938 } else {
Revathi Uddarajub26e3932020-06-10 14:51:02 +05303939 select_devices(adev, out->usecase);
3940 if (is_a2dp_out_device_type(&out->device_list) &&
3941 !adev->a2dp_started) {
3942 if (is_speaker_active || is_speaker_safe_active) {
3943 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, "");
3949 else
3950 reassign_device_list(&out->device_list,
3951 AUDIO_DEVICE_OUT_SPEAKER, "");
3952 select_devices(adev, out->usecase);
3953 assign_devices(&out->device_list, &dev);
3954 } else {
3955 ret = -EINVAL;
3956 goto error_open;
3957 }
3958 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303959 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003960
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003961 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3962 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003963 voice_set_device_mute_flag(adev, true);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003964 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003965
Derek Chenea197282019-01-07 17:35:01 -08003966 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3967 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003968
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003969 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3970 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003971
3972 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07003973 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07003974 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3975 ALOGE("%s: pcm stream not ready", __func__);
3976 goto error_open;
3977 }
3978 ret = pcm_start(out->pcm);
3979 if (ret < 0) {
3980 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3981 goto error_open;
3982 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07003983 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07003984 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003985 unsigned int flags = PCM_OUT;
3986 unsigned int pcm_open_retry_count = 0;
3987 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
3988 flags |= PCM_MMAP | PCM_NOIRQ;
3989 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003990 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08003991 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003992 } else
3993 flags |= PCM_MONOTONIC;
3994
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003995 if ((adev->vr_audio_mode_enabled) &&
3996 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
3997 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3998 "PCM_Dev %d Topology", out->pcm_device_id);
3999 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4000 if (!ctl) {
4001 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
4002 __func__, mixer_ctl_name);
4003 } else {
4004 //if success use ULLPP
4005 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
4006 __func__, mixer_ctl_name, out->pcm_device_id);
4007 //There is a still a possibility that some sessions
4008 // that request for FAST|RAW when 3D audio is active
4009 //can go through ULLPP. Ideally we expects apps to
4010 //listen to audio focus and stop concurrent playback
4011 //Also, we will look for mode flag (voice_in_communication)
4012 //before enabling the realtime flag.
4013 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
4014 }
4015 }
4016
Surendar Karka91fa3682018-07-02 18:12:12 +05304017 if (out->realtime)
4018 platform_set_stream_channel_map(adev->platform, out->channel_mask,
4019 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
4020
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004021 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
4022 flags, pcm_open_retry_count,
4023 &(out->config));
4024 if (out->pcm == NULL) {
4025 ret = -EIO;
4026 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004027 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004028
4029 if (is_haptic_usecase) {
4030 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
4031 adev->haptic_pcm_device_id,
4032 flags, pcm_open_retry_count,
4033 &(adev->haptics_config));
4034 // failure to open haptics pcm shouldnt stop audio,
4035 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07004036
4037 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
4038 ALOGD("%s: enable haptic audio synchronization", __func__);
4039 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
4040 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004041 }
4042
Surendar Karka91fa3682018-07-02 18:12:12 +05304043 if (!out->realtime)
4044 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Surendar Karkaf51b5842018-04-26 11:28:38 +05304045 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004046
Zhou Song2b8f28f2017-09-11 10:51:38 +08004047 // apply volume for voip playback after path is set up
4048 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
4049 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05304050 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
4051 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304052 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
4053 out->apply_volume = false;
Derek Chenf13dd492018-11-13 14:53:51 -08004054 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
4055 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304056 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004057 } else {
Zhou Song79929fe2020-01-20 17:57:43 +08004058 /*
4059 * set custom channel map if:
4060 * 1. neither mono nor stereo clips i.e. channels > 2 OR
4061 * 2. custom channel map has been set by client
4062 * else default channel map of FC/FR/FL can always be set to DSP
4063 */
4064 if (popcount(out->channel_mask) > 2 || out->channel_map_param.channel_map[0])
4065 platform_set_stream_channel_map(adev->platform, out->channel_mask,
4066 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08004067 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
4068 adev->dsp_bit_width_enforce_mode,
4069 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004070 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07004071 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004072 out->compr = compress_open(adev->snd_card,
4073 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004074 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004075 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05304076 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05304077 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
4078 adev->card_status = CARD_STATUS_OFFLINE;
4079 out->card_status = CARD_STATUS_OFFLINE;
4080 ret = -EIO;
4081 goto error_open;
4082 }
4083
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004084 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004085 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004086 compress_close(out->compr);
4087 out->compr = NULL;
4088 ret = -EIO;
4089 goto error_open;
4090 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304091 /* compress_open sends params of the track, so reset the flag here */
4092 out->is_compr_metadata_avail = false;
4093
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004094 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004095 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07004096
Fred Oh3f43e742015-03-04 18:42:34 -08004097 /* Since small bufs uses blocking writes, a write will be blocked
4098 for the default max poll time (20s) in the event of an SSR.
4099 Reduce the poll time to observe and deal with SSR faster.
4100 */
Ashish Jain5106d362016-05-11 19:23:33 +05304101 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08004102 compress_set_max_poll_wait(out->compr, 1000);
4103 }
4104
Manish Dewangan69426c82017-01-30 17:35:36 +05304105 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05304106 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05304107
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004108 audio_extn_dts_create_state_notifier_node(out->usecase);
4109 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4110 popcount(out->channel_mask),
4111 out->playback_started);
4112
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004113#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304114 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004115 audio_extn_dolby_send_ddp_endp_params(adev);
4116#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05304117 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
4118 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004119 if (adev->visualizer_start_output != NULL)
4120 adev->visualizer_start_output(out->handle, out->pcm_device_id);
4121 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05304122 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004123 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004124 }
Derek Chenf13dd492018-11-13 14:53:51 -08004125
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004126 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf13dd492018-11-13 14:53:51 -08004127 /* Update cached volume from media to offload/direct stream */
4128 struct listnode *node = NULL;
4129 list_for_each(node, &adev->active_outputs_list) {
4130 streams_output_ctxt_t *out_ctxt = node_to_item(node,
4131 streams_output_ctxt_t,
4132 list);
4133 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
4134 out->volume_l = out_ctxt->output->volume_l;
4135 out->volume_r = out_ctxt->output->volume_r;
4136 }
4137 }
4138 out_set_compr_volume(&out->stream,
4139 out->volume_l, out->volume_r);
4140 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004141 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004142
4143 if (ret == 0) {
4144 register_out_stream(out);
4145 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07004146 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4147 ALOGE("%s: pcm stream not ready", __func__);
4148 goto error_open;
4149 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004150 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004151 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004152 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004153 if (ret < 0)
4154 goto error_open;
4155 }
4156 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004157 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304158 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07004159 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004160
vivek mehtad15d2bf2019-05-17 13:35:10 -07004161 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
4162 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4163 audio_low_latency_hint_start();
4164 }
4165
Manish Dewangan21a850a2017-08-14 12:03:55 +05304166 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07004167 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07004168 if (ret < 0)
4169 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
4170 }
4171
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004172 // consider a scenario where on pause lower layers are tear down.
4173 // so on resume, swap mixer control need to be sent only when
4174 // backend is active, hence rather than sending from enable device
4175 // sending it from start of streamtream
4176
4177 platform_set_swap_channels(adev, true);
4178
Haynes Mathew George380745d2017-10-04 15:27:45 -07004179 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304180 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004181 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004182error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004183 if (adev->haptic_pcm) {
4184 pcm_close(adev->haptic_pcm);
4185 adev->haptic_pcm = NULL;
4186 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004187 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304188 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004189 stop_output_stream(out);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004190error_fatal:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05304191 /*
4192 * sleep 50ms to allow sufficient time for kernel
4193 * drivers to recover incases like SSR.
4194 */
4195 usleep(50000);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004196error_config:
Haynes Mathew George380745d2017-10-04 15:27:45 -07004197 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304198 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004199 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004200}
4201
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004202static int check_input_parameters(uint32_t sample_rate,
4203 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08004204 int channel_count,
4205 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004206{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004207 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004208
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304209 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
4210 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
4211 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07004212 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02004213 !audio_extn_compr_cap_format_supported(format) &&
4214 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004215 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004216
Aalique Grahame22e49102018-12-18 14:23:57 -08004217 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
4218 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
4219 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
4220 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
4221 return -EINVAL;
4222 }
4223
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004224 switch (channel_count) {
4225 case 1:
4226 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304227 case 3:
4228 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004229 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07004230 case 8:
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05304231 case 10:
4232 case 12:
4233 case 14:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004234 break;
4235 default:
4236 ret = -EINVAL;
4237 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004238
4239 switch (sample_rate) {
4240 case 8000:
4241 case 11025:
4242 case 12000:
4243 case 16000:
4244 case 22050:
4245 case 24000:
4246 case 32000:
4247 case 44100:
4248 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004249 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304250 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004251 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304252 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004253 break;
4254 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004255 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004256 }
4257
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004258 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004259}
4260
Naresh Tanniru04f71882018-06-26 17:46:22 +05304261
4262/** Add a value in a list if not already present.
4263 * @return true if value was successfully inserted or already present,
4264 * false if the list is full and does not contain the value.
4265 */
4266static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
4267 for (size_t i = 0; i < list_length; i++) {
4268 if (list[i] == value) return true; // value is already present
4269 if (list[i] == 0) { // no values in this slot
4270 list[i] = value;
4271 return true; // value inserted
4272 }
4273 }
4274 return false; // could not insert value
4275}
4276
4277/** Add channel_mask in supported_channel_masks if not already present.
4278 * @return true if channel_mask was successfully inserted or already present,
4279 * false if supported_channel_masks is full and does not contain channel_mask.
4280 */
4281static void register_channel_mask(audio_channel_mask_t channel_mask,
4282 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
4283 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
4284 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
4285}
4286
4287/** Add format in supported_formats if not already present.
4288 * @return true if format was successfully inserted or already present,
4289 * false if supported_formats is full and does not contain format.
4290 */
4291static void register_format(audio_format_t format,
4292 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
4293 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
4294 "%s: stream can not declare supporting its format %x", __func__, format);
4295}
4296/** Add sample_rate in supported_sample_rates if not already present.
4297 * @return true if sample_rate was successfully inserted or already present,
4298 * false if supported_sample_rates is full and does not contain sample_rate.
4299 */
4300static void register_sample_rate(uint32_t sample_rate,
4301 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
4302 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
4303 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
4304}
4305
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004306static inline uint32_t lcm(uint32_t num1, uint32_t num2)
4307{
4308 uint32_t high = num1, low = num2, temp = 0;
4309
4310 if (!num1 || !num2)
4311 return 0;
4312
4313 if (num1 < num2) {
4314 high = num2;
4315 low = num1;
4316 }
4317
4318 while (low != 0) {
4319 temp = low;
4320 low = high % low;
4321 high = temp;
4322 }
4323 return (num1 * num2)/high;
4324}
4325
4326static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
4327{
4328 uint32_t remainder = 0;
4329
4330 if (!multiplier)
4331 return num;
4332
4333 remainder = num % multiplier;
4334 if (remainder)
4335 num += (multiplier - remainder);
4336
4337 return num;
4338}
4339
Aalique Grahame22e49102018-12-18 14:23:57 -08004340static size_t get_stream_buffer_size(size_t duration_ms,
4341 uint32_t sample_rate,
4342 audio_format_t format,
4343 int channel_count,
4344 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004345{
4346 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004347 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004348
Aalique Grahame22e49102018-12-18 14:23:57 -08004349 size = (sample_rate * duration_ms) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004350 if (is_low_latency)
4351 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304352
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004353 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08004354 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004355
Ralf Herzbd08d632018-09-28 15:50:49 +02004356 /* make sure the size is multiple of 32 bytes and additionally multiple of
4357 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004358 * At 48 kHz mono 16-bit PCM:
4359 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
4360 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004361 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004362 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004363 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07004364
4365 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004366}
4367
Aalique Grahame22e49102018-12-18 14:23:57 -08004368static size_t get_input_buffer_size(uint32_t sample_rate,
4369 audio_format_t format,
4370 int channel_count,
4371 bool is_low_latency)
4372{
4373 /* Don't know if USB HIFI in this context so use true to be conservative */
4374 if (check_input_parameters(sample_rate, format, channel_count,
4375 true /*is_usb_hifi */) != 0)
4376 return 0;
4377
4378 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4379 sample_rate,
4380 format,
4381 channel_count,
4382 is_low_latency);
4383}
4384
Derek Chenf6318be2017-06-12 17:16:24 -04004385size_t get_output_period_size(uint32_t sample_rate,
4386 audio_format_t format,
4387 int channel_count,
4388 int duration /*in millisecs*/)
Ashish Jain058165c2016-09-28 23:18:48 +05304389{
4390 size_t size = 0;
4391 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
4392
4393 if ((duration == 0) || (sample_rate == 0) ||
4394 (bytes_per_sample == 0) || (channel_count == 0)) {
4395 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
4396 bytes_per_sample, channel_count);
4397 return -EINVAL;
4398 }
4399
4400 size = (sample_rate *
4401 duration *
4402 bytes_per_sample *
4403 channel_count) / 1000;
4404 /*
4405 * To have same PCM samples for all channels, the buffer size requires to
4406 * be multiple of (number of channels * bytes per sample)
4407 * For writes to succeed, the buffer must be written at address which is multiple of 32
4408 */
4409 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
4410
4411 return (size/(channel_count * bytes_per_sample));
4412}
4413
Zhou Song48453a02018-01-10 17:50:59 +08004414static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05304415{
4416 uint64_t actual_frames_rendered = 0;
Weiyin Jiang4813da12020-05-28 00:37:28 +08004417 uint64_t written_frames = 0;
4418 uint64_t kernel_frames = 0;
4419 uint64_t dsp_frames = 0;
4420 uint64_t signed_frames = 0;
4421 size_t kernel_buffer_size = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304422
4423 /* This adjustment accounts for buffering after app processor.
4424 * It is based on estimated DSP latency per use case, rather than exact.
4425 */
George Gao9ba8a142020-07-23 14:30:03 -07004426 dsp_frames = platform_render_latency(out) *
Weiyin Jiang4813da12020-05-28 00:37:28 +08004427 out->sample_rate / 1000000LL;
Ashish Jain5106d362016-05-11 19:23:33 +05304428
Zhou Song48453a02018-01-10 17:50:59 +08004429 pthread_mutex_lock(&out->position_query_lock);
Weiyin Jiang4813da12020-05-28 00:37:28 +08004430 written_frames = out->written /
4431 (audio_bytes_per_sample(out->hal_ip_format) * popcount(out->channel_mask));
4432
Ashish Jain5106d362016-05-11 19:23:33 +05304433 /* not querying actual state of buffering in kernel as it would involve an ioctl call
4434 * which then needs protection, this causes delay in TS query for pcm_offload usecase
4435 * hence only estimate.
4436 */
Weiyin Jiang4813da12020-05-28 00:37:28 +08004437 kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
4438 kernel_frames = kernel_buffer_size /
4439 (audio_bytes_per_sample(out->hal_op_format) * popcount(out->channel_mask));
Ashish Jain5106d362016-05-11 19:23:33 +05304440
Weiyin Jiang4813da12020-05-28 00:37:28 +08004441 if (written_frames >= (kernel_frames + dsp_frames))
4442 signed_frames = written_frames - kernel_frames - dsp_frames;
Ashish Jain5106d362016-05-11 19:23:33 +05304443
Zhou Song48453a02018-01-10 17:50:59 +08004444 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05304445 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08004446 if (timestamp != NULL )
4447 *timestamp = out->writeAt;
4448 } else if (timestamp != NULL) {
4449 clock_gettime(CLOCK_MONOTONIC, timestamp);
4450 }
4451 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304452
Weiyin Jiang4813da12020-05-28 00:37:28 +08004453 ALOGVV("%s signed frames %lld written frames %lld kernel frames %lld dsp frames %lld",
4454 __func__, signed_frames, written_frames, kernel_frames, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05304455
4456 return actual_frames_rendered;
4457}
4458
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004459static uint32_t out_get_sample_rate(const struct audio_stream *stream)
4460{
4461 struct stream_out *out = (struct stream_out *)stream;
4462
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004463 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004464}
4465
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004466static int out_set_sample_rate(struct audio_stream *stream __unused,
4467 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004468{
4469 return -ENOSYS;
4470}
4471
4472static size_t out_get_buffer_size(const struct audio_stream *stream)
4473{
4474 struct stream_out *out = (struct stream_out *)stream;
4475
Varun Balaraje49253e2017-07-06 19:48:56 +05304476 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05304477 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05304478 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304479 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4480 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
4481 else
4482 return out->compr_config.fragment_size;
4483 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004484 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304485 else if (is_offload_usecase(out->usecase) &&
4486 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304487 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004488
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004489 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004490 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004491}
4492
4493static uint32_t out_get_channels(const struct audio_stream *stream)
4494{
4495 struct stream_out *out = (struct stream_out *)stream;
4496
4497 return out->channel_mask;
4498}
4499
4500static audio_format_t out_get_format(const struct audio_stream *stream)
4501{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004502 struct stream_out *out = (struct stream_out *)stream;
4503
4504 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004505}
4506
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004507static int out_set_format(struct audio_stream *stream __unused,
4508 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004509{
4510 return -ENOSYS;
4511}
4512
4513static int out_standby(struct audio_stream *stream)
4514{
4515 struct stream_out *out = (struct stream_out *)stream;
4516 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07004517 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004518
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304519 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4520 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004521
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004522 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004523 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004524 if (adev->adm_deregister_stream)
4525 adev->adm_deregister_stream(adev->adm_data, out->handle);
4526
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004527 if (is_offload_usecase(out->usecase))
4528 stop_compressed_output_l(out);
4529
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004530 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004531 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004532 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4533 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304534 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08004535 pthread_mutex_unlock(&adev->lock);
4536 pthread_mutex_unlock(&out->lock);
4537 ALOGD("VOIP output entered standby");
4538 return 0;
4539 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004540 if (out->pcm) {
4541 pcm_close(out->pcm);
4542 out->pcm = NULL;
4543 }
Meng Wanga09da002020-04-20 12:56:04 +08004544 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4545 if (adev->haptic_pcm) {
4546 pcm_close(adev->haptic_pcm);
4547 adev->haptic_pcm = NULL;
4548 }
4549
4550 if (adev->haptic_buffer != NULL) {
4551 free(adev->haptic_buffer);
4552 adev->haptic_buffer = NULL;
4553 adev->haptic_buffer_size = 0;
4554 }
4555 adev->haptic_pcm_device_id = 0;
4556 }
4557
Haynes Mathew George16081042017-05-31 17:16:49 -07004558 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4559 do_stop = out->playback_started;
4560 out->playback_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07004561
4562 if (out->mmap_shared_memory_fd >= 0) {
4563 ALOGV("%s: closing mmap_shared_memory_fd = %d",
4564 __func__, out->mmap_shared_memory_fd);
4565 close(out->mmap_shared_memory_fd);
4566 out->mmap_shared_memory_fd = -1;
4567 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004568 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004569 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004570 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304571 out->send_next_track_params = false;
4572 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004573 out->gapless_mdata.encoder_delay = 0;
4574 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004575 if (out->compr != NULL) {
4576 compress_close(out->compr);
4577 out->compr = NULL;
4578 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004579 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004580 if (do_stop) {
4581 stop_output_stream(out);
4582 }
Lakshman Chaluvaraju06677b42019-06-24 10:04:52 +05304583 // if fm is active route on selected device in UI
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004584 audio_extn_fm_route_on_selected_device(adev, &out->device_list);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004585 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004586 }
4587 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05304588 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004589 return 0;
4590}
4591
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304592static int out_on_error(struct audio_stream *stream)
4593{
4594 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004595 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304596
4597 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004598 // always send CMD_ERROR for offload streams, this
4599 // is needed e.g. when SSR happens within compress_open
4600 // since the stream is active, offload_callback_thread is also active.
4601 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
4602 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004603 }
4604 pthread_mutex_unlock(&out->lock);
4605
4606 status = out_standby(&out->stream.common);
4607
4608 lock_output_stream(out);
4609 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004610 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304611 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05304612
4613 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
4614 ALOGD("Setting previous card status if offline");
4615 out->prev_card_status_offline = true;
4616 }
4617
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304618 pthread_mutex_unlock(&out->lock);
4619
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004620 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304621}
4622
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304623/*
4624 *standby implementation without locks, assumes that the callee already
4625 *has taken adev and out lock.
4626 */
4627int out_standby_l(struct audio_stream *stream)
4628{
4629 struct stream_out *out = (struct stream_out *)stream;
4630 struct audio_device *adev = out->dev;
4631
4632 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4633 stream, out->usecase, use_case_table[out->usecase]);
4634
4635 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07004636 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304637 if (adev->adm_deregister_stream)
4638 adev->adm_deregister_stream(adev->adm_data, out->handle);
4639
4640 if (is_offload_usecase(out->usecase))
4641 stop_compressed_output_l(out);
4642
4643 out->standby = true;
4644 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4645 voice_extn_compress_voip_close_output_stream(stream);
4646 out->started = 0;
4647 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07004648 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304649 return 0;
4650 } else if (!is_offload_usecase(out->usecase)) {
4651 if (out->pcm) {
4652 pcm_close(out->pcm);
4653 out->pcm = NULL;
4654 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004655 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4656 if (adev->haptic_pcm) {
4657 pcm_close(adev->haptic_pcm);
4658 adev->haptic_pcm = NULL;
4659 }
4660
4661 if (adev->haptic_buffer != NULL) {
4662 free(adev->haptic_buffer);
4663 adev->haptic_buffer = NULL;
4664 adev->haptic_buffer_size = 0;
4665 }
4666 adev->haptic_pcm_device_id = 0;
4667 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304668 } else {
4669 ALOGD("copl(%p):standby", out);
4670 out->send_next_track_params = false;
4671 out->is_compr_metadata_avail = false;
4672 out->gapless_mdata.encoder_delay = 0;
4673 out->gapless_mdata.encoder_padding = 0;
4674 if (out->compr != NULL) {
4675 compress_close(out->compr);
4676 out->compr = NULL;
4677 }
4678 }
4679 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004680 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304681 }
4682 ALOGD("%s: exit", __func__);
4683 return 0;
4684}
4685
Aalique Grahame22e49102018-12-18 14:23:57 -08004686static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004687{
Aalique Grahame22e49102018-12-18 14:23:57 -08004688 struct stream_out *out = (struct stream_out *)stream;
4689
4690 // We try to get the lock for consistency,
4691 // but it isn't necessary for these variables.
4692 // If we're not in standby, we may be blocked on a write.
4693 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
4694 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
4695 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
4696
Andy Hunga1f48fa2019-07-01 18:14:53 -07004697 char buffer[256]; // for statistics formatting
4698 if (!is_offload_usecase(out->usecase)) {
4699 simple_stats_to_string(&out->fifo_underruns, buffer, sizeof(buffer));
4700 dprintf(fd, " Fifo frame underruns: %s\n", buffer);
4701 }
4702
Andy Hungc6bfd4a2019-07-01 18:26:00 -07004703 if (out->start_latency_ms.n > 0) {
4704 simple_stats_to_string(&out->start_latency_ms, buffer, sizeof(buffer));
4705 dprintf(fd, " Start latency ms: %s\n", buffer);
4706 }
4707
Aalique Grahame22e49102018-12-18 14:23:57 -08004708 if (locked) {
4709 pthread_mutex_unlock(&out->lock);
4710 }
4711
4712 // dump error info
4713 (void)error_log_dump(
4714 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
4715
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004716 return 0;
4717}
4718
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004719static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
4720{
4721 int ret = 0;
4722 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08004723
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004724 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004725 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004726 return -EINVAL;
4727 }
4728
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304729 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08004730
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004731 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
4732 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304733 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004734 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004735 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
4736 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304737 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004738 }
4739
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004740 ALOGV("%s new encoder delay %u and padding %u", __func__,
4741 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
4742
4743 return 0;
4744}
4745
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004746static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
4747{
4748 return out == adev->primary_output || out == adev->voice_tx_output;
4749}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004750
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304751// note: this call is safe only if the stream_cb is
4752// removed first in close_output_stream (as is done now).
4753static void out_snd_mon_cb(void * stream, struct str_parms * parms)
4754{
4755 if (!stream || !parms)
4756 return;
4757
4758 struct stream_out *out = (struct stream_out *)stream;
4759 struct audio_device *adev = out->dev;
4760
4761 card_status_t status;
4762 int card;
4763 if (parse_snd_card_status(parms, &card, &status) < 0)
4764 return;
4765
4766 pthread_mutex_lock(&adev->lock);
4767 bool valid_cb = (card == adev->snd_card);
4768 pthread_mutex_unlock(&adev->lock);
4769
4770 if (!valid_cb)
4771 return;
4772
4773 lock_output_stream(out);
4774 if (out->card_status != status)
4775 out->card_status = status;
4776 pthread_mutex_unlock(&out->lock);
4777
4778 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
4779 use_case_table[out->usecase],
4780 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4781
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304782 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304783 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304784 if (voice_is_call_state_active(adev) &&
4785 out == adev->primary_output) {
4786 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
4787 pthread_mutex_lock(&adev->lock);
4788 voice_stop_call(adev);
4789 adev->mode = AUDIO_MODE_NORMAL;
4790 pthread_mutex_unlock(&adev->lock);
4791 }
4792 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304793 return;
4794}
4795
Kevin Rocardfce19002017-08-07 19:21:36 -07004796static int get_alive_usb_card(struct str_parms* parms) {
4797 int card;
4798 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
4799 !audio_extn_usb_alive(card)) {
4800 return card;
4801 }
4802 return -ENODEV;
4803}
4804
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004805int route_output_stream(struct stream_out *out,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004806 struct listnode *devices)
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004807{
4808 struct audio_device *adev = out->dev;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004809 int ret = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004810 struct listnode new_devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004811 bool bypass_a2dp = false;
4812 bool reconfig = false;
4813 unsigned long service_interval = 0;
4814
4815 ALOGD("%s: enter: usecase(%d: %s) devices %x",
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004816 __func__, out->usecase, use_case_table[out->usecase], get_device_types(devices));
4817
4818 list_init(&new_devices);
4819 assign_devices(&new_devices, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004820
4821 lock_output_stream(out);
4822 pthread_mutex_lock(&adev->lock);
4823
4824 /*
4825 * When HDMI cable is unplugged the music playback is paused and
4826 * the policy manager sends routing=0. But the audioflinger continues
4827 * to write data until standby time (3sec). As the HDMI core is
4828 * turned off, the write gets blocked.
4829 * Avoid this by routing audio to speaker until standby.
4830 */
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08004831 if (is_single_device_type_equal(&out->device_list,
4832 AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004833 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004834 !audio_extn_passthru_is_passthrough_stream(out) &&
4835 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004836 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004837 }
4838 /*
4839 * When A2DP is disconnected the
4840 * music playback is paused and the policy manager sends routing=0
4841 * But the audioflinger continues to write data until standby time
4842 * (3sec). As BT is turned off, the write gets blocked.
4843 * Avoid this by routing audio to speaker until standby.
4844 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004845 if (is_a2dp_out_device_type(&out->device_list) &&
4846 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004847 !audio_extn_a2dp_source_is_ready() &&
4848 !adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004849 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004850 }
4851 /*
4852 * When USB headset is disconnected the music platback paused
4853 * and the policy manager send routing=0. But if the USB is connected
4854 * back before the standby time, AFE is not closed and opened
4855 * when USB is connected back. So routing to speker will guarantee
4856 * AFE reconfiguration and AFE will be opend once USB is connected again
4857 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004858 if (is_usb_out_device_type(&out->device_list) &&
4859 list_empty(&new_devices) &&
4860 !audio_extn_usb_connected(NULL)) {
4861 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
4862 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004863 /* To avoid a2dp to sco overlapping / BT device improper state
4864 * check with BT lib about a2dp streaming support before routing
4865 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004866 if (is_a2dp_out_device_type(&new_devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004867 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004868 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER) ||
4869 compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004870 //combo usecase just by pass a2dp
4871 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
4872 bypass_a2dp = true;
4873 } else {
4874 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
4875 /* update device to a2dp and don't route as BT returned error
4876 * However it is still possible a2dp routing called because
4877 * of current active device disconnection (like wired headset)
4878 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004879 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004880 pthread_mutex_unlock(&adev->lock);
4881 pthread_mutex_unlock(&out->lock);
4882 goto error;
4883 }
4884 }
4885 }
4886
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004887 // Workaround: If routing to an non existing usb device, fail gracefully
4888 // The routing request will otherwise block during 10 second
4889 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004890 if (is_usb_out_device_type(&new_devices)) {
4891 struct str_parms *parms =
4892 str_parms_create_str(get_usb_device_address(&new_devices));
4893 if (!parms)
4894 goto error;
4895 if ((card = get_alive_usb_card(parms)) >= 0) {
4896 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
4897 pthread_mutex_unlock(&adev->lock);
4898 pthread_mutex_unlock(&out->lock);
4899 str_parms_destroy(parms);
4900 ret = -ENOSYS;
4901 goto error;
4902 }
4903 str_parms_destroy(parms);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004904 }
4905
Weiyin Jiang80c8f9a2020-01-10 20:42:08 +08004906 // Workaround: If routing to an non existing hdmi device, fail gracefully
4907 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4908 (platform_get_edid_info_v2(adev->platform,
4909 out->extconn.cs.controller,
4910 out->extconn.cs.stream) != 0)) {
4911 ALOGW("out_set_parameters() ignoring rerouting to non existing HDMI/DP");
4912 pthread_mutex_unlock(&adev->lock);
4913 pthread_mutex_unlock(&out->lock);
4914 ret = -ENOSYS;
4915 goto error;
4916 }
4917
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004918 /*
4919 * select_devices() call below switches all the usecases on the same
4920 * backend to the new device. Refer to check_usecases_codec_backend() in
4921 * the select_devices(). But how do we undo this?
4922 *
4923 * For example, music playback is active on headset (deep-buffer usecase)
4924 * and if we go to ringtones and select a ringtone, low-latency usecase
4925 * will be started on headset+speaker. As we can't enable headset+speaker
4926 * and headset devices at the same time, select_devices() switches the music
4927 * playback to headset+speaker while starting low-lateny usecase for ringtone.
4928 * So when the ringtone playback is completed, how do we undo the same?
4929 *
4930 * We are relying on the out_set_parameters() call on deep-buffer output,
4931 * once the ringtone playback is ended.
4932 * NOTE: We should not check if the current devices are same as new devices.
4933 * Because select_devices() must be called to switch back the music
4934 * playback to headset.
4935 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004936 if (!list_empty(&new_devices)) {
4937 bool same_dev = compare_devices(&out->device_list, &new_devices);
4938 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004939
4940 if (output_drives_call(adev, out)) {
4941 if (!voice_is_call_state_active(adev)) {
4942 if (adev->mode == AUDIO_MODE_IN_CALL) {
4943 adev->current_call_output = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004944 if (is_usb_out_device_type(&out->device_list)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004945 service_interval =
4946 audio_extn_usb_find_service_interval(true, true /*playback*/);
4947 audio_extn_usb_set_service_interval(true /*playback*/,
4948 service_interval,
4949 &reconfig);
4950 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
4951 }
4952 ret = voice_start_call(adev);
4953 }
4954 } else {
4955 adev->current_call_output = out;
4956 voice_update_devices_for_all_voice_usecases(adev);
4957 }
4958 }
4959
4960 if (!out->standby) {
4961 if (!same_dev) {
4962 ALOGV("update routing change");
4963 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4964 adev->perf_lock_opts,
4965 adev->perf_lock_opts_size);
4966 if (adev->adm_on_routing_change)
4967 adev->adm_on_routing_change(adev->adm_data,
4968 out->handle);
4969 }
4970 if (!bypass_a2dp) {
4971 select_devices(adev, out->usecase);
4972 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004973 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4974 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004975 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004976 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004977 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004978 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004979 }
4980
4981 if (!same_dev) {
4982 // on device switch force swap, lower functions will make sure
4983 // to check if swap is allowed or not.
4984 platform_set_swap_channels(adev, true);
4985 audio_extn_perf_lock_release(&adev->perf_lock_handle);
4986 }
4987 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
4988 out->a2dp_compress_mute &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004989 (!is_a2dp_out_device_type(&out->device_list) || audio_extn_a2dp_source_is_ready())) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004990 pthread_mutex_lock(&out->compr_mute_lock);
4991 out->a2dp_compress_mute = false;
4992 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
4993 pthread_mutex_unlock(&out->compr_mute_lock);
4994 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
4995 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
4996 }
4997 }
4998 }
4999
5000 pthread_mutex_unlock(&adev->lock);
5001 pthread_mutex_unlock(&out->lock);
5002
5003 /*handles device and call state changes*/
5004 audio_extn_extspk_update(adev->extspk);
5005
5006error:
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005007 ALOGV("%s: exit: code(%d)", __func__, ret);
5008 return ret;
5009}
5010
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005011static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
5012{
5013 struct stream_out *out = (struct stream_out *)stream;
5014 struct audio_device *adev = out->dev;
5015 struct str_parms *parms;
5016 char value[32];
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005017 int ret = 0, err;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005018 int ext_controller = -1;
5019 int ext_stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005020
sangwoobc677242013-08-08 16:53:43 +09005021 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005022 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005023 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305024 if (!parms)
5025 goto error;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005026
5027 err = platform_get_controller_stream_from_params(parms, &ext_controller,
5028 &ext_stream);
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08005029 if (err == 0) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005030 out->extconn.cs.controller = ext_controller;
5031 out->extconn.cs.stream = ext_stream;
5032 ALOGD("%s: usecase(%s) new controller/stream (%d/%d)", __func__,
5033 use_case_table[out->usecase], out->extconn.cs.controller,
5034 out->extconn.cs.stream);
5035 }
5036
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005037 if (out == adev->primary_output) {
5038 pthread_mutex_lock(&adev->lock);
5039 audio_extn_set_parameters(adev, parms);
5040 pthread_mutex_unlock(&adev->lock);
5041 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005042 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005043 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005044 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005045
5046 audio_extn_dts_create_state_notifier_node(out->usecase);
5047 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5048 popcount(out->channel_mask),
5049 out->playback_started);
5050
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08005051 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005052 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005053
Surendar Karkaf51b5842018-04-26 11:28:38 +05305054 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
5055 sizeof(value));
5056 if (err >= 0) {
5057 if (!strncmp("true", value, sizeof("true")) || atoi(value))
5058 audio_extn_send_dual_mono_mixing_coefficients(out);
5059 }
5060
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305061 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5062 if (err >= 0) {
5063 strlcpy(out->profile, value, sizeof(out->profile));
5064 ALOGV("updating stream profile with value '%s'", out->profile);
5065 lock_output_stream(out);
5066 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
5067 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005068 &out->device_list, out->flags,
5069 out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305070 out->sample_rate, out->bit_width,
5071 out->channel_mask, out->profile,
5072 &out->app_type_cfg);
5073 pthread_mutex_unlock(&out->lock);
5074 }
5075
Alexy Joseph98988832017-01-13 14:56:59 -08005076 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005077 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
5078 // and vendor.audio.hal.output.suspend.supported is set to true
5079 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08005080 //check suspend parameter only for low latency and if the property
5081 //is enabled
5082 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
5083 ALOGI("%s: got suspend_playback %s", __func__, value);
5084 lock_output_stream(out);
5085 if (!strncmp(value, "false", 5)) {
5086 //suspend_playback=false is supposed to set QOS value back to 75%
5087 //the mixer control sent with value Enable will achieve that
5088 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5089 } else if (!strncmp (value, "true", 4)) {
5090 //suspend_playback=true is supposed to remove QOS value
5091 //resetting the mixer control will set the default value
5092 //for the mixer control which is Disable and this removes the QOS vote
5093 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5094 } else {
5095 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
5096 " got %s", __func__, value);
5097 ret = -1;
5098 }
5099
5100 if (ret != 0) {
5101 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
5102 __func__, out->pm_qos_mixer_path, ret);
5103 }
5104
5105 pthread_mutex_unlock(&out->lock);
5106 }
5107 }
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005108
Alexy Joseph98988832017-01-13 14:56:59 -08005109 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005110 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305111error:
Eric Laurent994a6932013-07-17 11:51:42 -07005112 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005113 return ret;
5114}
5115
Paul McLeana50b7332018-12-17 08:24:21 -07005116static int in_set_microphone_direction(const struct audio_stream_in *stream,
5117 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07005118 struct stream_in *in = (struct stream_in *)stream;
5119
5120 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
5121
5122 in->direction = dir;
5123
5124 if (in->standby)
5125 return 0;
5126
5127 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07005128}
5129
5130static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07005131 struct stream_in *in = (struct stream_in *)stream;
5132
5133 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
5134
5135 if (zoom > 1.0 || zoom < -1.0)
5136 return -EINVAL;
5137
5138 in->zoom = zoom;
5139
5140 if (in->standby)
5141 return 0;
5142
5143 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07005144}
5145
5146
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005147static bool stream_get_parameter_channels(struct str_parms *query,
5148 struct str_parms *reply,
5149 audio_channel_mask_t *supported_channel_masks) {
5150 int ret = -1;
5151 char value[512];
5152 bool first = true;
5153 size_t i, j;
5154
5155 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
5156 ret = 0;
5157 value[0] = '\0';
5158 i = 0;
5159 while (supported_channel_masks[i] != 0) {
5160 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5161 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
5162 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305163 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005164
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305165 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005166 first = false;
5167 break;
5168 }
5169 }
5170 i++;
5171 }
5172 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5173 }
5174 return ret == 0;
5175}
5176
5177static bool stream_get_parameter_formats(struct str_parms *query,
5178 struct str_parms *reply,
5179 audio_format_t *supported_formats) {
5180 int ret = -1;
5181 char value[256];
5182 size_t i, j;
5183 bool first = true;
5184
5185 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
5186 ret = 0;
5187 value[0] = '\0';
5188 i = 0;
5189 while (supported_formats[i] != 0) {
5190 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5191 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
5192 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305193 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005194 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305195 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005196 first = false;
5197 break;
5198 }
5199 }
5200 i++;
5201 }
5202 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
5203 }
5204 return ret == 0;
5205}
5206
5207static bool stream_get_parameter_rates(struct str_parms *query,
5208 struct str_parms *reply,
5209 uint32_t *supported_sample_rates) {
5210
5211 int i;
5212 char value[256];
5213 int ret = -1;
5214 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
5215 ret = 0;
5216 value[0] = '\0';
5217 i=0;
5218 int cursor = 0;
5219 while (supported_sample_rates[i]) {
5220 int avail = sizeof(value) - cursor;
5221 ret = snprintf(value + cursor, avail, "%s%d",
5222 cursor > 0 ? "|" : "",
5223 supported_sample_rates[i]);
5224 if (ret < 0 || ret >= avail) {
5225 // if cursor is at the last element of the array
5226 // overwrite with \0 is duplicate work as
5227 // snprintf already put a \0 in place.
5228 // else
5229 // we had space to write the '|' at value[cursor]
5230 // (which will be overwritten) or no space to fill
5231 // the first element (=> cursor == 0)
5232 value[cursor] = '\0';
5233 break;
5234 }
5235 cursor += ret;
5236 ++i;
5237 }
5238 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
5239 value);
5240 }
5241 return ret >= 0;
5242}
5243
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005244static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
5245{
5246 struct stream_out *out = (struct stream_out *)stream;
5247 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005248 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005249 char value[256];
5250 struct str_parms *reply = str_parms_create();
5251 size_t i, j;
5252 int ret;
5253 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005254
5255 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005256 if (reply) {
5257 str_parms_destroy(reply);
5258 }
5259 if (query) {
5260 str_parms_destroy(query);
5261 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005262 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
5263 return NULL;
5264 }
5265
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005266 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005267 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
5268 if (ret >= 0) {
5269 value[0] = '\0';
5270 i = 0;
5271 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005272 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5273 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005274 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005275 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005276 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005277 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005278 first = false;
5279 break;
5280 }
5281 }
5282 i++;
5283 }
5284 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5285 str = str_parms_to_str(reply);
5286 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005287 voice_extn_out_get_parameters(out, query, reply);
5288 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005289 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005290
Alexy Joseph62142aa2015-11-16 15:10:34 -08005291
5292 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
5293 if (ret >= 0) {
5294 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05305295 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
5296 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08005297 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305298 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005299 } else {
5300 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05305301 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005302 }
5303 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005304 if (str)
5305 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08005306 str = str_parms_to_str(reply);
5307 }
5308
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005309 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
5310 if (ret >= 0) {
5311 value[0] = '\0';
5312 i = 0;
5313 first = true;
5314 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005315 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5316 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005317 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005318 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005319 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005320 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005321 first = false;
5322 break;
5323 }
5324 }
5325 i++;
5326 }
5327 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005328 if (str)
5329 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005330 str = str_parms_to_str(reply);
5331 }
Mingming Yin3a941d42016-02-17 18:08:05 -08005332
5333 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
5334 if (ret >= 0) {
5335 value[0] = '\0';
5336 i = 0;
5337 first = true;
5338 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005339 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
5340 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005341 if (!first) {
5342 strlcat(value, "|", sizeof(value));
5343 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005344 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08005345 first = false;
5346 break;
5347 }
5348 }
5349 i++;
5350 }
5351 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
5352 if (str)
5353 free(str);
5354 str = str_parms_to_str(reply);
5355 }
5356
Alexy Joseph98988832017-01-13 14:56:59 -08005357 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
5358 //only low latency track supports suspend_resume
5359 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005360 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08005361 if (str)
5362 free(str);
5363 str = str_parms_to_str(reply);
5364 }
5365
5366
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005367 str_parms_destroy(query);
5368 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07005369 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005370 return str;
5371}
5372
5373static uint32_t out_get_latency(const struct audio_stream_out *stream)
5374{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005375 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005376 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08005377 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005378
Alexy Josephaa54c872014-12-03 02:46:47 -08005379 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05305380 lock_output_stream(out);
5381 latency = audio_extn_utils_compress_get_dsp_latency(out);
5382 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005383 } else if ((out->realtime) ||
5384 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005385 // since the buffer won't be filled up faster than realtime,
5386 // return a smaller number
5387 if (out->config.rate)
5388 period_ms = (out->af_period_multiplier * out->config.period_size *
5389 1000) / (out->config.rate);
5390 else
5391 period_ms = 0;
George Gao9ba8a142020-07-23 14:30:03 -07005392 latency = period_ms + platform_render_latency(out) / 1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005393 } else {
5394 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005395 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08005396 }
5397
Zhou Songd2537a02020-06-11 22:04:46 +08005398 if (!out->standby && is_a2dp_out_device_type(&out->device_list))
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08005399 latency += audio_extn_a2dp_get_encoder_latency();
5400
Anish Kumar50ebcbf2014-12-09 04:01:39 +05305401 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08005402 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005403}
5404
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305405static float AmpToDb(float amplification)
5406{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305407 float db = DSD_VOLUME_MIN_DB;
5408 if (amplification > 0) {
5409 db = 20 * log10(amplification);
5410 if(db < DSD_VOLUME_MIN_DB)
5411 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305412 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305413 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305414}
5415
Arun Mirpuri5d170872019-03-26 13:21:31 -07005416static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
5417 float right)
5418{
5419 struct stream_out *out = (struct stream_out *)stream;
5420 long volume = 0;
5421 char mixer_ctl_name[128] = "";
5422 struct audio_device *adev = out->dev;
5423 struct mixer_ctl *ctl = NULL;
5424 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5425 PCM_PLAYBACK);
5426
5427 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5428 "Playback %d Volume", pcm_device_id);
5429 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5430 if (!ctl) {
5431 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5432 __func__, mixer_ctl_name);
5433 return -EINVAL;
5434 }
5435 if (left != right)
5436 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
5437 __func__, left, right);
5438 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
5439 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
5440 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
5441 __func__, mixer_ctl_name, volume);
5442 return -EINVAL;
5443 }
5444 return 0;
5445}
5446
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305447static int out_set_compr_volume(struct audio_stream_out *stream, float left,
5448 float right)
5449{
5450 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305451 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305452 char mixer_ctl_name[128];
5453 struct audio_device *adev = out->dev;
5454 struct mixer_ctl *ctl;
5455 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5456 PCM_PLAYBACK);
5457
5458 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5459 "Compress Playback %d Volume", pcm_device_id);
5460 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5461 if (!ctl) {
5462 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5463 __func__, mixer_ctl_name);
5464 return -EINVAL;
5465 }
5466 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
5467 __func__, mixer_ctl_name, left, right);
5468 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
5469 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
5470 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5471
5472 return 0;
5473}
5474
Zhou Song2b8f28f2017-09-11 10:51:38 +08005475static int out_set_voip_volume(struct audio_stream_out *stream, float left,
5476 float right)
5477{
5478 struct stream_out *out = (struct stream_out *)stream;
5479 char mixer_ctl_name[] = "App Type Gain";
5480 struct audio_device *adev = out->dev;
5481 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305482 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08005483
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07005484 if (!is_valid_volume(left, right)) {
5485 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
5486 __func__, left, right);
5487 return -EINVAL;
5488 }
5489
Zhou Song2b8f28f2017-09-11 10:51:38 +08005490 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5491 if (!ctl) {
5492 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5493 __func__, mixer_ctl_name);
5494 return -EINVAL;
5495 }
5496
5497 set_values[0] = 0; //0: Rx Session 1:Tx Session
5498 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305499 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
5500 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005501
5502 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
5503 return 0;
5504}
5505
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305506static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
5507 float right)
5508{
5509 struct stream_out *out = (struct stream_out *)stream;
5510 /* Volume control for pcm playback */
5511 if (left != right) {
5512 return -EINVAL;
5513 } else {
5514 char mixer_ctl_name[128];
5515 struct audio_device *adev = out->dev;
5516 struct mixer_ctl *ctl;
5517 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5518 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
5519 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5520 if (!ctl) {
5521 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5522 return -EINVAL;
5523 }
5524
5525 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
5526 int ret = mixer_ctl_set_value(ctl, 0, volume);
5527 if (ret < 0) {
5528 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
5529 return -EINVAL;
5530 }
5531
5532 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
5533
5534 return 0;
5535 }
5536}
5537
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005538static int out_set_volume(struct audio_stream_out *stream, float left,
5539 float right)
5540{
Eric Laurenta9024de2013-04-04 09:19:12 -07005541 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005542 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305543 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005544
Arun Mirpuri5d170872019-03-26 13:21:31 -07005545 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07005546 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
5547 /* only take left channel into account: the API is for stereo anyway */
5548 out->muted = (left == 0.0f);
5549 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005550 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305551 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005552 /*
5553 * Set mute or umute on HDMI passthrough stream.
5554 * Only take left channel into account.
5555 * Mute is 0 and unmute 1
5556 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305557 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305558 } else if (out->format == AUDIO_FORMAT_DSD){
5559 char mixer_ctl_name[128] = "DSD Volume";
5560 struct audio_device *adev = out->dev;
5561 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5562
5563 if (!ctl) {
5564 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5565 __func__, mixer_ctl_name);
5566 return -EINVAL;
5567 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05305568 volume[0] = (long)(AmpToDb(left));
5569 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305570 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5571 return 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005572 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS) &&
Derek Chendf05eea2019-08-01 13:57:49 -07005573 (out->car_audio_stream == CAR_AUDIO_STREAM_MEDIA)) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005574 ALOGD("%s: Overriding offload set volume for media bus stream", __func__);
5575 struct listnode *node = NULL;
5576 list_for_each(node, &adev->active_outputs_list) {
5577 streams_output_ctxt_t *out_ctxt = node_to_item(node,
5578 streams_output_ctxt_t,
5579 list);
5580 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
5581 out->volume_l = out_ctxt->output->volume_l;
5582 out->volume_r = out_ctxt->output->volume_r;
5583 }
5584 }
5585 if (!out->a2dp_compress_mute) {
5586 ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5587 }
5588 return ret;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005589 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305590 pthread_mutex_lock(&out->compr_mute_lock);
Arun Mirpuri5d170872019-03-26 13:21:31 -07005591 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305592 if (!out->a2dp_compress_mute)
5593 ret = out_set_compr_volume(stream, left, right);
5594 out->volume_l = left;
5595 out->volume_r = right;
5596 pthread_mutex_unlock(&out->compr_mute_lock);
5597 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005598 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005599 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005600 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
5601 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
5602 if (!out->standby) {
5603 audio_extn_utils_send_app_type_gain(out->dev,
5604 out->app_type_cfg.app_type,
5605 &out->app_type_cfg.gain[0]);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005606 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08005607 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08005608 out->volume_l = left;
5609 out->volume_r = right;
5610 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005611 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5612 ALOGV("%s: MMAP set volume called", __func__);
5613 if (!out->standby)
5614 ret = out_set_mmap_volume(stream, left, right);
5615 out->volume_l = left;
5616 out->volume_r = right;
5617 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305618 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05305619 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5620 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305621 /* Volume control for pcm playback */
5622 if (!out->standby)
5623 ret = out_set_pcm_volume(stream, left, right);
5624 else
5625 out->apply_volume = true;
5626
5627 out->volume_l = left;
5628 out->volume_r = right;
5629 return ret;
Derek Chenf13dd492018-11-13 14:53:51 -08005630 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
5631 ALOGV("%s: bus device set volume called", __func__);
5632 if (!out->standby)
5633 ret = out_set_pcm_volume(stream, left, right);
5634 out->volume_l = left;
5635 out->volume_r = right;
5636 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07005637 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005638
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005639 return -ENOSYS;
5640}
5641
Zhou Songc9672822017-08-16 16:01:39 +08005642static void update_frames_written(struct stream_out *out, size_t bytes)
5643{
5644 size_t bpf = 0;
5645
5646 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
5647 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
5648 bpf = 1;
5649 else if (!is_offload_usecase(out->usecase))
5650 bpf = audio_bytes_per_sample(out->format) *
5651 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08005652
5653 pthread_mutex_lock(&out->position_query_lock);
5654 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08005655 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08005656 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
5657 }
5658 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08005659}
5660
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005661int split_and_write_audio_haptic_data(struct stream_out *out,
5662 const void *buffer, size_t bytes_to_write)
5663{
5664 struct audio_device *adev = out->dev;
5665
5666 int ret = 0;
5667 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5668 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
5669 size_t frame_size = channel_count * bytes_per_sample;
5670 size_t frame_count = bytes_to_write / frame_size;
5671
5672 bool force_haptic_path =
5673 property_get_bool("vendor.audio.test_haptic", false);
5674
5675 // extract Haptics data from Audio buffer
5676 bool alloc_haptic_buffer = false;
5677 int haptic_channel_count = adev->haptics_config.channels;
5678 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
5679 size_t audio_frame_size = frame_size - haptic_frame_size;
5680 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
5681
5682 if (adev->haptic_buffer == NULL) {
5683 alloc_haptic_buffer = true;
5684 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
5685 free(adev->haptic_buffer);
5686 adev->haptic_buffer_size = 0;
5687 alloc_haptic_buffer = true;
5688 }
5689
5690 if (alloc_haptic_buffer) {
5691 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08005692 if(adev->haptic_buffer == NULL) {
5693 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
5694 return -ENOMEM;
5695 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005696 adev->haptic_buffer_size = total_haptic_buffer_size;
5697 }
5698
5699 size_t src_index = 0, aud_index = 0, hap_index = 0;
5700 uint8_t *audio_buffer = (uint8_t *)buffer;
5701 uint8_t *haptic_buffer = adev->haptic_buffer;
5702
5703 // This is required for testing only. This works for stereo data only.
5704 // One channel is fed to audio stream and other to haptic stream for testing.
5705 if (force_haptic_path)
5706 audio_frame_size = haptic_frame_size = bytes_per_sample;
5707
5708 for (size_t i = 0; i < frame_count; i++) {
5709 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
5710 audio_frame_size);
5711 aud_index += audio_frame_size;
5712 src_index += audio_frame_size;
5713
5714 if (adev->haptic_pcm)
5715 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
5716 haptic_frame_size);
5717 hap_index += haptic_frame_size;
5718 src_index += haptic_frame_size;
5719
5720 // This is required for testing only.
5721 // Discard haptic channel data.
5722 if (force_haptic_path)
5723 src_index += haptic_frame_size;
5724 }
5725
5726 // write to audio pipeline
5727 ret = pcm_write(out->pcm, (void *)audio_buffer,
5728 frame_count * audio_frame_size);
5729
5730 // write to haptics pipeline
5731 if (adev->haptic_pcm)
5732 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
5733 frame_count * haptic_frame_size);
5734
5735 return ret;
5736}
5737
Aalique Grahame22e49102018-12-18 14:23:57 -08005738#ifdef NO_AUDIO_OUT
5739static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
5740 const void *buffer __unused, size_t bytes)
5741{
5742 struct stream_out *out = (struct stream_out *)stream;
5743
5744 /* No Output device supported other than BT for playback.
5745 * Sleep for the amount of buffer duration
5746 */
5747 lock_output_stream(out);
5748 usleep(bytes * 1000000 / audio_stream_out_frame_size(
5749 (const struct audio_stream_out *)&out->stream) /
5750 out_get_sample_rate(&out->stream.common));
5751 pthread_mutex_unlock(&out->lock);
5752 return bytes;
5753}
5754#endif
5755
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005756static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
5757 size_t bytes)
5758{
5759 struct stream_out *out = (struct stream_out *)stream;
5760 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07005761 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305762 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005763 const size_t frame_size = audio_stream_out_frame_size(stream);
5764 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305765 struct audio_usecase *usecase = NULL;
Meng Wang4c32fb42020-01-16 17:57:11 +08005766 uint32_t compr_passthr = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005767
Haynes Mathew George380745d2017-10-04 15:27:45 -07005768 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005769 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305770
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305771 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08005772
Dhananjay Kumarac341582017-02-23 23:42:25 +05305773 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305774 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05305775 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
5776 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005777 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305778 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05305779 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05305780 ALOGD(" %s: sound card is not active/SSR state", __func__);
5781 ret= -EIO;
5782 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305783 }
5784 }
5785
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305786 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305787 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305788 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305789 goto exit;
5790 }
5791
Haynes Mathew George16081042017-05-31 17:16:49 -07005792 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5793 ret = -EINVAL;
5794 goto exit;
5795 }
5796
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005797 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305798 !out->is_iec61937_info_available) {
5799
5800 if (!audio_extn_passthru_is_passthrough_stream(out)) {
5801 out->is_iec61937_info_available = true;
5802 } else if (audio_extn_passthru_is_enabled()) {
5803 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05305804 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05305805
5806 if((out->format == AUDIO_FORMAT_DTS) ||
5807 (out->format == AUDIO_FORMAT_DTS_HD)) {
5808 ret = audio_extn_passthru_update_dts_stream_configuration(out,
5809 buffer, bytes);
5810 if (ret) {
5811 if (ret != -ENOSYS) {
5812 out->is_iec61937_info_available = false;
5813 ALOGD("iec61937 transmission info not yet updated retry");
5814 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305815 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05305816 /* if stream has started and after that there is
5817 * stream config change (iec transmission config)
5818 * then trigger select_device to update backend configuration.
5819 */
5820 out->stream_config_changed = true;
5821 pthread_mutex_lock(&adev->lock);
5822 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305823 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08005824 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305825 ret = -EINVAL;
5826 goto exit;
5827 }
Manish Dewangan671a4202017-08-18 17:30:46 +05305828 pthread_mutex_unlock(&adev->lock);
5829 out->stream_config_changed = false;
5830 out->is_iec61937_info_available = true;
5831 }
5832 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305833
Meng Wang4c32fb42020-01-16 17:57:11 +08005834#ifdef AUDIO_GKI_ENABLED
5835 /* out->compr_config.codec->reserved[0] is for compr_passthr */
5836 compr_passthr = out->compr_config.codec->reserved[0];
5837#else
5838 compr_passthr = out->compr_config.codec->compr_passthr;
5839#endif
5840
Garmond Leung317cbf12017-09-13 16:20:50 -07005841 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Meng Wang4c32fb42020-01-16 17:57:11 +08005842 (compr_passthr == PASSTHROUGH) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305843 (out->is_iec61937_info_available == true)) {
5844 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
5845 ret = -EINVAL;
5846 goto exit;
5847 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05305848 }
5849 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305850
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005851 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02005852 (audio_extn_a2dp_source_is_suspended())) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005853 if (!(compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER) ||
5854 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305855 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305856 ret = -EIO;
5857 goto exit;
5858 }
5859 }
5860 }
5861
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005862 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005863 out->standby = false;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005864 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
5865
Eric Laurent150dbfe2013-02-27 14:31:02 -08005866 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005867 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
5868 ret = voice_extn_compress_voip_start_output_stream(out);
5869 else
5870 ret = start_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005871 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005872 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005873 out->standby = true;
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005874 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005875 goto exit;
5876 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305877 out->started = 1;
Andy Hunga1f48fa2019-07-01 18:14:53 -07005878 out->last_fifo_valid = false; // we're coming out of standby, last_fifo isn't valid.
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005879
5880 if ((last_known_cal_step != -1) && (adev->platform != NULL)) {
vivek mehtab72d08d2016-04-29 03:16:47 -07005881 ALOGD("%s: retry previous failed cal level set", __func__);
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005882 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05305883 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005884 }
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005885 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305886
5887 if ((out->is_iec61937_info_available == true) &&
5888 (audio_extn_passthru_is_passthrough_stream(out))&&
5889 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
5890 ret = -EINVAL;
5891 goto exit;
5892 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05305893 if (out->set_dual_mono)
5894 audio_extn_send_dual_mono_mixing_coefficients(out);
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005895
5896 // log startup time in ms.
5897 simple_stats_log(
5898 &out->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005899 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005900
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005901 if (adev->is_channel_status_set == false &&
5902 compare_device_type(&out->device_list,
5903 AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Alexy Josephb1379942016-01-29 15:49:38 -08005904 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05305905 adev->is_channel_status_set = true;
5906 }
5907
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305908 if ((adev->use_old_pspd_mix_ctrl == true) &&
5909 (out->pspd_coeff_sent == false)) {
5910 /*
5911 * Need to resend pspd coefficients after stream started for
5912 * older kernel version as it does not save the coefficients
5913 * and also stream has to be started for coeff to apply.
5914 */
5915 usecase = get_usecase_from_list(adev, out->usecase);
5916 if (usecase != NULL) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05305917 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305918 out->pspd_coeff_sent = true;
5919 }
5920 }
5921
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005922 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08005923 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005924 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005925 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005926 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
5927 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305928 if (out->send_next_track_params && out->is_compr_metadata_avail) {
5929 ALOGD("copl(%p):send next track params in gapless", out);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08005930 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305931 out->send_next_track_params = false;
5932 out->is_compr_metadata_avail = false;
5933 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005934 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05305935 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305936 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005937
Ashish Jain83a6cc22016-06-28 14:34:17 +05305938 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305939 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05305940 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05305941 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005942 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05305943 return -EINVAL;
5944 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05305945 audio_format_t dst_format = out->hal_op_format;
5946 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305947
Dieter Luecking5d57def2018-09-07 14:23:37 +02005948 /* prevent division-by-zero */
5949 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
5950 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
5951 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
5952 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05305953 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005954 ATRACE_END();
5955 return -EINVAL;
5956 }
5957
Ashish Jainf1eaa582016-05-23 20:54:24 +05305958 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
5959 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
5960
Ashish Jain83a6cc22016-06-28 14:34:17 +05305961 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305962 dst_format,
5963 buffer,
5964 src_format,
5965 frames);
5966
Ashish Jain83a6cc22016-06-28 14:34:17 +05305967 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305968 bytes_to_write);
5969
5970 /*Convert written bytes in audio flinger format*/
5971 if (ret > 0)
5972 ret = ((ret * format_to_bitwidth_table[out->format]) /
5973 format_to_bitwidth_table[dst_format]);
5974 }
5975 } else
5976 ret = compress_write(out->compr, buffer, bytes);
5977
Zhou Songc9672822017-08-16 16:01:39 +08005978 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
5979 update_frames_written(out, bytes);
5980
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305981 if (ret < 0)
5982 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08005983 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05305984 /*msg to cb thread only if non blocking write is enabled*/
5985 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05305986 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005987 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05305988 } else if (-ENETRESET == ret) {
5989 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305990 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05305991 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05305992 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005993 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305994 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005995 }
Ashish Jain5106d362016-05-11 19:23:33 +05305996
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05305997 /* Call compr start only when non-zero bytes of data is there to be rendered */
5998 if (!out->playback_started && ret > 0) {
5999 int status = compress_start(out->compr);
6000 if (status < 0) {
6001 ret = status;
6002 ALOGE("%s: compr start failed with err %d", __func__, errno);
6003 goto exit;
6004 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07006005 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006006 out->playback_started = 1;
6007 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006008
6009 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6010 popcount(out->channel_mask),
6011 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006012 }
6013 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006014 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006015 return ret;
6016 } else {
6017 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006018 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006019 if (out->muted)
6020 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006021 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
6022 __func__, frames, frame_size, bytes_to_write);
6023
Aalique Grahame22e49102018-12-18 14:23:57 -08006024 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07006025 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
6026 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
6027 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006028 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
6029 int16_t *src = (int16_t *)buffer;
6030 int16_t *dst = (int16_t *)buffer;
6031
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006032 LOG_ALWAYS_FATAL_IF(channel_count > 2 ||
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006033 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08006034 "out_write called for %s use case with wrong properties",
6035 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006036
6037 /*
6038 * FIXME: this can be removed once audio flinger mixer supports
6039 * mono output
6040 */
6041
6042 /*
6043 * Code below goes over each frame in the buffer and adds both
6044 * L and R samples and then divides by 2 to convert to mono
6045 */
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006046 if (channel_count == 2) {
6047 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
6048 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
6049 }
6050 bytes_to_write /= 2;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006051 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006052 }
Andy Hunga1f48fa2019-07-01 18:14:53 -07006053
6054 // Note: since out_get_presentation_position() is called alternating with out_write()
6055 // by AudioFlinger, we can check underruns using the prior timestamp read.
6056 // (Alternately we could check if the buffer is empty using pcm_get_htimestamp().
6057 if (out->last_fifo_valid) {
6058 // compute drain to see if there is an underrun.
6059 const int64_t current_ns = systemTime(SYSTEM_TIME_MONOTONIC); // sys call
Dhananjay Kumara4429632020-07-11 02:53:37 +05306060 int64_t time_diff_ns = current_ns - out->last_fifo_time_ns;
6061 int64_t frames_by_time =
6062 ((time_diff_ns > 0) && (time_diff_ns < (INT64_MAX / out->config.rate))) ?
6063 (time_diff_ns * out->config.rate / NANOS_PER_SECOND) : 0;
Andy Hunga1f48fa2019-07-01 18:14:53 -07006064 const int64_t underrun = frames_by_time - out->last_fifo_frames_remaining;
6065
6066 if (underrun > 0) {
6067 simple_stats_log(&out->fifo_underruns, underrun);
6068
6069 ALOGW("%s: underrun(%lld) "
6070 "frames_by_time(%lld) > out->last_fifo_frames_remaining(%lld)",
6071 __func__,
6072 (long long)out->fifo_underruns.n,
6073 (long long)frames_by_time,
6074 (long long)out->last_fifo_frames_remaining);
6075 }
6076 out->last_fifo_valid = false; // we're writing below, mark fifo info as stale.
6077 }
6078
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306079 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006080
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006081 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006082
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006083 if (out->config.rate)
6084 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
6085 out->config.rate;
6086
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006087 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006088 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
6089
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006090 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006091 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006092 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306093 out->convert_buffer != NULL) {
6094
6095 memcpy_by_audio_format(out->convert_buffer,
6096 out->hal_op_format,
6097 buffer,
6098 out->hal_ip_format,
6099 out->config.period_size * out->config.channels);
6100
6101 ret = pcm_write(out->pcm, out->convert_buffer,
6102 (out->config.period_size *
6103 out->config.channels *
6104 format_to_bitwidth_table[out->hal_op_format]));
6105 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05306106 /*
6107 * To avoid underrun in DSP when the application is not pumping
6108 * data at required rate, check for the no. of bytes and ignore
6109 * pcm_write if it is less than actual buffer size.
6110 * It is a work around to a change in compress VOIP driver.
6111 */
6112 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
6113 bytes < (out->config.period_size * out->config.channels *
6114 audio_bytes_per_sample(out->format))) {
6115 size_t voip_buf_size =
6116 out->config.period_size * out->config.channels *
6117 audio_bytes_per_sample(out->format);
6118 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
6119 __func__, bytes, voip_buf_size);
6120 usleep(((uint64_t)voip_buf_size - bytes) *
6121 1000000 / audio_stream_out_frame_size(stream) /
6122 out_get_sample_rate(&out->stream.common));
6123 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006124 } else {
6125 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
6126 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
6127 else
6128 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
6129 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306130 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006131
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006132 release_out_focus(out);
6133
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306134 if (ret < 0)
6135 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08006136 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05306137 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006138 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006139 }
6140
6141exit:
Zhou Songc9672822017-08-16 16:01:39 +08006142 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306143 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306144 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306145 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006146 pthread_mutex_unlock(&out->lock);
6147
6148 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006149 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08006150 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306151 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306152 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306153 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306154 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306155 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306156 out->standby = true;
6157 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306158 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006159 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
6160 /* prevent division-by-zero */
6161 uint32_t stream_size = audio_stream_out_frame_size(stream);
6162 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006163
Dieter Luecking5d57def2018-09-07 14:23:37 +02006164 if ((stream_size == 0) || (srate == 0)) {
6165 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
6166 ATRACE_END();
6167 return -EINVAL;
6168 }
6169 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
6170 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006171 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05306172 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006173 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006174 return ret;
6175 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006176 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07006177 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006178 return bytes;
6179}
6180
6181static int out_get_render_position(const struct audio_stream_out *stream,
6182 uint32_t *dsp_frames)
6183{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006184 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08006185
6186 if (dsp_frames == NULL)
6187 return -EINVAL;
6188
6189 *dsp_frames = 0;
6190 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08006191 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05306192
6193 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
6194 * this operation and adev_close_output_stream(where out gets reset).
6195 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05306196 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006197 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05306198 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006199 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05306200 return 0;
6201 }
6202
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006203 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05306204 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306205 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006206 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306207 if (ret < 0)
6208 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006209 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05306210 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006211 }
Naresh Tanniru80659832014-06-04 18:17:56 +05306212 if (-ENETRESET == ret) {
6213 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306214 out->card_status = CARD_STATUS_OFFLINE;
6215 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306216 } else if(ret < 0) {
6217 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306218 ret = -EINVAL;
6219 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05306220 /*
6221 * Handle corner case where compress session is closed during SSR
6222 * and timestamp is queried
6223 */
6224 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306225 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306226 } else if (out->prev_card_status_offline) {
6227 ALOGE("ERROR: previously sound card was offline,return error");
6228 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306229 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306230 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006231 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05306232 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306233 pthread_mutex_unlock(&out->lock);
6234 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08006235 } else if (audio_is_linear_pcm(out->format)) {
6236 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006237 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08006238 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006239 } else
6240 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006241}
6242
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006243static int out_add_audio_effect(const struct audio_stream *stream __unused,
6244 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006245{
6246 return 0;
6247}
6248
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006249static int out_remove_audio_effect(const struct audio_stream *stream __unused,
6250 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006251{
6252 return 0;
6253}
6254
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006255static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
6256 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006257{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05306258 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006259}
6260
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006261static int out_get_presentation_position(const struct audio_stream_out *stream,
6262 uint64_t *frames, struct timespec *timestamp)
6263{
6264 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05306265 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07006266 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006267
Ashish Jain5106d362016-05-11 19:23:33 +05306268 /* below piece of code is not guarded against any lock because audioFliner serializes
6269 * this operation and adev_close_output_stream( where out gets reset).
6270 */
6271 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05306272 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006273 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05306274 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
6275 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
6276 return 0;
6277 }
6278
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006279 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006280
Ashish Jain5106d362016-05-11 19:23:33 +05306281 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
6282 ret = compress_get_tstamp(out->compr, &dsp_frames,
6283 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08006284 // Adjustment accounts for A2dp encoder latency with offload usecases
6285 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006286 if (is_a2dp_out_device_type(&out->device_list)) {
yidongh0515e042017-07-06 15:00:34 +08006287 unsigned long offset =
6288 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
6289 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
6290 }
Ashish Jain5106d362016-05-11 19:23:33 +05306291 ALOGVV("%s rendered frames %ld sample_rate %d",
6292 __func__, dsp_frames, out->sample_rate);
6293 *frames = dsp_frames;
6294 if (ret < 0)
6295 ret = -errno;
6296 if (-ENETRESET == ret) {
6297 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306298 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05306299 ret = -EINVAL;
6300 } else
6301 ret = 0;
6302 /* this is the best we can do */
6303 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07006304 } else {
6305 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08006306 unsigned int avail;
6307 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
George Gao62ebc722019-07-29 16:29:44 -07006308 uint64_t signed_frames = 0;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006309 uint64_t frames_temp = 0;
George Gao62ebc722019-07-29 16:29:44 -07006310
Andy Hunga1f48fa2019-07-01 18:14:53 -07006311 if (out->kernel_buffer_size > avail) {
6312 frames_temp = out->last_fifo_frames_remaining = out->kernel_buffer_size - avail;
6313 } else {
6314 ALOGW("%s: avail:%u > kernel_buffer_size:%zu clamping!",
6315 __func__, avail, out->kernel_buffer_size);
6316 avail = out->kernel_buffer_size;
6317 frames_temp = out->last_fifo_frames_remaining = 0;
6318 }
6319 out->last_fifo_valid = true;
6320 out->last_fifo_time_ns = audio_utils_ns_from_timespec(timestamp);
6321
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006322 if (out->written >= frames_temp)
6323 signed_frames = out->written - frames_temp;
George Gao62ebc722019-07-29 16:29:44 -07006324
Andy Hunga1f48fa2019-07-01 18:14:53 -07006325 ALOGVV("%s: frames:%lld avail:%u kernel_buffer_size:%zu",
6326 __func__, (long long)signed_frames, avail, out->kernel_buffer_size);
6327
Weiyin Jiangd4633762018-03-16 12:05:03 +08006328 // This adjustment accounts for buffering after app processor.
6329 // It is based on estimated DSP latency per use case, rather than exact.
George Gao9ba8a142020-07-23 14:30:03 -07006330 frames_temp = platform_render_latency(out) *
Robert Lee58215542019-07-15 20:55:12 +08006331 out->sample_rate / 1000000LL;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006332 if (signed_frames >= frames_temp)
6333 signed_frames -= frames_temp;
Aniket Kumar Lataff613152017-07-18 18:19:21 -07006334
Weiyin Jiangd4633762018-03-16 12:05:03 +08006335 // Adjustment accounts for A2dp encoder latency with non offload usecases
6336 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006337 if (is_a2dp_out_device_type(&out->device_list)) {
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006338 frames_temp = audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000;
6339 if (signed_frames >= frames_temp)
6340 signed_frames -= frames_temp;
Weiyin Jiangd4633762018-03-16 12:05:03 +08006341 }
6342
6343 // It would be unusual for this value to be negative, but check just in case ...
George Gao62ebc722019-07-29 16:29:44 -07006344 *frames = signed_frames;
6345 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006346 }
Eric Laurenta7a33042019-07-10 16:20:22 -07006347 } else if (out->card_status == CARD_STATUS_OFFLINE ||
6348 // audioflinger still needs position updates when A2DP is suspended
Jasmine Cha5c2517f2019-09-09 11:07:28 +08006349 (is_a2dp_out_device_type(&out->device_list) && audio_extn_a2dp_source_is_suspended())) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306350 *frames = out->written;
6351 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306352 if (is_offload_usecase(out->usecase))
6353 ret = -EINVAL;
6354 else
6355 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006356 }
6357 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006358 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006359 return ret;
6360}
6361
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006362static int out_set_callback(struct audio_stream_out *stream,
6363 stream_callback_t callback, void *cookie)
6364{
6365 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006366 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006367
6368 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006369 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006370 out->client_callback = callback;
6371 out->client_cookie = cookie;
6372 if (out->adsp_hdlr_stream_handle) {
6373 ret = audio_extn_adsp_hdlr_stream_set_callback(
6374 out->adsp_hdlr_stream_handle,
6375 callback,
6376 cookie);
6377 if (ret)
6378 ALOGW("%s:adsp hdlr callback registration failed %d",
6379 __func__, ret);
6380 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006381 pthread_mutex_unlock(&out->lock);
6382 return 0;
6383}
6384
6385static int out_pause(struct audio_stream_out* stream)
6386{
6387 struct stream_out *out = (struct stream_out *)stream;
6388 int status = -ENOSYS;
6389 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006390 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006391 ALOGD("copl(%p):pause compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306392 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006393 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006394 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306395 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05306396 status = compress_pause(out->compr);
6397
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006398 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006399
Mingming Yin21854652016-04-13 11:54:02 -07006400 if (audio_extn_passthru_is_active()) {
6401 ALOGV("offload use case, pause passthru");
6402 audio_extn_passthru_on_pause(out);
6403 }
6404
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306405 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006406 audio_extn_dts_notify_playback_state(out->usecase, 0,
6407 out->sample_rate, popcount(out->channel_mask),
6408 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006409 }
6410 pthread_mutex_unlock(&out->lock);
6411 }
6412 return status;
6413}
6414
6415static int out_resume(struct audio_stream_out* stream)
6416{
6417 struct stream_out *out = (struct stream_out *)stream;
6418 int status = -ENOSYS;
6419 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006420 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006421 ALOGD("copl(%p):resume compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306422 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006423 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006424 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306425 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306426 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07006427 }
6428 if (!status) {
6429 out->offload_state = OFFLOAD_STATE_PLAYING;
6430 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306431 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006432 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6433 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006434 }
6435 pthread_mutex_unlock(&out->lock);
6436 }
6437 return status;
6438}
6439
6440static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
6441{
6442 struct stream_out *out = (struct stream_out *)stream;
6443 int status = -ENOSYS;
6444 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006445 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006446 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006447 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
6448 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
6449 else
6450 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
6451 pthread_mutex_unlock(&out->lock);
6452 }
6453 return status;
6454}
6455
6456static int out_flush(struct audio_stream_out* stream)
6457{
6458 struct stream_out *out = (struct stream_out *)stream;
6459 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006460 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006461 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006462 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006463 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
6464 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006465 } else {
6466 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
6467 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08006468 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006469 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006470 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006471 return 0;
6472 }
6473 return -ENOSYS;
6474}
6475
Haynes Mathew George16081042017-05-31 17:16:49 -07006476static int out_stop(const struct audio_stream_out* stream)
6477{
6478 struct stream_out *out = (struct stream_out *)stream;
6479 struct audio_device *adev = out->dev;
6480 int ret = -ENOSYS;
6481
6482 ALOGV("%s", __func__);
6483 pthread_mutex_lock(&adev->lock);
6484 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6485 out->playback_started && out->pcm != NULL) {
6486 pcm_stop(out->pcm);
6487 ret = stop_output_stream(out);
6488 out->playback_started = false;
6489 }
6490 pthread_mutex_unlock(&adev->lock);
6491 return ret;
6492}
6493
6494static int out_start(const struct audio_stream_out* stream)
6495{
6496 struct stream_out *out = (struct stream_out *)stream;
6497 struct audio_device *adev = out->dev;
6498 int ret = -ENOSYS;
6499
6500 ALOGV("%s", __func__);
6501 pthread_mutex_lock(&adev->lock);
6502 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6503 !out->playback_started && out->pcm != NULL) {
6504 ret = start_output_stream(out);
6505 if (ret == 0) {
6506 out->playback_started = true;
6507 }
6508 }
6509 pthread_mutex_unlock(&adev->lock);
6510 return ret;
6511}
6512
6513/*
6514 * Modify config->period_count based on min_size_frames
6515 */
6516static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
6517{
6518 int periodCountRequested = (min_size_frames + config->period_size - 1)
6519 / config->period_size;
6520 int periodCount = MMAP_PERIOD_COUNT_MIN;
6521
6522 ALOGV("%s original config.period_size = %d config.period_count = %d",
6523 __func__, config->period_size, config->period_count);
6524
6525 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
6526 periodCount *= 2;
6527 }
6528 config->period_count = periodCount;
6529
6530 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
6531}
6532
Phil Burkfe17efd2019-03-25 10:23:35 -07006533// Read offset for the positional timestamp from a persistent vendor property.
6534// This is to workaround apparent inaccuracies in the timing information that
6535// is used by the AAudio timing model. The inaccuracies can cause glitches.
6536static int64_t get_mmap_out_time_offset() {
6537 const int32_t kDefaultOffsetMicros = 0;
6538 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006539 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07006540 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
6541 return mmap_time_offset_micros * (int64_t)1000;
6542}
6543
Haynes Mathew George16081042017-05-31 17:16:49 -07006544static int out_create_mmap_buffer(const struct audio_stream_out *stream,
6545 int32_t min_size_frames,
6546 struct audio_mmap_buffer_info *info)
6547{
6548 struct stream_out *out = (struct stream_out *)stream;
6549 struct audio_device *adev = out->dev;
6550 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07006551 unsigned int offset1 = 0;
6552 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006553 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006554 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006555 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07006556
Arun Mirpuri5d170872019-03-26 13:21:31 -07006557 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306558 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07006559 pthread_mutex_lock(&adev->lock);
6560
Sharad Sanglec6f32552018-05-04 16:15:38 +05306561 if (CARD_STATUS_OFFLINE == out->card_status ||
6562 CARD_STATUS_OFFLINE == adev->card_status) {
6563 ALOGW("out->card_status or adev->card_status offline, try again");
6564 ret = -EIO;
6565 goto exit;
6566 }
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306567 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07006568 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
6569 ret = -EINVAL;
6570 goto exit;
6571 }
6572 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
6573 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
6574 ret = -ENOSYS;
6575 goto exit;
6576 }
6577 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
6578 if (out->pcm_device_id < 0) {
6579 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6580 __func__, out->pcm_device_id, out->usecase);
6581 ret = -EINVAL;
6582 goto exit;
6583 }
6584
6585 adjust_mmap_period_count(&out->config, min_size_frames);
6586
Arun Mirpuri5d170872019-03-26 13:21:31 -07006587 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006588 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
6589 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
6590 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306591 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306592 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6593 out->card_status = CARD_STATUS_OFFLINE;
6594 adev->card_status = CARD_STATUS_OFFLINE;
6595 ret = -EIO;
6596 goto exit;
6597 }
6598
Haynes Mathew George16081042017-05-31 17:16:49 -07006599 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
6600 step = "open";
6601 ret = -ENODEV;
6602 goto exit;
6603 }
6604 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
6605 if (ret < 0) {
6606 step = "begin";
6607 goto exit;
6608 }
juyuchen626833d2019-06-04 16:48:02 +08006609
6610 info->flags = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006611 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07006612 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07006613 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006614 ret = platform_get_mmap_data_fd(adev->platform,
6615 out->pcm_device_id, 0 /*playback*/,
6616 &info->shared_memory_fd,
6617 &mmap_size);
6618 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07006619 // Fall back to non exclusive mode
6620 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
6621 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07006622 out->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
6623 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, out->mmap_shared_memory_fd);
6624
Arun Mirpuri5d170872019-03-26 13:21:31 -07006625 if (mmap_size < buffer_size) {
6626 step = "mmap";
6627 goto exit;
6628 }
juyuchen626833d2019-06-04 16:48:02 +08006629 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006630 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006631 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006632 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07006633
6634 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
6635 if (ret < 0) {
6636 step = "commit";
6637 goto exit;
6638 }
6639
Phil Burkfe17efd2019-03-25 10:23:35 -07006640 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
6641
Haynes Mathew George16081042017-05-31 17:16:49 -07006642 out->standby = false;
6643 ret = 0;
6644
Arun Mirpuri5d170872019-03-26 13:21:31 -07006645 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006646 __func__, info->shared_memory_address, info->buffer_size_frames);
6647
6648exit:
6649 if (ret != 0) {
6650 if (out->pcm == NULL) {
6651 ALOGE("%s: %s - %d", __func__, step, ret);
6652 } else {
6653 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
6654 pcm_close(out->pcm);
6655 out->pcm = NULL;
6656 }
6657 }
6658 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306659 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07006660 return ret;
6661}
6662
6663static int out_get_mmap_position(const struct audio_stream_out *stream,
6664 struct audio_mmap_position *position)
6665{
6666 struct stream_out *out = (struct stream_out *)stream;
6667 ALOGVV("%s", __func__);
6668 if (position == NULL) {
6669 return -EINVAL;
6670 }
6671 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08006672 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006673 return -ENOSYS;
6674 }
6675 if (out->pcm == NULL) {
6676 return -ENOSYS;
6677 }
6678
6679 struct timespec ts = { 0, 0 };
6680 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
6681 if (ret < 0) {
6682 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
6683 return ret;
6684 }
Phil Burkfe17efd2019-03-25 10:23:35 -07006685 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
6686 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07006687 return 0;
6688}
6689
6690
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006691/** audio_stream_in implementation **/
6692static uint32_t in_get_sample_rate(const struct audio_stream *stream)
6693{
6694 struct stream_in *in = (struct stream_in *)stream;
6695
6696 return in->config.rate;
6697}
6698
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006699static int in_set_sample_rate(struct audio_stream *stream __unused,
6700 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006701{
6702 return -ENOSYS;
6703}
6704
6705static size_t in_get_buffer_size(const struct audio_stream *stream)
6706{
6707 struct stream_in *in = (struct stream_in *)stream;
6708
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006709 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
6710 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07006711 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
6712 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306713 else if(audio_extn_cin_attached_usecase(in))
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306714 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006715
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006716 return in->config.period_size * in->af_period_multiplier *
6717 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006718}
6719
6720static uint32_t in_get_channels(const struct audio_stream *stream)
6721{
6722 struct stream_in *in = (struct stream_in *)stream;
6723
6724 return in->channel_mask;
6725}
6726
6727static audio_format_t in_get_format(const struct audio_stream *stream)
6728{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006729 struct stream_in *in = (struct stream_in *)stream;
6730
6731 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006732}
6733
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006734static int in_set_format(struct audio_stream *stream __unused,
6735 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006736{
6737 return -ENOSYS;
6738}
6739
6740static int in_standby(struct audio_stream *stream)
6741{
6742 struct stream_in *in = (struct stream_in *)stream;
6743 struct audio_device *adev = in->dev;
6744 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306745 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
6746 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006747 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306748
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006749 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006750 if (!in->standby && in->is_st_session) {
6751 ALOGD("%s: sound trigger pcm stop lab", __func__);
6752 audio_extn_sound_trigger_stop_lab(in);
George Gao3018ede2019-10-23 13:23:00 -07006753 if (adev->num_va_sessions > 0)
6754 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006755 in->standby = 1;
6756 }
6757
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006758 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006759 if (adev->adm_deregister_stream)
6760 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
6761
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08006762 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006763 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08006764 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08006765 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08006766 voice_extn_compress_voip_close_input_stream(stream);
6767 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07006768 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6769 do_stop = in->capture_started;
6770 in->capture_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07006771 if (in->mmap_shared_memory_fd >= 0) {
6772 ALOGV("%s: closing mmap_shared_memory_fd = %d",
6773 __func__, in->mmap_shared_memory_fd);
6774 close(in->mmap_shared_memory_fd);
6775 in->mmap_shared_memory_fd = -1;
6776 }
Zhou Songa8895042016-07-05 17:54:22 +08006777 } else {
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306778 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05306779 audio_extn_cin_close_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08006780 }
6781
Arun Mirpuri5d170872019-03-26 13:21:31 -07006782 if (in->pcm) {
6783 ATRACE_BEGIN("pcm_in_close");
6784 pcm_close(in->pcm);
6785 ATRACE_END();
6786 in->pcm = NULL;
6787 }
6788
Carter Hsu2e429db2019-05-14 18:50:52 +08006789 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08006790 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006791
George Gao3018ede2019-10-23 13:23:00 -07006792 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
6793 if (adev->num_va_sessions > 0)
6794 adev->num_va_sessions--;
6795 }
Quinn Malef6050362019-01-30 15:55:40 -08006796
Eric Laurent150dbfe2013-02-27 14:31:02 -08006797 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006798 }
6799 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07006800 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006801 return status;
6802}
6803
Aalique Grahame22e49102018-12-18 14:23:57 -08006804static int in_dump(const struct audio_stream *stream,
6805 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006806{
Aalique Grahame22e49102018-12-18 14:23:57 -08006807 struct stream_in *in = (struct stream_in *)stream;
6808
6809 // We try to get the lock for consistency,
6810 // but it isn't necessary for these variables.
6811 // If we're not in standby, we may be blocked on a read.
6812 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
6813 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
6814 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
6815 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
6816
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006817 char buffer[256]; // for statistics formatting
6818 if (in->start_latency_ms.n > 0) {
6819 simple_stats_to_string(&in->start_latency_ms, buffer, sizeof(buffer));
6820 dprintf(fd, " Start latency ms: %s\n", buffer);
6821 }
6822
Aalique Grahame22e49102018-12-18 14:23:57 -08006823 if (locked) {
6824 pthread_mutex_unlock(&in->lock);
6825 }
6826
6827 // dump error info
6828 (void)error_log_dump(
6829 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
6830
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006831 return 0;
6832}
6833
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306834static void in_snd_mon_cb(void * stream, struct str_parms * parms)
6835{
6836 if (!stream || !parms)
6837 return;
6838
6839 struct stream_in *in = (struct stream_in *)stream;
6840 struct audio_device *adev = in->dev;
6841
6842 card_status_t status;
6843 int card;
6844 if (parse_snd_card_status(parms, &card, &status) < 0)
6845 return;
6846
6847 pthread_mutex_lock(&adev->lock);
6848 bool valid_cb = (card == adev->snd_card);
6849 pthread_mutex_unlock(&adev->lock);
6850
6851 if (!valid_cb)
6852 return;
6853
6854 lock_input_stream(in);
6855 if (in->card_status != status)
6856 in->card_status = status;
6857 pthread_mutex_unlock(&in->lock);
6858
6859 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
6860 use_case_table[in->usecase],
6861 status == CARD_STATUS_OFFLINE ? "offline" : "online");
6862
6863 // a better solution would be to report error back to AF and let
6864 // it put the stream to standby
6865 if (status == CARD_STATUS_OFFLINE)
6866 in_standby(&in->stream.common);
6867
6868 return;
6869}
6870
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006871int route_input_stream(struct stream_in *in,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006872 struct listnode *devices,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006873 audio_source_t source)
6874{
6875 struct audio_device *adev = in->dev;
6876 int ret = 0;
6877
6878 lock_input_stream(in);
6879 pthread_mutex_lock(&adev->lock);
6880
6881 /* no audio source uses val == 0 */
6882 if ((in->source != source) && (source != AUDIO_SOURCE_DEFAULT)) {
6883 in->source = source;
6884 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6885 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
6886 (voice_extn_compress_voip_is_format_supported(in->format)) &&
6887 (in->config.rate == 8000 || in->config.rate == 16000 ||
6888 in->config.rate == 32000 || in->config.rate == 48000 ) &&
6889 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
6890 ret = voice_extn_compress_voip_open_input_stream(in);
6891 if (ret != 0) {
6892 ALOGE("%s: Compress voip input cannot be opened, error:%d",
6893 __func__, ret);
6894 }
6895 }
6896 }
6897
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006898 if (!compare_devices(&in->device_list, devices) && !list_empty(devices) &&
6899 is_audio_in_device_type(devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006900 // Workaround: If routing to an non existing usb device, fail gracefully
6901 // The routing request will otherwise block during 10 second
6902 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006903 struct str_parms *usb_addr =
6904 str_parms_create_str(get_usb_device_address(devices));
6905 if (is_usb_in_device_type(devices) && usb_addr &&
6906 (card = get_alive_usb_card(usb_addr)) >= 0) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006907 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
6908 ret = -ENOSYS;
6909 } else {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006910 /* If recording is in progress, change the tx device to new device */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006911 assign_devices(&in->device_list, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006912 if (!in->standby && !in->is_st_session) {
6913 ALOGV("update input routing change");
6914 // inform adm before actual routing to prevent glitches.
6915 if (adev->adm_on_routing_change) {
6916 adev->adm_on_routing_change(adev->adm_data,
6917 in->capture_handle);
6918 ret = select_devices(adev, in->usecase);
6919 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6920 adev->adm_routing_changed = true;
6921 }
6922 }
6923 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006924 if (usb_addr)
6925 str_parms_destroy(usb_addr);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006926 }
6927 pthread_mutex_unlock(&adev->lock);
6928 pthread_mutex_unlock(&in->lock);
6929
6930 ALOGD("%s: exit: status(%d)", __func__, ret);
6931 return ret;
6932}
6933
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006934static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
6935{
6936 struct stream_in *in = (struct stream_in *)stream;
6937 struct audio_device *adev = in->dev;
6938 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006939 char value[32];
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306940 int err = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006941
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306942 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006943 parms = str_parms_create_str(kvpairs);
6944
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306945 if (!parms)
6946 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006947 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006948 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006949
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306950 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
6951 if (err >= 0) {
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306952 strlcpy(in->profile, value, sizeof(in->profile));
6953 ALOGV("updating stream profile with value '%s'", in->profile);
6954 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
6955 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006956 &in->device_list, in->flags, in->format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306957 in->sample_rate, in->bit_width,
6958 in->profile, &in->app_type_cfg);
6959 }
6960
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006961 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006962 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006963
6964 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306965error:
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306966 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006967}
6968
6969static char* in_get_parameters(const struct audio_stream *stream,
6970 const char *keys)
6971{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006972 struct stream_in *in = (struct stream_in *)stream;
6973 struct str_parms *query = str_parms_create_str(keys);
6974 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006975 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006976
6977 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08006978 if (reply) {
6979 str_parms_destroy(reply);
6980 }
6981 if (query) {
6982 str_parms_destroy(query);
6983 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006984 ALOGE("in_get_parameters: failed to create query or reply");
6985 return NULL;
6986 }
6987
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006988 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006989
6990 voice_extn_in_get_parameters(in, query, reply);
6991
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006992 stream_get_parameter_channels(query, reply,
6993 &in->supported_channel_masks[0]);
6994 stream_get_parameter_formats(query, reply,
6995 &in->supported_formats[0]);
6996 stream_get_parameter_rates(query, reply,
6997 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006998 str = str_parms_to_str(reply);
6999 str_parms_destroy(query);
7000 str_parms_destroy(reply);
7001
7002 ALOGV("%s: exit: returns - %s", __func__, str);
7003 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007004}
7005
Aalique Grahame22e49102018-12-18 14:23:57 -08007006static int in_set_gain(struct audio_stream_in *stream,
7007 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007008{
Aalique Grahame22e49102018-12-18 14:23:57 -08007009 struct stream_in *in = (struct stream_in *)stream;
7010 char mixer_ctl_name[128];
7011 struct mixer_ctl *ctl;
7012 int ctl_value;
7013
7014 ALOGV("%s: gain %f", __func__, gain);
7015
7016 if (stream == NULL)
7017 return -EINVAL;
7018
7019 /* in_set_gain() only used to silence MMAP capture for now */
7020 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
7021 return -ENOSYS;
7022
7023 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
7024
7025 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
7026 if (!ctl) {
7027 ALOGW("%s: Could not get ctl for mixer cmd - %s",
7028 __func__, mixer_ctl_name);
7029 return -ENOSYS;
7030 }
7031
7032 if (gain < RECORD_GAIN_MIN)
7033 gain = RECORD_GAIN_MIN;
7034 else if (gain > RECORD_GAIN_MAX)
7035 gain = RECORD_GAIN_MAX;
7036 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
7037
7038 mixer_ctl_set_value(ctl, 0, ctl_value);
7039
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007040 return 0;
7041}
7042
7043static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
7044 size_t bytes)
7045{
7046 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05307047
7048 if (in == NULL) {
7049 ALOGE("%s: stream_in ptr is NULL", __func__);
7050 return -EINVAL;
7051 }
7052
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007053 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05307054 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307055 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007056
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007057 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05307058
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007059 if (in->is_st_session) {
7060 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
7061 /* Read from sound trigger HAL */
7062 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08007063 if (in->standby) {
George Gao3018ede2019-10-23 13:23:00 -07007064 if (adev->num_va_sessions < UINT_MAX)
7065 adev->num_va_sessions++;
Quinn Malef6050362019-01-30 15:55:40 -08007066 in->standby = 0;
7067 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007068 pthread_mutex_unlock(&in->lock);
7069 return bytes;
7070 }
7071
Haynes Mathew George16081042017-05-31 17:16:49 -07007072 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
7073 ret = -ENOSYS;
7074 goto exit;
7075 }
7076
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007077 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
7078 !in->standby && adev->adm_routing_changed) {
7079 ret = -ENOSYS;
7080 goto exit;
7081 }
7082
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007083 if (in->standby) {
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007084 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
7085
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007086 pthread_mutex_lock(&adev->lock);
7087 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
7088 ret = voice_extn_compress_voip_start_input_stream(in);
7089 else
7090 ret = start_input_stream(in);
George Gao3018ede2019-10-23 13:23:00 -07007091 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
7092 if (adev->num_va_sessions < UINT_MAX)
7093 adev->num_va_sessions++;
7094 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007095 pthread_mutex_unlock(&adev->lock);
7096 if (ret != 0) {
7097 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007098 }
7099 in->standby = 0;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007100
7101 // log startup time in ms.
7102 simple_stats_log(
7103 &in->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007104 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007105
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05307106 /* Avoid read if capture_stopped is set */
7107 if (android_atomic_acquire_load(&(in->capture_stopped)) > 0) {
7108 ALOGD("%s: force stopped catpure session, ignoring read request", __func__);
7109 ret = -EINVAL;
7110 goto exit;
7111 }
7112
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007113 // what's the duration requested by the client?
7114 long ns = 0;
7115
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307116 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007117 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
7118 in->config.rate;
7119
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007120 ret = request_in_focus(in, ns);
7121 if (ret != 0)
7122 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007123 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007124
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307125 if (audio_extn_cin_attached_usecase(in)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307126 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
7127 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307128 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007129 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307130 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07007131 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007132 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007133 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07007134 } else if (audio_extn_ffv_get_stream() == in) {
7135 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307136 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007137 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307138 /* data from DSP comes in 24_8 format, convert it to 8_24 */
7139 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
7140 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
7141 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307142 ret = -EINVAL;
7143 goto exit;
7144 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307145 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307146 ret = -errno;
7147 }
7148 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307149 /* bytes read is always set to bytes for non compress usecases */
7150 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007151 }
7152
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007153 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007154
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007155 /*
Quinn Malef6050362019-01-30 15:55:40 -08007156 * Instead of writing zeroes here, we could trust the hardware to always
7157 * provide zeroes when muted. This is also muted with voice recognition
7158 * usecases so that other clients do not have access to voice recognition
7159 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007160 */
Quinn Malef6050362019-01-30 15:55:40 -08007161 if ((ret == 0 && voice_get_mic_mute(adev) &&
7162 !voice_is_in_call_rec_stream(in) &&
Zhou Song62ea0282020-03-22 19:53:01 +08007163 (in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY &&
7164 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY2)) ||
Quinn Malef6050362019-01-30 15:55:40 -08007165 (adev->num_va_sessions &&
7166 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
7167 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
7168 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007169 memset(buffer, 0, bytes);
7170
7171exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307172 frame_size = audio_stream_in_frame_size(stream);
7173 if (frame_size > 0)
7174 in->frames_read += bytes_read/frame_size;
7175
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007176 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307177 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007178 pthread_mutex_unlock(&in->lock);
7179
7180 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307181 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307182 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307183 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307184 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307185 in->standby = true;
7186 }
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307187 if (!audio_extn_cin_attached_usecase(in)) {
Sharad Sangled17c9122017-03-20 15:58:52 +05307188 bytes_read = bytes;
7189 memset(buffer, 0, bytes);
7190 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007191 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007192 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7193 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007194 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05307195 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05307196 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007197 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307198 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007199}
7200
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007201static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007202{
7203 return 0;
7204}
7205
Aalique Grahame22e49102018-12-18 14:23:57 -08007206static int in_get_capture_position(const struct audio_stream_in *stream,
7207 int64_t *frames, int64_t *time)
7208{
7209 if (stream == NULL || frames == NULL || time == NULL) {
7210 return -EINVAL;
7211 }
7212 struct stream_in *in = (struct stream_in *)stream;
7213 int ret = -ENOSYS;
7214
7215 lock_input_stream(in);
7216 // note: ST sessions do not close the alsa pcm driver synchronously
7217 // on standby. Therefore, we may return an error even though the
7218 // pcm stream is still opened.
7219 if (in->standby) {
7220 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
7221 "%s stream in standby but pcm not NULL for non ST session", __func__);
7222 goto exit;
7223 }
7224 if (in->pcm) {
7225 struct timespec timestamp;
7226 unsigned int avail;
7227 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
7228 *frames = in->frames_read + avail;
Robert Lee58215542019-07-15 20:55:12 +08007229 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec
George Gao9ba8a142020-07-23 14:30:03 -07007230 - platform_capture_latency(in) * 1000LL;
Aalique Grahame22e49102018-12-18 14:23:57 -08007231 ret = 0;
7232 }
7233 }
7234exit:
7235 pthread_mutex_unlock(&in->lock);
7236 return ret;
7237}
7238
Carter Hsu2e429db2019-05-14 18:50:52 +08007239static int in_update_effect_list(bool add, effect_handle_t effect,
7240 struct listnode *head)
7241{
7242 struct listnode *node;
7243 struct in_effect_list *elist = NULL;
7244 struct in_effect_list *target = NULL;
7245 int ret = 0;
7246
7247 if (!head)
7248 return ret;
7249
7250 list_for_each(node, head) {
7251 elist = node_to_item(node, struct in_effect_list, list);
7252 if (elist->handle == effect) {
7253 target = elist;
7254 break;
7255 }
7256 }
7257
7258 if (add) {
7259 if (target) {
7260 ALOGD("effect %p already exist", effect);
7261 return ret;
7262 }
7263
7264 target = (struct in_effect_list *)
7265 calloc(1, sizeof(struct in_effect_list));
7266
7267 if (!target) {
7268 ALOGE("%s:fail to allocate memory", __func__);
7269 return -ENOMEM;
7270 }
7271
7272 target->handle = effect;
7273 list_add_tail(head, &target->list);
7274 } else {
7275 if (target) {
7276 list_remove(&target->list);
7277 free(target);
7278 }
7279 }
7280
7281 return ret;
7282}
7283
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007284static int add_remove_audio_effect(const struct audio_stream *stream,
7285 effect_handle_t effect,
7286 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007287{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007288 struct stream_in *in = (struct stream_in *)stream;
7289 int status = 0;
7290 effect_descriptor_t desc;
7291
7292 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007293 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
7294
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007295 if (status != 0)
7296 return status;
7297
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007298 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007299 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08007300 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08007301 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
7302 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007303 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08007304
7305 in_update_effect_list(enable, effect, &in->aec_list);
7306 enable = !list_empty(&in->aec_list);
7307 if (enable == in->enable_aec)
7308 goto exit;
7309
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007310 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007311 ALOGD("AEC enable %d", enable);
7312
Aalique Grahame22e49102018-12-18 14:23:57 -08007313 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7314 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
7315 in->dev->enable_voicerx = enable;
7316 struct audio_usecase *usecase;
7317 struct listnode *node;
7318 list_for_each(node, &in->dev->usecase_list) {
7319 usecase = node_to_item(node, struct audio_usecase, list);
7320 if (usecase->type == PCM_PLAYBACK)
7321 select_devices(in->dev, usecase->id);
7322 }
7323 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007324 if (!in->standby) {
7325 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
7326 select_devices(in->dev, in->usecase);
7327 }
7328
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007329 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007330 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
7331
7332 in_update_effect_list(enable, effect, &in->ns_list);
7333 enable = !list_empty(&in->ns_list);
7334 if (enable == in->enable_ns)
7335 goto exit;
7336
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007337 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007338 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007339 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08007340 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7341 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007342 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
7343 select_devices(in->dev, in->usecase);
7344 } else
7345 select_devices(in->dev, in->usecase);
7346 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007347 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007348exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007349 pthread_mutex_unlock(&in->dev->lock);
7350 pthread_mutex_unlock(&in->lock);
7351
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007352 return 0;
7353}
7354
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007355static int in_add_audio_effect(const struct audio_stream *stream,
7356 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007357{
Eric Laurent994a6932013-07-17 11:51:42 -07007358 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007359 return add_remove_audio_effect(stream, effect, true);
7360}
7361
7362static int in_remove_audio_effect(const struct audio_stream *stream,
7363 effect_handle_t effect)
7364{
Eric Laurent994a6932013-07-17 11:51:42 -07007365 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007366 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007367}
7368
Derek Chenf939fb72018-11-13 13:34:41 -08007369streams_input_ctxt_t *in_get_stream(struct audio_device *dev,
7370 audio_io_handle_t input)
7371{
7372 struct listnode *node;
7373
7374 list_for_each(node, &dev->active_inputs_list) {
7375 streams_input_ctxt_t *in_ctxt = node_to_item(node,
7376 streams_input_ctxt_t,
7377 list);
7378 if (in_ctxt->input->capture_handle == input) {
7379 return in_ctxt;
7380 }
7381 }
7382 return NULL;
7383}
7384
7385streams_output_ctxt_t *out_get_stream(struct audio_device *dev,
7386 audio_io_handle_t output)
7387{
7388 struct listnode *node;
7389
7390 list_for_each(node, &dev->active_outputs_list) {
7391 streams_output_ctxt_t *out_ctxt = node_to_item(node,
7392 streams_output_ctxt_t,
7393 list);
7394 if (out_ctxt->output->handle == output) {
7395 return out_ctxt;
7396 }
7397 }
7398 return NULL;
7399}
7400
Haynes Mathew George16081042017-05-31 17:16:49 -07007401static int in_stop(const struct audio_stream_in* stream)
7402{
7403 struct stream_in *in = (struct stream_in *)stream;
7404 struct audio_device *adev = in->dev;
7405
7406 int ret = -ENOSYS;
7407 ALOGV("%s", __func__);
7408 pthread_mutex_lock(&adev->lock);
7409 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7410 in->capture_started && in->pcm != NULL) {
7411 pcm_stop(in->pcm);
7412 ret = stop_input_stream(in);
7413 in->capture_started = false;
7414 }
7415 pthread_mutex_unlock(&adev->lock);
7416 return ret;
7417}
7418
7419static int in_start(const struct audio_stream_in* stream)
7420{
7421 struct stream_in *in = (struct stream_in *)stream;
7422 struct audio_device *adev = in->dev;
7423 int ret = -ENOSYS;
7424
7425 ALOGV("%s in %p", __func__, in);
7426 pthread_mutex_lock(&adev->lock);
7427 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7428 !in->capture_started && in->pcm != NULL) {
7429 if (!in->capture_started) {
7430 ret = start_input_stream(in);
7431 if (ret == 0) {
7432 in->capture_started = true;
7433 }
7434 }
7435 }
7436 pthread_mutex_unlock(&adev->lock);
7437 return ret;
7438}
7439
Phil Burke0a86d12019-02-16 22:28:11 -08007440// Read offset for the positional timestamp from a persistent vendor property.
7441// This is to workaround apparent inaccuracies in the timing information that
7442// is used by the AAudio timing model. The inaccuracies can cause glitches.
7443static int64_t in_get_mmap_time_offset() {
7444 const int32_t kDefaultOffsetMicros = 0;
7445 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08007446 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08007447 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
7448 return mmap_time_offset_micros * (int64_t)1000;
7449}
7450
Haynes Mathew George16081042017-05-31 17:16:49 -07007451static int in_create_mmap_buffer(const struct audio_stream_in *stream,
7452 int32_t min_size_frames,
7453 struct audio_mmap_buffer_info *info)
7454{
7455 struct stream_in *in = (struct stream_in *)stream;
7456 struct audio_device *adev = in->dev;
7457 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07007458 unsigned int offset1 = 0;
7459 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007460 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07007461 uint32_t mmap_size = 0;
7462 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007463
7464 pthread_mutex_lock(&adev->lock);
7465 ALOGV("%s in %p", __func__, in);
7466
Sharad Sanglec6f32552018-05-04 16:15:38 +05307467 if (CARD_STATUS_OFFLINE == in->card_status||
7468 CARD_STATUS_OFFLINE == adev->card_status) {
7469 ALOGW("in->card_status or adev->card_status offline, try again");
7470 ret = -EIO;
7471 goto exit;
7472 }
7473
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307474 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07007475 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
7476 ret = -EINVAL;
7477 goto exit;
7478 }
7479 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
7480 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
7481 ALOGV("%s in %p", __func__, in);
7482 ret = -ENOSYS;
7483 goto exit;
7484 }
7485 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
7486 if (in->pcm_device_id < 0) {
7487 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
7488 __func__, in->pcm_device_id, in->usecase);
7489 ret = -EINVAL;
7490 goto exit;
7491 }
7492
7493 adjust_mmap_period_count(&in->config, min_size_frames);
7494
7495 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
7496 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
7497 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
7498 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307499 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307500 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7501 in->card_status = CARD_STATUS_OFFLINE;
7502 adev->card_status = CARD_STATUS_OFFLINE;
7503 ret = -EIO;
7504 goto exit;
7505 }
7506
Haynes Mathew George16081042017-05-31 17:16:49 -07007507 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
7508 step = "open";
7509 ret = -ENODEV;
7510 goto exit;
7511 }
7512
7513 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
7514 if (ret < 0) {
7515 step = "begin";
7516 goto exit;
7517 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007518
juyuchen626833d2019-06-04 16:48:02 +08007519 info->flags = 0;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007520 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
7521 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
7522 info->burst_size_frames = in->config.period_size;
7523 ret = platform_get_mmap_data_fd(adev->platform,
7524 in->pcm_device_id, 1 /*capture*/,
7525 &info->shared_memory_fd,
7526 &mmap_size);
7527 if (ret < 0) {
7528 // Fall back to non exclusive mode
7529 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
7530 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07007531 in->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
7532 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, in->mmap_shared_memory_fd);
7533
Arun Mirpuri5d170872019-03-26 13:21:31 -07007534 if (mmap_size < buffer_size) {
7535 step = "mmap";
7536 goto exit;
7537 }
juyuchen626833d2019-06-04 16:48:02 +08007538 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007539 }
7540
7541 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07007542
7543 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
7544 if (ret < 0) {
7545 step = "commit";
7546 goto exit;
7547 }
7548
Phil Burke0a86d12019-02-16 22:28:11 -08007549 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
7550
Haynes Mathew George16081042017-05-31 17:16:49 -07007551 in->standby = false;
7552 ret = 0;
7553
7554 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
7555 __func__, info->shared_memory_address, info->buffer_size_frames);
7556
7557exit:
7558 if (ret != 0) {
7559 if (in->pcm == NULL) {
7560 ALOGE("%s: %s - %d", __func__, step, ret);
7561 } else {
7562 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
7563 pcm_close(in->pcm);
7564 in->pcm = NULL;
7565 }
7566 }
7567 pthread_mutex_unlock(&adev->lock);
7568 return ret;
7569}
7570
7571static int in_get_mmap_position(const struct audio_stream_in *stream,
7572 struct audio_mmap_position *position)
7573{
7574 struct stream_in *in = (struct stream_in *)stream;
7575 ALOGVV("%s", __func__);
7576 if (position == NULL) {
7577 return -EINVAL;
7578 }
7579 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
7580 return -ENOSYS;
7581 }
7582 if (in->pcm == NULL) {
7583 return -ENOSYS;
7584 }
7585 struct timespec ts = { 0, 0 };
7586 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
7587 if (ret < 0) {
7588 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
7589 return ret;
7590 }
Phil Burke0a86d12019-02-16 22:28:11 -08007591 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7592 + in->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07007593 return 0;
7594}
7595
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307596static int in_get_active_microphones(const struct audio_stream_in *stream,
7597 struct audio_microphone_characteristic_t *mic_array,
7598 size_t *mic_count) {
7599 struct stream_in *in = (struct stream_in *)stream;
7600 struct audio_device *adev = in->dev;
7601 ALOGVV("%s", __func__);
7602
7603 lock_input_stream(in);
7604 pthread_mutex_lock(&adev->lock);
7605 int ret = platform_get_active_microphones(adev->platform,
7606 audio_channel_count_from_in_mask(in->channel_mask),
7607 in->usecase, mic_array, mic_count);
7608 pthread_mutex_unlock(&adev->lock);
7609 pthread_mutex_unlock(&in->lock);
7610
7611 return ret;
7612}
7613
7614static int adev_get_microphones(const struct audio_hw_device *dev,
7615 struct audio_microphone_characteristic_t *mic_array,
7616 size_t *mic_count) {
7617 struct audio_device *adev = (struct audio_device *)dev;
7618 ALOGVV("%s", __func__);
7619
7620 pthread_mutex_lock(&adev->lock);
7621 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
7622 pthread_mutex_unlock(&adev->lock);
7623
7624 return ret;
7625}
juyuchendb308c22019-01-21 11:57:17 -07007626
7627static void in_update_sink_metadata(struct audio_stream_in *stream,
7628 const struct sink_metadata *sink_metadata) {
7629
7630 if (stream == NULL
7631 || sink_metadata == NULL
7632 || sink_metadata->tracks == NULL) {
7633 return;
7634 }
7635
7636 int error = 0;
7637 struct stream_in *in = (struct stream_in *)stream;
7638 struct audio_device *adev = in->dev;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007639 struct listnode devices;
Zhou Song62ea0282020-03-22 19:53:01 +08007640 bool is_ha_usecase = false;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007641
7642 list_init(&devices);
juyuchendb308c22019-01-21 11:57:17 -07007643
7644 if (sink_metadata->track_count != 0)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007645 reassign_device_list(&devices, sink_metadata->tracks->dest_device, "");
juyuchendb308c22019-01-21 11:57:17 -07007646
7647 lock_input_stream(in);
7648 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007649 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, get_device_types(&devices));
juyuchendb308c22019-01-21 11:57:17 -07007650
Zhou Song62ea0282020-03-22 19:53:01 +08007651 is_ha_usecase = adev->ha_proxy_enable ?
7652 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2 :
7653 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY;
7654 if (is_ha_usecase && !list_empty(&devices)
juyuchendb308c22019-01-21 11:57:17 -07007655 && adev->voice_tx_output != NULL) {
7656 /* Use the rx device from afe-proxy record to route voice call because
7657 there is no routing if tx device is on primary hal and rx device
7658 is on other hal during voice call. */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007659 assign_devices(&adev->voice_tx_output->device_list, &devices);
juyuchendb308c22019-01-21 11:57:17 -07007660
7661 if (!voice_is_call_state_active(adev)) {
7662 if (adev->mode == AUDIO_MODE_IN_CALL) {
7663 adev->current_call_output = adev->voice_tx_output;
7664 error = voice_start_call(adev);
7665 if (error != 0)
7666 ALOGE("%s: start voice call failed %d", __func__, error);
7667 }
7668 } else {
7669 adev->current_call_output = adev->voice_tx_output;
7670 voice_update_devices_for_all_voice_usecases(adev);
7671 }
7672 }
7673
7674 pthread_mutex_unlock(&adev->lock);
7675 pthread_mutex_unlock(&in->lock);
7676}
7677
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307678int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07007679 audio_io_handle_t handle,
7680 audio_devices_t devices,
7681 audio_output_flags_t flags,
7682 struct audio_config *config,
7683 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04007684 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007685{
7686 struct audio_device *adev = (struct audio_device *)dev;
7687 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05307688 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007689 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007690 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05307691 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007692 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
7693 bool is_usb_dev = audio_is_usb_out_device(devices) &&
7694 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
7695 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007696 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07007697 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
7698 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007699 bool force_haptic_path =
7700 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007701 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08007702#ifdef AUDIO_GKI_ENABLED
7703 __s32 *generic_dec;
7704#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007705
kunleizdff872d2018-08-20 14:40:33 +08007706 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007707 is_usb_dev = false;
7708 devices = AUDIO_DEVICE_OUT_SPEAKER;
7709 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
7710 __func__, devices);
Mingshu Pangdbd20562019-11-25 18:04:39 +08007711 if (config->format == AUDIO_FORMAT_DEFAULT)
7712 config->format = AUDIO_FORMAT_PCM_16_BIT;
7713 if (config->sample_rate == 0)
7714 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7715 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7716 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
kunleizd6a9e0c2018-07-30 15:38:52 +08007717 }
7718
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007719 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05307720
Rahul Sharma99770982019-03-06 17:05:26 +05307721 pthread_mutex_lock(&adev->lock);
7722 if (out_get_stream(adev, handle) != NULL) {
7723 ALOGW("%s, output stream already opened", __func__);
7724 ret = -EEXIST;
7725 }
7726 pthread_mutex_unlock(&adev->lock);
7727 if (ret)
7728 return ret;
7729
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007730 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
7731
Mingming Yin3a941d42016-02-17 18:08:05 -08007732 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04007733 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
7734 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307735
7736
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007737 if (!out) {
7738 return -ENOMEM;
7739 }
7740
Haynes Mathew George204045b2015-02-25 20:32:03 -08007741 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007742 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307743 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08007744 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08007745 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
7746
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007747 if (devices == AUDIO_DEVICE_NONE)
7748 devices = AUDIO_DEVICE_OUT_SPEAKER;
7749
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007750 out->flags = flags;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007751 list_init(&out->device_list);
7752 update_device_list(&out->device_list, devices, address, true /* add devices */);
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07007753 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07007754 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007755 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05307756 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05307757 if (out->channel_mask == AUDIO_CHANNEL_NONE)
7758 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
7759 else
7760 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07007761 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007762 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08007763 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307764 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307765 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307766 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007767 out->hal_output_suspend_supported = 0;
7768 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05307769 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05307770 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05307771 out->pspd_coeff_sent = false;
Phil Burkd898ba62019-06-20 12:49:01 -07007772 out->mmap_shared_memory_fd = -1; // not open
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007773
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05307774 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05307775 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07007776 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
7777
Aalique Grahame22e49102018-12-18 14:23:57 -08007778 if (direct_dev &&
7779 (audio_is_linear_pcm(out->format) ||
7780 config->format == AUDIO_FORMAT_DEFAULT) &&
7781 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
7782 audio_format_t req_format = config->format;
7783 audio_channel_mask_t req_channel_mask = config->channel_mask;
7784 uint32_t req_sample_rate = config->sample_rate;
7785
7786 pthread_mutex_lock(&adev->lock);
7787 if (is_hdmi) {
7788 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
7789 ret = read_hdmi_sink_caps(out);
7790 if (config->sample_rate == 0)
7791 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7792 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7793 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
7794 if (config->format == AUDIO_FORMAT_DEFAULT)
7795 config->format = AUDIO_FORMAT_PCM_16_BIT;
7796 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007797 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
7798 &config->format,
7799 &out->supported_formats[0],
7800 MAX_SUPPORTED_FORMATS,
7801 &config->channel_mask,
7802 &out->supported_channel_masks[0],
7803 MAX_SUPPORTED_CHANNEL_MASKS,
7804 &config->sample_rate,
7805 &out->supported_sample_rates[0],
7806 MAX_SUPPORTED_SAMPLE_RATES);
7807 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007808 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007809
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007810 pthread_mutex_unlock(&adev->lock);
7811 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007812 if (ret == -ENOSYS) {
7813 /* ignore and go with default */
7814 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007815 }
7816 // For MMAP NO IRQ, allow conversions in ADSP
7817 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
7818 goto error_open;
7819 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007820 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08007821 goto error_open;
7822 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007823
7824 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
7825 config->sample_rate = req_sample_rate;
7826 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
7827 config->channel_mask = req_channel_mask;
7828 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
7829 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08007830 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007831
7832 out->sample_rate = config->sample_rate;
7833 out->channel_mask = config->channel_mask;
7834 out->format = config->format;
7835 if (is_hdmi) {
7836 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7837 out->config = pcm_config_hdmi_multi;
7838 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7839 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7840 out->config = pcm_config_mmap_playback;
7841 out->stream.start = out_start;
7842 out->stream.stop = out_stop;
7843 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7844 out->stream.get_mmap_position = out_get_mmap_position;
7845 } else {
7846 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7847 out->config = pcm_config_hifi;
7848 }
7849
7850 out->config.rate = out->sample_rate;
7851 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7852 if (is_hdmi) {
7853 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7854 audio_bytes_per_sample(out->format));
7855 }
7856 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08007857 }
7858
Derek Chenf6318be2017-06-12 17:16:24 -04007859 /* validate bus device address */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007860 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04007861 /* extract car audio stream index */
7862 out->car_audio_stream =
7863 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
7864 if (out->car_audio_stream < 0) {
7865 ALOGE("%s: invalid car audio stream %x",
7866 __func__, out->car_audio_stream);
7867 ret = -EINVAL;
7868 goto error_open;
7869 }
Derek Chen5f67a942020-02-24 23:08:13 -08007870 ALOGV("%s: car_audio_stream %x", __func__, out->car_audio_stream);
Derek Chenf6318be2017-06-12 17:16:24 -04007871 }
7872
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007873 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007874 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007875 if (!voice_extn_is_compress_voip_supported()) {
7876 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
7877 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07007878 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
Lakshman Chaluvarajue7fc9482020-05-30 14:29:29 +05307879 config->channel_mask : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007880 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
7881 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07007882 out->volume_l = INVALID_OUT_VOLUME;
7883 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07007884
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007885 out->config = default_pcm_config_voip_copp;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007886 out->config.rate = out->sample_rate;
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007887 uint32_t channel_count =
7888 audio_channel_count_from_out_mask(out->channel_mask);
Ramjee Singh8e34a2f2020-08-06 16:30:48 +05307889 out->config.channels = channel_count;
7890
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007891 uint32_t buffer_size = get_stream_buffer_size(DEFAULT_VOIP_BUF_DURATION_MS,
7892 out->sample_rate, out->format,
7893 channel_count, false);
7894 uint32_t frame_size = audio_bytes_per_sample(out->format) * channel_count;
7895 if (frame_size != 0)
7896 out->config.period_size = buffer_size / frame_size;
7897 else
7898 ALOGW("%s: frame size is 0 for format %#x", __func__, out->format);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007899 }
7900 } else {
7901 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7902 voice_extn_compress_voip_is_active(out->dev)) &&
7903 (voice_extn_compress_voip_is_config_supported(config))) {
7904 ret = voice_extn_compress_voip_open_output_stream(out);
7905 if (ret != 0) {
7906 ALOGE("%s: Compress voip output cannot be opened, error:%d",
7907 __func__, ret);
7908 goto error_open;
7909 }
Sujin Panicker19027262019-09-16 18:28:06 +05307910 } else {
7911 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
7912 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007913 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007914 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007915 } else if (audio_is_linear_pcm(out->format) &&
7916 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
7917 out->channel_mask = config->channel_mask;
7918 out->sample_rate = config->sample_rate;
7919 out->format = config->format;
7920 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7921 // does this change?
7922 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
7923 out->config.rate = config->sample_rate;
7924 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7925 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7926 audio_bytes_per_sample(config->format));
7927 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07007928 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307929 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307930 pthread_mutex_lock(&adev->lock);
7931 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
7932 pthread_mutex_unlock(&adev->lock);
7933
7934 // reject offload during card offline to allow
7935 // fallback to s/w paths
7936 if (offline) {
7937 ret = -ENODEV;
7938 goto error_open;
7939 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007940
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007941 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
7942 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
7943 ALOGE("%s: Unsupported Offload information", __func__);
7944 ret = -EINVAL;
7945 goto error_open;
7946 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007947
Atul Khare3fa6e542017-08-09 00:56:17 +05307948 if (config->offload_info.format == 0)
7949 config->offload_info.format = config->format;
7950 if (config->offload_info.sample_rate == 0)
7951 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007952
Mingming Yin90310102013-11-13 16:57:00 -08007953 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307954 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07007955 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007956 ret = -EINVAL;
7957 goto error_open;
7958 }
7959
Ben Romberger0f8c87b2017-05-24 17:41:11 -07007960 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
7961 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
7962 (audio_extn_passthru_is_passthrough_stream(out)) &&
7963 !((config->sample_rate == 48000) ||
7964 (config->sample_rate == 96000) ||
7965 (config->sample_rate == 192000))) {
7966 ALOGE("%s: Unsupported sample rate %d for audio format %x",
7967 __func__, config->sample_rate, config->offload_info.format);
7968 ret = -EINVAL;
7969 goto error_open;
7970 }
7971
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007972 out->compr_config.codec = (struct snd_codec *)
7973 calloc(1, sizeof(struct snd_codec));
7974
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007975 if (!out->compr_config.codec) {
7976 ret = -ENOMEM;
7977 goto error_open;
7978 }
7979
Dhananjay Kumarac341582017-02-23 23:42:25 +05307980 out->stream.pause = out_pause;
7981 out->stream.resume = out_resume;
7982 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05307983 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307984 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07007985 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307986 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07007987 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05307988 } else {
7989 out->usecase = get_offload_usecase(adev, false /* is_compress */);
7990 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07007991 }
vivek mehta446c3962015-09-14 10:57:35 -07007992
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307993 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
7994 ALOGD("%s: Setting latency mode to true", __func__);
Meng Wang4c32fb42020-01-16 17:57:11 +08007995#ifdef AUDIO_GKI_ENABLED
7996 /* out->compr_config.codec->reserved[1] is for flags */
7997 out->compr_config.codec->reserved[1] |= audio_extn_utils_get_perf_mode_flag();
7998#else
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307999 out->compr_config.codec->flags |= audio_extn_utils_get_perf_mode_flag();
Meng Wang4c32fb42020-01-16 17:57:11 +08008000#endif
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308001 }
8002
vivek mehta446c3962015-09-14 10:57:35 -07008003 if (out->usecase == USECASE_INVALID) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008004 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Mingming Yin3a941d42016-02-17 18:08:05 -08008005 config->format == 0 && config->sample_rate == 0 &&
8006 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07008007 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08008008 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
8009 } else {
8010 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
8011 ret = -EEXIST;
8012 goto error_open;
8013 }
vivek mehta446c3962015-09-14 10:57:35 -07008014 }
8015
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008016 if (config->offload_info.channel_mask)
8017 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008018 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008019 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008020 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008021 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05308022 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008023 ret = -EINVAL;
8024 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008025 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008026
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008027 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008028 out->sample_rate = config->offload_info.sample_rate;
8029
Mingming Yin3ee55c62014-08-04 14:23:35 -07008030 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008031
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308032 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05308033 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308034 audio_extn_dolby_send_ddp_endp_params(adev);
8035 audio_extn_dolby_set_dmid(adev);
8036 }
vivek mehta0ea887a2015-08-26 14:01:20 -07008037
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008038 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08008039 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008040 out->compr_config.codec->bit_rate =
8041 config->offload_info.bit_rate;
8042 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05308043 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008044 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05308045 /* Update bit width only for non passthrough usecases.
8046 * For passthrough usecases, the output will always be opened @16 bit
8047 */
8048 if (!audio_extn_passthru_is_passthrough_stream(out))
8049 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308050
8051 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
Meng Wang4c32fb42020-01-16 17:57:11 +08008052#ifdef AUDIO_GKI_ENABLED
8053 /* out->compr_config.codec->reserved[1] is for flags */
8054 out->compr_config.codec->reserved[1] |= COMPRESSED_TIMESTAMP_FLAG;
8055 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->reserved[1]);
8056#else
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308057 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
8058 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
Meng Wang4c32fb42020-01-16 17:57:11 +08008059#endif
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308060
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008061 /*TODO: Do we need to change it for passthrough */
8062 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008063
Manish Dewangana6fc5442015-08-24 20:30:31 +05308064 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
8065 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308066 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05308067 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308068 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
8069 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308070
8071 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
8072 AUDIO_FORMAT_PCM) {
8073
8074 /*Based on platform support, configure appropriate alsa format for corresponding
8075 *hal input format.
8076 */
8077 out->compr_config.codec->format = hal_format_to_alsa(
8078 config->offload_info.format);
8079
Ashish Jain83a6cc22016-06-28 14:34:17 +05308080 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05308081 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308082 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308083
Dhananjay Kumarac341582017-02-23 23:42:25 +05308084 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05308085 *hal input format and alsa format might differ based on platform support.
8086 */
8087 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05308088 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308089
8090 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
8091
Deeraj Soman93155a62019-09-30 19:00:37 +05308092 if (property_get_bool("vendor.audio.offload.buffer.duration.enabled", false)) {
8093 if ((config->offload_info.duration_us >= MIN_OFFLOAD_BUFFER_DURATION_MS * 1000) &&
8094 (config->offload_info.duration_us <= MAX_OFFLOAD_BUFFER_DURATION_MS * 1000))
8095 out->info.duration_us = (int64_t)config->offload_info.duration_us;
8096 }
Deeraj Soman65358ab2019-02-07 15:40:49 +05308097
Ashish Jainf1eaa582016-05-23 20:54:24 +05308098 /* Check if alsa session is configured with the same format as HAL input format,
8099 * if not then derive correct fragment size needed to accomodate the
8100 * conversion of HAL input format to alsa format.
8101 */
8102 audio_extn_utils_update_direct_pcm_fragment_size(out);
8103
8104 /*if hal input and output fragment size is different this indicates HAL input format is
8105 *not same as the alsa format
8106 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308107 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05308108 /*Allocate a buffer to convert input data to the alsa configured format.
8109 *size of convert buffer is equal to the size required to hold one fragment size
8110 *worth of pcm data, this is because flinger does not write more than fragment_size
8111 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308112 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
8113 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05308114 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
8115 ret = -ENOMEM;
8116 goto error_open;
8117 }
8118 }
8119 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
8120 out->compr_config.fragment_size =
8121 audio_extn_passthru_get_buffer_size(&config->offload_info);
8122 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8123 } else {
8124 out->compr_config.fragment_size =
8125 platform_get_compress_offload_buffer_size(&config->offload_info);
8126 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8127 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008128
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308129 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8130 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
8131 }
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008132 if (config->offload_info.format == AUDIO_FORMAT_FLAC) {
8133#ifdef AUDIO_GKI_ENABLED
8134 generic_dec =
8135 &(out->compr_config.codec->options.generic.reserved[1]);
8136 ((struct snd_generic_dec_flac *)generic_dec)->sample_size =
8137 AUDIO_OUTPUT_BIT_WIDTH;
8138#else
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05308139 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008140#endif
8141 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008142
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05308143 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
8144 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
8145 }
8146
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008147 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
8148 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008149
Manish Dewangan69426c82017-01-30 17:35:36 +05308150 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
8151 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
8152 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
8153 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8154 out->render_mode = RENDER_MODE_AUDIO_MASTER;
8155 } else {
8156 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
8157 }
Alexy Josephaa54c872014-12-03 02:46:47 -08008158
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05308159 memset(&out->channel_map_param, 0,
8160 sizeof(struct audio_out_channel_map_param));
8161
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008162 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05308163 out->send_next_track_params = false;
8164 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008165 out->offload_state = OFFLOAD_STATE_IDLE;
8166 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08008167 out->writeAt.tv_sec = 0;
8168 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008169
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008170 audio_extn_dts_create_state_notifier_node(out->usecase);
8171
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008172 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
8173 __func__, config->offload_info.version,
8174 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05308175
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308176 /* Check if DSD audio format is supported in codec
8177 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308178 */
8179
8180 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308181 (!platform_check_codec_dsd_support(adev->platform) ||
8182 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308183 ret = -EINVAL;
8184 goto error_open;
8185 }
8186
Ashish Jain5106d362016-05-11 19:23:33 +05308187 /* Disable gapless if any of the following is true
8188 * passthrough playback
8189 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05308190 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05308191 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308192 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308193 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07008194 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308195 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308196 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05308197 check_and_set_gapless_mode(adev, false);
8198 } else
8199 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07008200
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308201 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07008202 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
8203 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308204 if (config->format == AUDIO_FORMAT_DSD) {
8205 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
Meng Wang4c32fb42020-01-16 17:57:11 +08008206#ifdef AUDIO_GKI_ENABLED
8207 /* out->compr_config.codec->reserved[0] is for compr_passthr */
8208 out->compr_config.codec->reserved[0] = PASSTHROUGH_DSD;
8209#else
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308210 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
Meng Wang4c32fb42020-01-16 17:57:11 +08008211#endif
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308212 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07008213
8214 create_offload_callback_thread(out);
8215
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008216 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008217 switch (config->sample_rate) {
8218 case 0:
8219 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8220 break;
8221 case 8000:
8222 case 16000:
8223 case 48000:
8224 out->sample_rate = config->sample_rate;
8225 break;
8226 default:
8227 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
8228 config->sample_rate);
8229 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8230 ret = -EINVAL;
8231 goto error_open;
8232 }
8233 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8234 switch (config->channel_mask) {
8235 case AUDIO_CHANNEL_NONE:
8236 case AUDIO_CHANNEL_OUT_STEREO:
8237 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8238 break;
8239 default:
8240 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
8241 config->channel_mask);
8242 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8243 ret = -EINVAL;
8244 goto error_open;
8245 }
8246 switch (config->format) {
8247 case AUDIO_FORMAT_DEFAULT:
8248 case AUDIO_FORMAT_PCM_16_BIT:
8249 out->format = AUDIO_FORMAT_PCM_16_BIT;
8250 break;
8251 default:
8252 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
8253 config->format);
8254 config->format = AUDIO_FORMAT_PCM_16_BIT;
8255 ret = -EINVAL;
8256 goto error_open;
8257 }
8258
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05308259 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008260 if (ret != 0) {
8261 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008262 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008263 goto error_open;
8264 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008265 } else if (is_single_device_type_equal(&out->device_list,
8266 AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08008267 switch (config->sample_rate) {
8268 case 0:
8269 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
8270 break;
8271 case 8000:
8272 case 16000:
8273 case 48000:
8274 out->sample_rate = config->sample_rate;
8275 break;
8276 default:
8277 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
8278 config->sample_rate);
8279 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8280 ret = -EINVAL;
8281 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008282 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008283 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8284 switch (config->channel_mask) {
8285 case AUDIO_CHANNEL_NONE:
8286 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8287 break;
8288 case AUDIO_CHANNEL_OUT_STEREO:
8289 out->channel_mask = config->channel_mask;
8290 break;
8291 default:
8292 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
8293 config->channel_mask);
8294 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8295 ret = -EINVAL;
8296 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008297 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008298 switch (config->format) {
8299 case AUDIO_FORMAT_DEFAULT:
8300 out->format = AUDIO_FORMAT_PCM_16_BIT;
8301 break;
8302 case AUDIO_FORMAT_PCM_16_BIT:
8303 out->format = config->format;
8304 break;
8305 default:
8306 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
8307 config->format);
8308 config->format = AUDIO_FORMAT_PCM_16_BIT;
8309 ret = -EINVAL;
8310 break;
8311 }
8312 if (ret != 0)
8313 goto error_open;
8314
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008315 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
8316 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08008317 out->config.rate = out->sample_rate;
8318 out->config.channels =
8319 audio_channel_count_from_out_mask(out->channel_mask);
8320 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008321 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008322 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05308323 unsigned int channels = 0;
8324 /*Update config params to default if not set by the caller*/
8325 if (config->sample_rate == 0)
8326 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8327 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8328 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8329 if (config->format == AUDIO_FORMAT_DEFAULT)
8330 config->format = AUDIO_FORMAT_PCM_16_BIT;
8331
8332 channels = audio_channel_count_from_out_mask(out->channel_mask);
8333
Varun Balaraje49253e2017-07-06 19:48:56 +05308334 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
8335 out->usecase = get_interactive_usecase(adev);
8336 out->config = pcm_config_low_latency;
8337 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05308338 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008339 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
8340 out->flags);
8341 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07008342 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8343 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8344 out->config = pcm_config_mmap_playback;
8345 out->stream.start = out_start;
8346 out->stream.stop = out_stop;
8347 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8348 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308349 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8350 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008351 out->hal_output_suspend_supported =
8352 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
8353 out->dynamic_pm_qos_config_supported =
8354 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
8355 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08008356 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
8357 } else {
8358 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
8359 //the mixer path will be a string similar to "low-latency-playback resume"
8360 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
8361 strlcat(out->pm_qos_mixer_path,
8362 " resume", MAX_MIXER_PATH_LEN);
8363 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
8364 out->pm_qos_mixer_path);
8365 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308366 out->config = pcm_config_low_latency;
8367 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
8368 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
8369 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05308370 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
8371 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
8372 if (out->config.period_size <= 0) {
8373 ALOGE("Invalid configuration period size is not valid");
8374 ret = -EINVAL;
8375 goto error_open;
8376 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008377 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
8378 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
8379 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008380 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
8381 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
8382 out->config = pcm_config_haptics_audio;
8383 if (force_haptic_path)
8384 adev->haptics_config = pcm_config_haptics_audio;
8385 else
8386 adev->haptics_config = pcm_config_haptics;
8387
Meng Wangd08ce322020-04-02 08:59:20 +08008388 channels =
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008389 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
8390
8391 if (force_haptic_path) {
8392 out->config.channels = 1;
8393 adev->haptics_config.channels = 1;
8394 } else
8395 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 -08008396 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008397 ret = audio_extn_auto_hal_open_output_stream(out);
8398 if (ret) {
8399 ALOGE("%s: Failed to open output stream for bus device", __func__);
8400 ret = -EINVAL;
8401 goto error_open;
8402 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308403 } else {
8404 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008405 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8406 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308407 }
8408 out->hal_ip_format = format = out->format;
8409 out->config.format = hal_format_to_pcm(out->hal_ip_format);
8410 out->hal_op_format = pcm_format_to_hal(out->config.format);
8411 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
8412 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008413 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05308414 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308415 if (out->hal_ip_format != out->hal_op_format) {
8416 uint32_t buffer_size = out->config.period_size *
8417 format_to_bitwidth_table[out->hal_op_format] *
8418 out->config.channels;
8419 out->convert_buffer = calloc(1, buffer_size);
8420 if (out->convert_buffer == NULL){
8421 ALOGE("Allocation failed for convert buffer for size %d",
8422 out->compr_config.fragment_size);
8423 ret = -ENOMEM;
8424 goto error_open;
8425 }
8426 ALOGD("Convert buffer allocated of size %d", buffer_size);
8427 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008428 }
8429
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008430 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
8431 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308432
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008433 /* TODO remove this hardcoding and check why width is zero*/
8434 if (out->bit_width == 0)
8435 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308436 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008437 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008438 &out->device_list, out->flags,
8439 out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05308440 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05308441 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08008442 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08008443 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
8444 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008445 if(adev->primary_output == NULL)
8446 adev->primary_output = out;
8447 else {
8448 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008449 ret = -EEXIST;
8450 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008451 }
8452 }
8453
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008454 /* Check if this usecase is already existing */
8455 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07008456 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
8457 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008458 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008459 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008460 ret = -EEXIST;
8461 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008462 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008463
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008464 pthread_mutex_unlock(&adev->lock);
8465
8466 out->stream.common.get_sample_rate = out_get_sample_rate;
8467 out->stream.common.set_sample_rate = out_set_sample_rate;
8468 out->stream.common.get_buffer_size = out_get_buffer_size;
8469 out->stream.common.get_channels = out_get_channels;
8470 out->stream.common.get_format = out_get_format;
8471 out->stream.common.set_format = out_set_format;
8472 out->stream.common.standby = out_standby;
8473 out->stream.common.dump = out_dump;
8474 out->stream.common.set_parameters = out_set_parameters;
8475 out->stream.common.get_parameters = out_get_parameters;
8476 out->stream.common.add_audio_effect = out_add_audio_effect;
8477 out->stream.common.remove_audio_effect = out_remove_audio_effect;
8478 out->stream.get_latency = out_get_latency;
8479 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08008480#ifdef NO_AUDIO_OUT
8481 out->stream.write = out_write_for_no_output;
8482#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008483 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08008484#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008485 out->stream.get_render_position = out_get_render_position;
8486 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008487 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008488
Haynes Mathew George16081042017-05-31 17:16:49 -07008489 if (out->realtime)
8490 out->af_period_multiplier = af_period_multiplier;
8491 else
8492 out->af_period_multiplier = 1;
8493
Andy Hunga1f48fa2019-07-01 18:14:53 -07008494 out->kernel_buffer_size = out->config.period_size * out->config.period_count;
8495
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008496 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07008497 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008498 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008499
8500 config->format = out->stream.common.get_format(&out->stream.common);
8501 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
8502 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308503 register_format(out->format, out->supported_formats);
8504 register_channel_mask(out->channel_mask, out->supported_channel_masks);
8505 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008506
Aalique Grahame22e49102018-12-18 14:23:57 -08008507 out->error_log = error_log_create(
8508 ERROR_LOG_ENTRIES,
8509 1000000000 /* aggregate consecutive identical errors within one second in ns */);
8510
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308511 /*
8512 By locking output stream before registering, we allow the callback
8513 to update stream's state only after stream's initial state is set to
8514 adev state.
8515 */
8516 lock_output_stream(out);
8517 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
8518 pthread_mutex_lock(&adev->lock);
8519 out->card_status = adev->card_status;
8520 pthread_mutex_unlock(&adev->lock);
8521 pthread_mutex_unlock(&out->lock);
8522
Aalique Grahame22e49102018-12-18 14:23:57 -08008523 stream_app_type_cfg_init(&out->app_type_cfg);
8524
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008525 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308526 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07008527 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008528
8529 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
8530 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
8531 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008532 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05308533 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008534 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07008535 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05308536 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
8537 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008538 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
8539 out->usecase, PCM_PLAYBACK);
8540 hdlr_stream_cfg.flags = out->flags;
8541 hdlr_stream_cfg.type = PCM_PLAYBACK;
8542 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
8543 &hdlr_stream_cfg);
8544 if (ret) {
8545 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
8546 out->adsp_hdlr_stream_handle = NULL;
8547 }
8548 }
Gangadhar Sb0210342019-02-22 17:39:41 +05308549 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
8550 is_direct_passthough, false);
8551 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
8552 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07008553 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07008554 if (ret < 0) {
8555 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
8556 out->ip_hdlr_handle = NULL;
8557 }
8558 }
Derek Chenf939fb72018-11-13 13:34:41 -08008559
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008560 ret = io_streams_map_insert(adev, &out->stream.common,
8561 out->handle, AUDIO_PATCH_HANDLE_NONE);
8562 if (ret != 0)
8563 goto error_open;
8564
Derek Chenf939fb72018-11-13 13:34:41 -08008565 streams_output_ctxt_t *out_ctxt = (streams_output_ctxt_t *)
8566 calloc(1, sizeof(streams_output_ctxt_t));
8567 if (out_ctxt == NULL) {
8568 ALOGE("%s fail to allocate output ctxt", __func__);
8569 ret = -ENOMEM;
8570 goto error_open;
8571 }
8572 out_ctxt->output = out;
8573
8574 pthread_mutex_lock(&adev->lock);
8575 list_add_tail(&adev->active_outputs_list, &out_ctxt->list);
8576 pthread_mutex_unlock(&adev->lock);
8577
Eric Laurent994a6932013-07-17 11:51:42 -07008578 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008579 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008580
8581error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05308582 if (out->convert_buffer)
8583 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008584 free(out);
8585 *stream_out = NULL;
8586 ALOGD("%s: exit: ret %d", __func__, ret);
8587 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008588}
8589
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308590void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008591 struct audio_stream_out *stream)
8592{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008593 struct stream_out *out = (struct stream_out *)stream;
8594 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008595 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008596
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008597 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308598
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008599 io_streams_map_remove(adev, out->handle);
8600
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308601 // must deregister from sndmonitor first to prevent races
8602 // between the callback and close_stream
8603 audio_extn_snd_mon_unregister_listener(out);
8604
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008605 /* close adsp hdrl session before standby */
8606 if (out->adsp_hdlr_stream_handle) {
8607 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
8608 if (ret)
8609 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
8610 out->adsp_hdlr_stream_handle = NULL;
8611 }
8612
Manish Dewangan21a850a2017-08-14 12:03:55 +05308613 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07008614 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
8615 out->ip_hdlr_handle = NULL;
8616 }
8617
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008618 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308619 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008620 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308621 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308622 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008623 if(ret != 0)
8624 ALOGE("%s: Compress voip output cannot be closed, error:%d",
8625 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008626 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008627 out_standby(&stream->common);
8628
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008629 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008630 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008631 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008632 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008633 if (out->compr_config.codec != NULL)
8634 free(out->compr_config.codec);
8635 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008636
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05308637 out->a2dp_compress_mute = false;
8638
Varun Balaraje49253e2017-07-06 19:48:56 +05308639 if (is_interactive_usecase(out->usecase))
8640 free_interactive_usecase(adev, out->usecase);
8641
Ashish Jain83a6cc22016-06-28 14:34:17 +05308642 if (out->convert_buffer != NULL) {
8643 free(out->convert_buffer);
8644 out->convert_buffer = NULL;
8645 }
8646
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008647 if (adev->voice_tx_output == out)
8648 adev->voice_tx_output = NULL;
8649
Aalique Grahame22e49102018-12-18 14:23:57 -08008650 error_log_destroy(out->error_log);
8651 out->error_log = NULL;
8652
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05308653 if (adev->primary_output == out)
8654 adev->primary_output = NULL;
8655
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008656 pthread_cond_destroy(&out->cond);
8657 pthread_mutex_destroy(&out->lock);
Derek Chenf939fb72018-11-13 13:34:41 -08008658
8659 pthread_mutex_lock(&adev->lock);
8660 streams_output_ctxt_t *out_ctxt = out_get_stream(adev, out->handle);
8661 if (out_ctxt != NULL) {
8662 list_remove(&out_ctxt->list);
8663 free(out_ctxt);
8664 } else {
8665 ALOGW("%s, output stream already closed", __func__);
8666 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008667 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08008668 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07008669 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008670}
8671
8672static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
8673{
8674 struct audio_device *adev = (struct audio_device *)dev;
8675 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008676 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008677 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008678 int ret;
8679 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08008680 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008681 struct listnode *node;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008682 int controller = -1, stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008683
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008684 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008685 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008686
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308687 if (!parms)
8688 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05308689
Derek Chen6f293672019-04-01 01:40:24 -07008690 /* notify adev and input/output streams on the snd card status */
8691 adev_snd_mon_cb((void *)adev, parms);
8692
8693 list_for_each(node, &adev->active_outputs_list) {
8694 streams_output_ctxt_t *out_ctxt = node_to_item(node,
8695 streams_output_ctxt_t,
8696 list);
8697 out_snd_mon_cb((void *)out_ctxt->output, parms);
8698 }
8699
8700 list_for_each(node, &adev->active_inputs_list) {
8701 streams_input_ctxt_t *in_ctxt = node_to_item(node,
8702 streams_input_ctxt_t,
8703 list);
8704 in_snd_mon_cb((void *)in_ctxt->input, parms);
8705 }
8706
Zhou Songd6d71752019-05-21 18:08:51 +08008707 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308708 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
8709 if (ret >= 0) {
8710 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08008711 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308712 adev->bt_sco_on = true;
Zhou Songd6d71752019-05-21 18:08:51 +08008713 } else {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308714 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008715 audio_extn_sco_reset_configuration();
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008716 }
8717 }
8718
8719 ret = str_parms_get_str(parms, "A2dpSuspended", value, sizeof(value));
8720 if (ret>=0) {
8721 if (!strncmp(value, "false", 5) &&
8722 audio_extn_a2dp_source_is_suspended()) {
8723 struct audio_usecase *usecase;
8724 struct listnode *node;
Zhou Songd6d71752019-05-21 18:08:51 +08008725 list_for_each(node, &adev->usecase_list) {
8726 usecase = node_to_item(node, struct audio_usecase, list);
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008727 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008728 is_sco_in_device_type(&usecase->stream.in->device_list)) {
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008729 ALOGD("a2dp resumed, switch bt sco mic to handset mic");
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008730 reassign_device_list(&usecase->stream.in->device_list,
8731 AUDIO_DEVICE_IN_BUILTIN_MIC, "");
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008732 select_devices(adev, usecase->id);
8733 }
Zhou Songd6d71752019-05-21 18:08:51 +08008734 }
8735 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308736 }
8737
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008738 status = voice_set_parameters(adev, parms);
8739 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008740 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008741
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008742 status = platform_set_parameters(adev->platform, parms);
8743 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008744 goto done;
8745
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008746 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
8747 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07008748 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008749 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8750 adev->bluetooth_nrec = true;
8751 else
8752 adev->bluetooth_nrec = false;
8753 }
8754
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008755 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
8756 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008757 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8758 adev->screen_off = false;
8759 else
8760 adev->screen_off = true;
Quinn Male70f20f32019-06-26 16:50:26 -07008761 audio_extn_sound_trigger_update_screen_status(adev->screen_off);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008762 }
8763
Eric Laurent4b084132018-10-19 17:33:43 -07008764 ret = str_parms_get_int(parms, "rotation", &val);
8765 if (ret >= 0) {
8766 bool reverse_speakers = false;
8767 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8768 switch (val) {
8769 // FIXME: note that the code below assumes that the speakers are in the correct placement
8770 // relative to the user when the device is rotated 90deg from its default rotation. This
8771 // assumption is device-specific, not platform-specific like this code.
8772 case 270:
8773 reverse_speakers = true;
8774 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
8775 break;
8776 case 0:
8777 case 180:
8778 camera_rotation = CAMERA_ROTATION_PORTRAIT;
8779 break;
8780 case 90:
8781 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8782 break;
8783 default:
8784 ALOGE("%s: unexpected rotation of %d", __func__, val);
8785 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008786 }
Eric Laurent4b084132018-10-19 17:33:43 -07008787 if (status == 0) {
8788 // check and set swap
8789 // - check if orientation changed and speaker active
8790 // - set rotation and cache the rotation value
8791 adev->camera_orientation =
8792 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
8793 if (!audio_extn_is_maxx_audio_enabled())
8794 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
8795 }
8796 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008797
Mingming Yin514a8bc2014-07-29 15:22:21 -07008798 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
8799 if (ret >= 0) {
8800 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8801 adev->bt_wb_speech_enabled = true;
8802 else
8803 adev->bt_wb_speech_enabled = false;
8804 }
8805
Zhou Song12c29502019-03-16 10:37:18 +08008806 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
8807 if (ret >= 0) {
8808 val = atoi(value);
8809 adev->swb_speech_mode = val;
8810 }
8811
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008812 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
8813 if (ret >= 0) {
8814 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308815 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08008816 if (audio_is_output_device(val) &&
8817 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008818 ALOGV("cache new ext disp type and edid");
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008819 platform_get_controller_stream_from_params(parms, &controller, &stream);
8820 platform_set_ext_display_device_v2(adev->platform, controller, stream);
8821 ret = platform_get_ext_disp_type_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008822 if (ret < 0) {
8823 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05308824 } else {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008825 platform_cache_edid_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008826 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308827 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07008828 /*
8829 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
8830 * Per AudioPolicyManager, USB device is higher priority than WFD.
8831 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
8832 * If WFD use case occupies AFE proxy, it may result unintended behavior while
8833 * starting voice call on USB
8834 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008835 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308836 if (ret >= 0)
8837 audio_extn_usb_add_device(device, atoi(value));
8838
Zhou Song6f862822017-11-06 17:27:57 +08008839 if (!audio_extn_usb_is_tunnel_supported()) {
8840 ALOGV("detected USB connect .. disable proxy");
8841 adev->allow_afe_proxy_usage = false;
8842 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008843 }
8844 }
8845
8846 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
8847 if (ret >= 0) {
8848 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308849 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07008850 /*
8851 * The HDMI / Displayport disconnect handling has been moved to
8852 * audio extension to ensure that its parameters are not
8853 * invalidated prior to updating sysfs of the disconnect event
8854 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
8855 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308856 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008857 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308858 if (ret >= 0)
8859 audio_extn_usb_remove_device(device, atoi(value));
8860
Zhou Song6f862822017-11-06 17:27:57 +08008861 if (!audio_extn_usb_is_tunnel_supported()) {
8862 ALOGV("detected USB disconnect .. enable proxy");
8863 adev->allow_afe_proxy_usage = true;
8864 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008865 }
8866 }
8867
Aalique Grahame22e49102018-12-18 14:23:57 -08008868 audio_extn_hfp_set_parameters(adev, parms);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008869 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08008870
8871 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08008872 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308873 struct audio_usecase *usecase;
8874 struct listnode *node;
8875 list_for_each(node, &adev->usecase_list) {
8876 usecase = node_to_item(node, struct audio_usecase, list);
Weiyin Jiangff56ff32020-05-08 14:32:21 +08008877 if ((usecase->stream.out == NULL) || (usecase->type != PCM_PLAYBACK))
8878 continue;
8879
8880 if (is_a2dp_out_device_type(&usecase->device_list)) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308881 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08008882 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308883 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08008884 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308885 audio_extn_a2dp_set_handoff_mode(true);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308886 ALOGD("Switching to speaker and muting the stream before select_devices");
8887 check_a2dp_restore_l(adev, usecase->stream.out, false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308888 //force device switch to re configure encoder
8889 select_devices(adev, usecase->id);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308890 ALOGD("Unmuting the stream after select_devices");
8891 usecase->stream.out->a2dp_compress_mute = false;
8892 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 +05308893 audio_extn_a2dp_set_handoff_mode(false);
8894 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308895 break;
Manisha Agarwal6a6fb9a2019-12-04 11:38:41 +05308896 } else if ((usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
8897 usecase->stream.out->a2dp_compress_mute) {
8898 pthread_mutex_unlock(&adev->lock);
8899 lock_output_stream(usecase->stream.out);
8900 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008901 reassign_device_list(&usecase->stream.out->device_list,
8902 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, "");
Manisha Agarwal6a6fb9a2019-12-04 11:38:41 +05308903 check_a2dp_restore_l(adev, usecase->stream.out, true);
8904 pthread_mutex_unlock(&usecase->stream.out->lock);
8905 break;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308906 }
8907 }
8908 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008909
8910 //handle vr audio setparam
8911 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8912 value, sizeof(value));
8913 if (ret >= 0) {
8914 ALOGI("Setting vr mode to be %s", value);
8915 if (!strncmp(value, "true", 4)) {
8916 adev->vr_audio_mode_enabled = true;
8917 ALOGI("Setting vr mode to true");
8918 } else if (!strncmp(value, "false", 5)) {
8919 adev->vr_audio_mode_enabled = false;
8920 ALOGI("Setting vr mode to false");
8921 } else {
8922 ALOGI("wrong vr mode set");
8923 }
8924 }
8925
Eric Laurent4b084132018-10-19 17:33:43 -07008926 //FIXME: to be replaced by proper video capture properties API
8927 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
8928 if (ret >= 0) {
8929 int camera_facing = CAMERA_FACING_BACK;
8930 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
8931 camera_facing = CAMERA_FACING_FRONT;
8932 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
8933 camera_facing = CAMERA_FACING_BACK;
8934 else {
8935 ALOGW("%s: invalid camera facing value: %s", __func__, value);
8936 goto done;
8937 }
8938 adev->camera_orientation =
8939 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
8940 struct audio_usecase *usecase;
8941 struct listnode *node;
8942 list_for_each(node, &adev->usecase_list) {
8943 usecase = node_to_item(node, struct audio_usecase, list);
8944 struct stream_in *in = usecase->stream.in;
8945 if (usecase->type == PCM_CAPTURE && in != NULL &&
8946 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
8947 select_devices(adev, in->usecase);
8948 }
8949 }
8950 }
8951
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308952 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008953done:
8954 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008955 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308956error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008957 ALOGV("%s: exit with code(%d)", __func__, status);
8958 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008959}
8960
8961static char* adev_get_parameters(const struct audio_hw_device *dev,
8962 const char *keys)
8963{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308964 ALOGD("%s:%s", __func__, keys);
8965
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008966 struct audio_device *adev = (struct audio_device *)dev;
8967 struct str_parms *reply = str_parms_create();
8968 struct str_parms *query = str_parms_create_str(keys);
8969 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05308970 char value[256] = {0};
8971 int ret = 0;
8972
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008973 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08008974 if (reply) {
8975 str_parms_destroy(reply);
8976 }
8977 if (query) {
8978 str_parms_destroy(query);
8979 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008980 ALOGE("adev_get_parameters: failed to create query or reply");
8981 return NULL;
8982 }
8983
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008984 //handle vr audio getparam
8985
8986 ret = str_parms_get_str(query,
8987 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8988 value, sizeof(value));
8989
8990 if (ret >= 0) {
8991 bool vr_audio_enabled = false;
8992 pthread_mutex_lock(&adev->lock);
8993 vr_audio_enabled = adev->vr_audio_mode_enabled;
8994 pthread_mutex_unlock(&adev->lock);
8995
8996 ALOGI("getting vr mode to %d", vr_audio_enabled);
8997
8998 if (vr_audio_enabled) {
8999 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9000 "true");
9001 goto exit;
9002 } else {
9003 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9004 "false");
9005 goto exit;
9006 }
9007 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009008
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009009 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009010 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08009011 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08009012 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009013 platform_get_parameters(adev->platform, query, reply);
justinwengd5395152019-11-04 12:23:09 +08009014 audio_extn_ma_get_parameters(adev, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05309015 pthread_mutex_unlock(&adev->lock);
9016
Naresh Tannirud7205b62014-06-20 02:54:48 +05309017exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009018 str = str_parms_to_str(reply);
9019 str_parms_destroy(query);
9020 str_parms_destroy(reply);
9021
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05309022 ALOGD("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009023 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009024}
9025
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009026static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009027{
9028 return 0;
9029}
9030
9031static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
9032{
Haynes Mathew George5191a852013-09-11 14:19:36 -07009033 int ret;
9034 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08009035
9036 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
9037
Haynes Mathew George5191a852013-09-11 14:19:36 -07009038 pthread_mutex_lock(&adev->lock);
9039 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07009040 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07009041 pthread_mutex_unlock(&adev->lock);
9042 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009043}
9044
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009045static int adev_set_master_volume(struct audio_hw_device *dev __unused,
9046 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009047{
9048 return -ENOSYS;
9049}
9050
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009051static int adev_get_master_volume(struct audio_hw_device *dev __unused,
9052 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009053{
9054 return -ENOSYS;
9055}
9056
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009057static int adev_set_master_mute(struct audio_hw_device *dev __unused,
9058 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009059{
9060 return -ENOSYS;
9061}
9062
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009063static int adev_get_master_mute(struct audio_hw_device *dev __unused,
9064 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009065{
9066 return -ENOSYS;
9067}
9068
9069static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
9070{
9071 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07009072 struct listnode *node;
9073 struct audio_usecase *usecase = NULL;
9074 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08009075
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009076 pthread_mutex_lock(&adev->lock);
9077 if (adev->mode != mode) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309078 ALOGD("%s: mode %d , prev_mode %d \n", __func__, mode , adev->mode);
9079 adev->prev_mode = adev->mode; /* prev_mode is kept to handle voip concurrency*/
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009080 adev->mode = mode;
Jaideep Sharma477917f2020-03-13 18:13:33 +05309081 if( mode == AUDIO_MODE_CALL_SCREEN ){
9082 adev->current_call_output = adev->primary_output;
9083 voice_start_call(adev);
9084 } else if (voice_is_in_call_or_call_screen(adev) &&
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08009085 (mode == AUDIO_MODE_NORMAL ||
9086 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07009087 list_for_each(node, &adev->usecase_list) {
9088 usecase = node_to_item(node, struct audio_usecase, list);
9089 if (usecase->type == VOICE_CALL)
9090 break;
9091 }
9092 if (usecase &&
9093 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
9094 ret = audio_extn_usb_check_and_set_svc_int(usecase,
9095 true);
9096 if (ret != 0) {
9097 /* default service interval was successfully updated,
9098 reopen USB backend with new service interval */
9099 check_usecases_codec_backend(adev,
9100 usecase,
9101 usecase->out_snd_device);
9102 }
9103 }
9104
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009105 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07009106 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009107 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08009108 // restore device for other active usecases after stop call
9109 list_for_each(node, &adev->usecase_list) {
9110 usecase = node_to_item(node, struct audio_usecase, list);
9111 select_devices(adev, usecase->id);
9112 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009113 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009114 }
9115 pthread_mutex_unlock(&adev->lock);
9116 return 0;
9117}
9118
9119static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
9120{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009121 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08009122 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009123
9124 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08009125 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009126 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009127
Derek Chend2530072014-11-24 12:39:14 -08009128 if (adev->ext_hw_plugin)
9129 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009130
9131 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009132 pthread_mutex_unlock(&adev->lock);
9133
9134 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009135}
9136
9137static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
9138{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009139 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009140 return 0;
9141}
9142
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009143static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009144 const struct audio_config *config)
9145{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009146 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009147
Aalique Grahame22e49102018-12-18 14:23:57 -08009148 /* Don't know if USB HIFI in this context so use true to be conservative */
9149 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9150 true /*is_usb_hifi */) != 0)
9151 return 0;
9152
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009153 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
9154 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009155}
9156
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009157static bool adev_input_allow_hifi_record(struct audio_device *adev,
9158 audio_devices_t devices,
9159 audio_input_flags_t flags,
9160 audio_source_t source) {
9161 const bool allowed = true;
9162
9163 if (!audio_is_usb_in_device(devices))
9164 return !allowed;
9165
9166 switch (flags) {
9167 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009168 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07009169 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
9170 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009171 default:
9172 return !allowed;
9173 }
9174
9175 switch (source) {
9176 case AUDIO_SOURCE_DEFAULT:
9177 case AUDIO_SOURCE_MIC:
9178 case AUDIO_SOURCE_UNPROCESSED:
9179 break;
9180 default:
9181 return !allowed;
9182 }
9183
9184 switch (adev->mode) {
9185 case 0:
9186 break;
9187 default:
9188 return !allowed;
9189 }
9190
9191 return allowed;
9192}
9193
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009194static int adev_update_voice_comm_input_stream(struct stream_in *in,
9195 struct audio_config *config)
9196{
9197 bool valid_rate = (config->sample_rate == 8000 ||
9198 config->sample_rate == 16000 ||
9199 config->sample_rate == 32000 ||
9200 config->sample_rate == 48000);
9201 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
9202
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009203 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08009204 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009205 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9206 in->config = default_pcm_config_voip_copp;
9207 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
9208 DEFAULT_VOIP_BUF_DURATION_MS,
9209 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009210 } else {
9211 ALOGW("%s No valid input in voip, use defaults"
9212 "sample rate %u, channel mask 0x%X",
9213 __func__, config->sample_rate, in->channel_mask);
9214 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009215 in->config.rate = config->sample_rate;
9216 in->sample_rate = config->sample_rate;
9217 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009218 //XXX needed for voice_extn_compress_voip_open_input_stream
9219 in->config.rate = config->sample_rate;
9220 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
Shalini Manjunathaa763cc42019-08-23 15:13:46 +05309221 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009222 voice_extn_compress_voip_is_active(in->dev)) &&
9223 (voice_extn_compress_voip_is_format_supported(in->format)) &&
9224 valid_rate && valid_ch) {
9225 voice_extn_compress_voip_open_input_stream(in);
9226 // update rate entries to match config from AF
9227 in->config.rate = config->sample_rate;
9228 in->sample_rate = config->sample_rate;
9229 } else {
9230 ALOGW("%s compress voip not active, use defaults", __func__);
9231 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009232 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009233 return 0;
9234}
9235
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009236static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07009237 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009238 audio_devices_t devices,
9239 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009240 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309241 audio_input_flags_t flags,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009242 const char *address,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009243 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009244{
9245 struct audio_device *adev = (struct audio_device *)dev;
9246 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009247 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009248 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009249 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05309250 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009251 bool is_usb_dev = audio_is_usb_in_device(devices);
9252 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
9253 devices,
9254 flags,
9255 source);
Andy Hung94320602018-10-29 18:31:12 -07009256 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
9257 " sample_rate %u, channel_mask %#x, format %#x",
9258 __func__, flags, is_usb_dev, may_use_hifi_record,
9259 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309260
kunleizdff872d2018-08-20 14:40:33 +08009261 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08009262 is_usb_dev = false;
9263 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
9264 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
9265 __func__, devices);
9266 }
9267
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009268 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009269
9270 if (!(is_usb_dev && may_use_hifi_record)) {
9271 if (config->sample_rate == 0)
9272 config->sample_rate = 48000;
9273 if (config->channel_mask == AUDIO_CHANNEL_NONE)
9274 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9275 if (config->format == AUDIO_FORMAT_DEFAULT)
9276 config->format = AUDIO_FORMAT_PCM_16_BIT;
9277
9278 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
9279
Aalique Grahame22e49102018-12-18 14:23:57 -08009280 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9281 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009282 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05309283 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009284
Rahul Sharma99770982019-03-06 17:05:26 +05309285 pthread_mutex_lock(&adev->lock);
9286 if (in_get_stream(adev, handle) != NULL) {
9287 ALOGW("%s, input stream already opened", __func__);
9288 ret = -EEXIST;
9289 }
9290 pthread_mutex_unlock(&adev->lock);
9291 if (ret)
9292 return ret;
9293
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009294 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009295
9296 if (!in) {
9297 ALOGE("failed to allocate input stream");
9298 return -ENOMEM;
9299 }
9300
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309301 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05309302 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
9303 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009304 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07009305 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009306
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009307 in->stream.common.get_sample_rate = in_get_sample_rate;
9308 in->stream.common.set_sample_rate = in_set_sample_rate;
9309 in->stream.common.get_buffer_size = in_get_buffer_size;
9310 in->stream.common.get_channels = in_get_channels;
9311 in->stream.common.get_format = in_get_format;
9312 in->stream.common.set_format = in_set_format;
9313 in->stream.common.standby = in_standby;
9314 in->stream.common.dump = in_dump;
9315 in->stream.common.set_parameters = in_set_parameters;
9316 in->stream.common.get_parameters = in_get_parameters;
9317 in->stream.common.add_audio_effect = in_add_audio_effect;
9318 in->stream.common.remove_audio_effect = in_remove_audio_effect;
9319 in->stream.set_gain = in_set_gain;
9320 in->stream.read = in_read;
9321 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08009322 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309323 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07009324 in->stream.set_microphone_direction = in_set_microphone_direction;
9325 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07009326 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009327
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009328 list_init(&in->device_list);
9329 update_device_list(&in->device_list, devices, address, true);
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009330 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009331 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009332 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009333 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009334 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07009335 in->bit_width = 16;
9336 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07009337 in->direction = MIC_DIRECTION_UNSPECIFIED;
9338 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08009339 list_init(&in->aec_list);
9340 list_init(&in->ns_list);
Phil Burkd898ba62019-06-20 12:49:01 -07009341 in->mmap_shared_memory_fd = -1; // not open
Haynes Mathew George46740472017-10-27 18:40:12 -07009342
Andy Hung94320602018-10-29 18:31:12 -07009343 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08009344 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
9345 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
9346 /* Force channel config requested to mono if incall
9347 record is being requested for only uplink/downlink */
9348 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
9349 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9350 ret = -EINVAL;
9351 goto err_open;
9352 }
9353 }
9354
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009355 if (is_usb_dev && may_use_hifi_record) {
9356 /* HiFi record selects an appropriate format, channel, rate combo
9357 depending on sink capabilities*/
9358 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
9359 &config->format,
9360 &in->supported_formats[0],
9361 MAX_SUPPORTED_FORMATS,
9362 &config->channel_mask,
9363 &in->supported_channel_masks[0],
9364 MAX_SUPPORTED_CHANNEL_MASKS,
9365 &config->sample_rate,
9366 &in->supported_sample_rates[0],
9367 MAX_SUPPORTED_SAMPLE_RATES);
9368 if (ret != 0) {
9369 ret = -EINVAL;
9370 goto err_open;
9371 }
9372 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009373 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309374 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05309375 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
9376 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
9377 in->config.format = PCM_FORMAT_S32_LE;
9378 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309379 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
9380 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
9381 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
9382 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
9383 bool ret_error = false;
9384 in->bit_width = 24;
9385 /* 24 bit is restricted to UNPROCESSED source only,also format supported
9386 from HAL is 24_packed and 8_24
9387 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
9388 24_packed return error indicating supported format is 24_packed
9389 *> In case of any other source requesting 24 bit or float return error
9390 indicating format supported is 16 bit only.
9391
9392 on error flinger will retry with supported format passed
9393 */
9394 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
9395 (source != AUDIO_SOURCE_CAMCORDER)) {
9396 config->format = AUDIO_FORMAT_PCM_16_BIT;
9397 if (config->sample_rate > 48000)
9398 config->sample_rate = 48000;
9399 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07009400 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
9401 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309402 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
9403 ret_error = true;
9404 }
9405
9406 if (ret_error) {
9407 ret = -EINVAL;
9408 goto err_open;
9409 }
9410 }
9411
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009412 in->channel_mask = config->channel_mask;
9413 in->format = config->format;
9414
9415 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309416
9417 if (in->source == AUDIO_SOURCE_FM_TUNER) {
9418 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
9419 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
9420 else {
9421 ret = -EINVAL;
9422 goto err_open;
9423 }
9424 }
9425
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009426 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Deeraj Somanfa377bf2019-02-06 12:57:59 +05309427 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
9428 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009429 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
9430 is_low_latency = true;
9431#if LOW_LATENCY_CAPTURE_USE_CASE
9432 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
9433#endif
9434 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08009435 if (!in->realtime) {
9436 in->config = pcm_config_audio_capture;
9437 frame_size = audio_stream_in_frame_size(&in->stream);
9438 buffer_size = get_input_buffer_size(config->sample_rate,
9439 config->format,
9440 channel_count,
9441 is_low_latency);
9442 in->config.period_size = buffer_size / frame_size;
9443 in->config.rate = config->sample_rate;
9444 in->af_period_multiplier = 1;
9445 } else {
9446 // period size is left untouched for rt mode playback
9447 in->config = pcm_config_audio_capture_rt;
9448 in->af_period_multiplier = af_period_multiplier;
9449 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009450 }
9451
9452 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
9453 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
9454 in->realtime = 0;
9455 in->usecase = USECASE_AUDIO_RECORD_MMAP;
9456 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07009457 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009458 in->stream.start = in_start;
9459 in->stream.stop = in_stop;
9460 in->stream.create_mmap_buffer = in_create_mmap_buffer;
9461 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009462 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
Haynes Mathew George46740472017-10-27 18:40:12 -07009463 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009464 in->usecase = USECASE_AUDIO_RECORD_HIFI;
9465 in->config = pcm_config_audio_capture;
9466 frame_size = audio_stream_in_frame_size(&in->stream);
9467 buffer_size = get_input_buffer_size(config->sample_rate,
9468 config->format,
9469 channel_count,
9470 false /*is_low_latency*/);
9471 in->config.period_size = buffer_size / frame_size;
9472 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009473 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07009474 switch (config->format) {
9475 case AUDIO_FORMAT_PCM_32_BIT:
9476 in->bit_width = 32;
9477 break;
9478 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
9479 case AUDIO_FORMAT_PCM_8_24_BIT:
9480 in->bit_width = 24;
9481 break;
9482 default:
9483 in->bit_width = 16;
9484 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009485 } else if (is_single_device_type_equal(&in->device_list,
9486 AUDIO_DEVICE_IN_TELEPHONY_RX) ||
9487 is_single_device_type_equal(&in->device_list,
9488 AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009489 if (config->sample_rate == 0)
9490 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9491 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
9492 config->sample_rate != 8000) {
9493 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9494 ret = -EINVAL;
9495 goto err_open;
9496 }
9497 if (config->format == AUDIO_FORMAT_DEFAULT)
9498 config->format = AUDIO_FORMAT_PCM_16_BIT;
9499 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
9500 config->format = AUDIO_FORMAT_PCM_16_BIT;
9501 ret = -EINVAL;
9502 goto err_open;
9503 }
9504
9505 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
Zhou Song62ea0282020-03-22 19:53:01 +08009506 if (adev->ha_proxy_enable &&
9507 is_single_device_type_equal(&in->device_list,
9508 AUDIO_DEVICE_IN_TELEPHONY_RX))
9509 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY2;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009510 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009511 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08009512 in->af_period_multiplier = 1;
9513 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
9514 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
9515 (config->sample_rate == 8000 ||
9516 config->sample_rate == 16000 ||
9517 config->sample_rate == 32000 ||
9518 config->sample_rate == 48000) &&
9519 channel_count == 1) {
9520 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9521 in->config = pcm_config_audio_capture;
9522 frame_size = audio_stream_in_frame_size(&in->stream);
9523 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
9524 config->sample_rate,
9525 config->format,
9526 channel_count, false /*is_low_latency*/);
9527 in->config.period_size = buffer_size / frame_size;
9528 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
9529 in->config.rate = config->sample_rate;
9530 in->af_period_multiplier = 1;
Haynes Mathew George46740472017-10-27 18:40:12 -07009531 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05309532 int ret_val;
9533 pthread_mutex_lock(&adev->lock);
9534 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
9535 in, config, &channel_mask_updated);
9536 pthread_mutex_unlock(&adev->lock);
9537
9538 if (!ret_val) {
9539 if (channel_mask_updated == true) {
9540 ALOGD("%s: return error to retry with updated channel mask (%#x)",
9541 __func__, config->channel_mask);
9542 ret = -EINVAL;
9543 goto err_open;
9544 }
9545 ALOGD("%s: created multi-channel session succesfully",__func__);
9546 } else if (audio_extn_compr_cap_enabled() &&
9547 audio_extn_compr_cap_format_supported(config->format) &&
9548 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
9549 audio_extn_compr_cap_init(in);
9550 } else if (audio_extn_cin_applicable_stream(in)) {
Deeraj Soman14230922019-01-30 16:39:30 +05309551 ret = audio_extn_cin_configure_input_stream(in, config);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309552 if (ret)
9553 goto err_open;
9554 } else {
9555 in->config = pcm_config_audio_capture;
9556 in->config.rate = config->sample_rate;
9557 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309558 in->format = config->format;
9559 frame_size = audio_stream_in_frame_size(&in->stream);
9560 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07009561 config->format,
9562 channel_count,
9563 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02009564 /* prevent division-by-zero */
9565 if (frame_size == 0) {
9566 ALOGE("%s: Error frame_size==0", __func__);
9567 ret = -EINVAL;
9568 goto err_open;
9569 }
9570
Revathi Uddarajud2634032017-12-07 14:42:34 +05309571 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08009572 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009573
Revathi Uddarajud2634032017-12-07 14:42:34 +05309574 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9575 /* optionally use VOIP usecase depending on config(s) */
9576 ret = adev_update_voice_comm_input_stream(in, config);
9577 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009578
Revathi Uddarajud2634032017-12-07 14:42:34 +05309579 if (ret) {
9580 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
9581 goto err_open;
9582 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009583 }
Jaideep Sharmad305a4a2020-02-27 14:29:04 +05309584
9585 /* assign concurrent capture usecase if record has to caried out from
9586 * actual hardware input source */
9587 if (audio_extn_is_concurrent_capture_enabled() &&
9588 !audio_is_virtual_input_source(in->source)) {
Samyak Jainc37062f2019-04-25 18:41:06 +05309589 /* Acquire lock to avoid two concurrent use cases initialized to
9590 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +08009591
Samyak Jainc37062f2019-04-25 18:41:06 +05309592 if (in->usecase == USECASE_AUDIO_RECORD) {
9593 pthread_mutex_lock(&adev->lock);
9594 if (!(adev->pcm_record_uc_state)) {
9595 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
9596 adev->pcm_record_uc_state = 1;
9597 pthread_mutex_unlock(&adev->lock);
9598 } else {
9599 pthread_mutex_unlock(&adev->lock);
9600 /* Assign compress record use case for second record */
9601 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
9602 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
9603 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
9604 if (audio_extn_cin_applicable_stream(in)) {
9605 in->sample_rate = config->sample_rate;
Deeraj Soman14230922019-01-30 16:39:30 +05309606 ret = audio_extn_cin_configure_input_stream(in, config);
Samyak Jainc37062f2019-04-25 18:41:06 +05309607 if (ret)
9608 goto err_open;
9609 }
9610 }
9611 }
kunleiz28c73e72019-03-27 17:24:04 +08009612 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009613 }
Ramjee Singh82fd0c12019-08-21 16:31:33 +05309614 if (audio_extn_ssr_get_stream() != in)
9615 in->config.channels = channel_count;
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009616
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009617 in->sample_rate = in->config.rate;
9618
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309619 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
9620 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009621 &in->device_list, flags, in->format,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009622 in->sample_rate, in->bit_width,
9623 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05309624 register_format(in->format, in->supported_formats);
9625 register_channel_mask(in->channel_mask, in->supported_channel_masks);
9626 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309627
Aalique Grahame22e49102018-12-18 14:23:57 -08009628 in->error_log = error_log_create(
9629 ERROR_LOG_ENTRIES,
9630 1000000000 /* aggregate consecutive identical errors within one second */);
9631
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009632 /* This stream could be for sound trigger lab,
9633 get sound trigger pcm if present */
9634 audio_extn_sound_trigger_check_and_get_session(in);
9635
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309636 lock_input_stream(in);
9637 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
9638 pthread_mutex_lock(&adev->lock);
9639 in->card_status = adev->card_status;
9640 pthread_mutex_unlock(&adev->lock);
9641 pthread_mutex_unlock(&in->lock);
9642
Aalique Grahame22e49102018-12-18 14:23:57 -08009643 stream_app_type_cfg_init(&in->app_type_cfg);
9644
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009645 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -08009646
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009647 ret = io_streams_map_insert(adev, &in->stream.common,
9648 handle, AUDIO_PATCH_HANDLE_NONE);
9649 if (ret != 0)
9650 goto err_open;
9651
Derek Chenf939fb72018-11-13 13:34:41 -08009652 streams_input_ctxt_t *in_ctxt = (streams_input_ctxt_t *)
9653 calloc(1, sizeof(streams_input_ctxt_t));
9654 if (in_ctxt == NULL) {
9655 ALOGE("%s fail to allocate input ctxt", __func__);
9656 ret = -ENOMEM;
9657 goto err_open;
9658 }
9659 in_ctxt->input = in;
9660
9661 pthread_mutex_lock(&adev->lock);
9662 list_add_tail(&adev->active_inputs_list, &in_ctxt->list);
9663 pthread_mutex_unlock(&adev->lock);
9664
Eric Laurent994a6932013-07-17 11:51:42 -07009665 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009666 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009667
9668err_open:
Samyak Jainc37062f2019-04-25 18:41:06 +05309669 if (in->usecase == USECASE_AUDIO_RECORD) {
9670 pthread_mutex_lock(&adev->lock);
9671 adev->pcm_record_uc_state = 0;
9672 pthread_mutex_unlock(&adev->lock);
9673 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009674 free(in);
9675 *stream_in = NULL;
9676 return ret;
9677}
9678
9679static void adev_close_input_stream(struct audio_hw_device *dev,
9680 struct audio_stream_in *stream)
9681{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009682 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009683 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009684 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309685
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309686 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08009687
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009688 if (in == NULL) {
9689 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
9690 return;
9691 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009692 io_streams_map_remove(adev, in->capture_handle);
9693
kunleiz70e57612018-12-28 17:50:23 +08009694 /* must deregister from sndmonitor first to prevent races
9695 * between the callback and close_stream
9696 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309697 audio_extn_snd_mon_unregister_listener(stream);
9698
kunleiz70e57612018-12-28 17:50:23 +08009699 /* Disable echo reference if there are no active input, hfp call
9700 * and sound trigger while closing input stream
9701 */
Eric Laurent637e2d42018-11-15 12:24:31 -08009702 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +08009703 !audio_extn_hfp_is_active(adev) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009704 !audio_extn_sound_trigger_check_ec_ref_enable()) {
9705 struct listnode out_devices;
9706 list_init(&out_devices);
9707 platform_set_echo_reference(adev, false, &out_devices);
9708 } else
kunleiz70e57612018-12-28 17:50:23 +08009709 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05309710
Weiyin Jiang2995f662019-04-17 14:25:12 +08009711 error_log_destroy(in->error_log);
9712 in->error_log = NULL;
9713
Pallavid7c7a272018-01-16 11:22:55 +05309714
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009715 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309716 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009717 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309718 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009719 if (ret != 0)
9720 ALOGE("%s: Compress voip input cannot be closed, error:%d",
9721 __func__, ret);
9722 } else
9723 in_standby(&stream->common);
9724
Revathi Uddarajud2634032017-12-07 14:42:34 +05309725 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05309726 if (in->usecase == USECASE_AUDIO_RECORD) {
9727 adev->pcm_record_uc_state = 0;
9728 }
9729
Kunlei Zhang5d5d8d92020-02-26 15:00:59 +08009730 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9731 adev->enable_voicerx = false;
9732 }
9733
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07009734 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009735 audio_extn_ssr_deinit();
9736 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009737
Garmond Leunge2433c32017-09-28 21:51:22 -07009738 if (audio_extn_ffv_get_stream() == in) {
9739 audio_extn_ffv_stream_deinit();
9740 }
9741
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309742 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07009743 audio_extn_compr_cap_format_supported(in->config.format))
9744 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05309745
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05309746 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05309747 audio_extn_cin_free_input_stream_resources(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009748
Mingming Yinfd7607b2016-01-22 12:48:44 -08009749 if (in->is_st_session) {
9750 ALOGV("%s: sound trigger pcm stop lab", __func__);
9751 audio_extn_sound_trigger_stop_lab(in);
9752 }
Derek Chenf939fb72018-11-13 13:34:41 -08009753 streams_input_ctxt_t *in_ctxt = in_get_stream(adev, in->capture_handle);
9754 if (in_ctxt != NULL) {
9755 list_remove(&in_ctxt->list);
9756 free(in_ctxt);
9757 } else {
9758 ALOGW("%s, input stream already closed", __func__);
9759 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009760 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309761 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009762 return;
9763}
9764
Aalique Grahame22e49102018-12-18 14:23:57 -08009765/* verifies input and output devices and their capabilities.
9766 *
9767 * This verification is required when enabling extended bit-depth or
9768 * sampling rates, as not all qcom products support it.
9769 *
9770 * Suitable for calling only on initialization such as adev_open().
9771 * It fills the audio_device use_case_table[] array.
9772 *
9773 * Has a side-effect that it needs to configure audio routing / devices
9774 * in order to power up the devices and read the device parameters.
9775 * It does not acquire any hw device lock. Should restore the devices
9776 * back to "normal state" upon completion.
9777 */
9778static int adev_verify_devices(struct audio_device *adev)
9779{
9780 /* enumeration is a bit difficult because one really wants to pull
9781 * the use_case, device id, etc from the hidden pcm_device_table[].
9782 * In this case there are the following use cases and device ids.
9783 *
9784 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
9785 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
9786 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
9787 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
9788 * [USECASE_AUDIO_RECORD] = {0, 0},
9789 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
9790 * [USECASE_VOICE_CALL] = {2, 2},
9791 *
9792 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
9793 * USECASE_VOICE_CALL omitted, but possible for either input or output.
9794 */
9795
9796 /* should be the usecases enabled in adev_open_input_stream() */
9797 static const int test_in_usecases[] = {
9798 USECASE_AUDIO_RECORD,
9799 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
9800 };
9801 /* should be the usecases enabled in adev_open_output_stream()*/
9802 static const int test_out_usecases[] = {
9803 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
9804 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
9805 };
9806 static const usecase_type_t usecase_type_by_dir[] = {
9807 PCM_PLAYBACK,
9808 PCM_CAPTURE,
9809 };
9810 static const unsigned flags_by_dir[] = {
9811 PCM_OUT,
9812 PCM_IN,
9813 };
9814
9815 size_t i;
9816 unsigned dir;
9817 const unsigned card_id = adev->snd_card;
9818
9819 for (dir = 0; dir < 2; ++dir) {
9820 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
9821 const unsigned flags_dir = flags_by_dir[dir];
9822 const size_t testsize =
9823 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
9824 const int *testcases =
9825 dir ? test_in_usecases : test_out_usecases;
9826 const audio_devices_t audio_device =
9827 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
9828
9829 for (i = 0; i < testsize; ++i) {
9830 const audio_usecase_t audio_usecase = testcases[i];
9831 int device_id;
9832 struct pcm_params **pparams;
9833 struct stream_out out;
9834 struct stream_in in;
9835 struct audio_usecase uc_info;
9836 int retval;
9837
9838 pparams = &adev->use_case_table[audio_usecase];
9839 pcm_params_free(*pparams); /* can accept null input */
9840 *pparams = NULL;
9841
9842 /* find the device ID for the use case (signed, for error) */
9843 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
9844 if (device_id < 0)
9845 continue;
9846
9847 /* prepare structures for device probing */
9848 memset(&uc_info, 0, sizeof(uc_info));
9849 uc_info.id = audio_usecase;
9850 uc_info.type = usecase_type;
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009851 list_init(&uc_info.device_list);
Aalique Grahame22e49102018-12-18 14:23:57 -08009852 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -08009853 memset(&in, 0, sizeof(in));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009854 list_init(&in.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009855 update_device_list(&in.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009856 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
9857 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -08009858 }
9859 memset(&out, 0, sizeof(out));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009860 list_init(&out.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009861 update_device_list(&out.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009862 uc_info.stream.out = &out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009863 update_device_list(&uc_info.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009864 uc_info.in_snd_device = SND_DEVICE_NONE;
9865 uc_info.out_snd_device = SND_DEVICE_NONE;
9866 list_add_tail(&adev->usecase_list, &uc_info.list);
9867
9868 /* select device - similar to start_(in/out)put_stream() */
9869 retval = select_devices(adev, audio_usecase);
9870 if (retval >= 0) {
9871 *pparams = pcm_params_get(card_id, device_id, flags_dir);
9872#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -07009873 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -08009874 if (*pparams) {
9875 ALOGV("%s: (%s) card %d device %d", __func__,
9876 dir ? "input" : "output", card_id, device_id);
9877 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
9878 } else {
9879 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
9880 }
9881#endif
9882 }
9883
9884 /* deselect device - similar to stop_(in/out)put_stream() */
9885 /* 1. Get and set stream specific mixer controls */
9886 retval = disable_audio_route(adev, &uc_info);
9887 /* 2. Disable the rx device */
9888 retval = disable_snd_device(adev,
9889 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
9890 list_remove(&uc_info.list);
9891 }
9892 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009893 return 0;
9894}
9895
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009896int update_patch(unsigned int num_sources,
9897 const struct audio_port_config *sources,
9898 unsigned int num_sinks,
9899 const struct audio_port_config *sinks,
9900 audio_patch_handle_t handle,
9901 struct audio_patch_info *p_info,
9902 patch_type_t patch_type, bool new_patch)
9903{
9904 ALOGD("%s: enter", __func__);
9905
9906 if (p_info == NULL) {
9907 ALOGE("%s: Invalid patch pointer", __func__);
9908 return -EINVAL;
9909 }
9910
9911 if (new_patch) {
9912 p_info->patch = (struct audio_patch *) calloc(1, sizeof(struct audio_patch));
9913 if (p_info->patch == NULL) {
9914 ALOGE("%s: Could not allocate patch", __func__);
9915 return -ENOMEM;
9916 }
9917 }
9918
9919 p_info->patch->id = handle;
9920 p_info->patch->num_sources = num_sources;
9921 p_info->patch->num_sinks = num_sinks;
9922
9923 for (int i = 0; i < num_sources; i++)
9924 p_info->patch->sources[i] = sources[i];
9925 for (int i = 0; i < num_sinks; i++)
9926 p_info->patch->sinks[i] = sinks[i];
9927
9928 p_info->patch_type = patch_type;
9929 return 0;
9930}
9931
9932audio_patch_handle_t generate_patch_handle()
9933{
9934 static audio_patch_handle_t patch_handle = AUDIO_PATCH_HANDLE_NONE;
9935 if (++patch_handle < 0)
9936 patch_handle = AUDIO_PATCH_HANDLE_NONE + 1;
9937 return patch_handle;
9938}
9939
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309940int adev_create_audio_patch(struct audio_hw_device *dev,
9941 unsigned int num_sources,
9942 const struct audio_port_config *sources,
9943 unsigned int num_sinks,
9944 const struct audio_port_config *sinks,
9945 audio_patch_handle_t *handle)
9946{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009947 int ret = 0;
9948 struct audio_device *adev = (struct audio_device *)dev;
9949 struct audio_patch_info *p_info = NULL;
9950 patch_type_t patch_type = PATCH_NONE;
9951 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
9952 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
9953 struct audio_stream_info *s_info = NULL;
9954 struct audio_stream *stream = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009955 struct listnode devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009956 audio_devices_t device_type = AUDIO_DEVICE_NONE;
9957 bool new_patch = false;
9958 char addr[AUDIO_DEVICE_MAX_ADDRESS_LEN];
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309959
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009960 ALOGD("%s: enter: num sources %d, num_sinks %d, handle %d", __func__,
9961 num_sources, num_sinks, *handle);
9962
9963 if (num_sources == 0 || num_sources > AUDIO_PATCH_PORTS_MAX ||
9964 num_sinks == 0 || num_sinks > AUDIO_PATCH_PORTS_MAX) {
9965 ALOGE("%s: Invalid patch arguments", __func__);
9966 ret = -EINVAL;
9967 goto done;
9968 }
9969
9970 if (num_sources > 1) {
9971 ALOGE("%s: Multiple sources are not supported", __func__);
9972 ret = -EINVAL;
9973 goto done;
9974 }
9975
9976 if (sources == NULL || sinks == NULL) {
9977 ALOGE("%s: Invalid sources or sinks port config", __func__);
9978 ret = -EINVAL;
9979 goto done;
9980 }
9981
9982 ALOGV("%s: source role %d, source type %d", __func__,
9983 sources[0].type, sources[0].role);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009984 list_init(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009985
9986 // Populate source/sink information and fetch stream info
9987 switch (sources[0].type) {
9988 case AUDIO_PORT_TYPE_DEVICE: // Patch for audio capture or loopback
9989 device_type = sources[0].ext.device.type;
9990 strlcpy(&addr[0], &sources[0].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009991 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009992 if (sinks[0].type == AUDIO_PORT_TYPE_MIX) {
9993 patch_type = PATCH_CAPTURE;
9994 io_handle = sinks[0].ext.mix.handle;
9995 input_source = sinks[0].ext.mix.usecase.source;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009996 ALOGD("%s: Capture patch from device %x to mix %d",
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009997 __func__, device_type, io_handle);
9998 } else {
9999 // Device to device patch is not implemented.
10000 // This space will need changes if audio HAL
10001 // handles device to device patches in the future.
10002 patch_type = PATCH_DEVICE_LOOPBACK;
10003 }
10004 break;
10005 case AUDIO_PORT_TYPE_MIX: // Patch for audio playback
10006 io_handle = sources[0].ext.mix.handle;
10007 for (int i = 0; i < num_sinks; i++) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010008 device_type = sinks[i].ext.device.type;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010009 strlcpy(&addr[0], &sinks[i].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010010 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010011 }
10012 patch_type = PATCH_PLAYBACK;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010013 ALOGD("%s: Playback patch from mix handle %d to device %x",
10014 __func__, io_handle, get_device_types(&devices));
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010015 break;
10016 case AUDIO_PORT_TYPE_SESSION:
10017 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010018 ALOGE("%s: Unsupported source type %d", __func__, sources[0].type);
10019 ret = -EINVAL;
10020 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010021 }
10022
10023 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010024
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010025 // Generate patch info and update patch
10026 if (*handle == AUDIO_PATCH_HANDLE_NONE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010027 *handle = generate_patch_handle();
10028 p_info = (struct audio_patch_info *)
10029 calloc(1, sizeof(struct audio_patch_info));
10030 if (p_info == NULL) {
10031 ALOGE("%s: Failed to allocate memory", __func__);
10032 pthread_mutex_unlock(&adev->lock);
10033 ret = -ENOMEM;
10034 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010035 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010036 new_patch = true;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010037 } else {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010038 p_info = fetch_patch_info_l(adev, *handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010039 if (p_info == NULL) {
10040 ALOGE("%s: Unable to fetch patch for received patch handle %d",
10041 __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010042 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010043 ret = -EINVAL;
10044 goto done;
10045 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010046 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010047 update_patch(num_sources, sources, num_sinks, sinks,
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010048 *handle, p_info, patch_type, new_patch);
10049
10050 // Fetch stream info of associated mix for playback or capture patches
10051 if (p_info->patch_type == PATCH_PLAYBACK ||
10052 p_info->patch_type == PATCH_CAPTURE) {
10053 s_info = hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10054 if (s_info == NULL) {
10055 ALOGE("%s: Failed to obtain stream info", __func__);
10056 if (new_patch)
10057 free(p_info);
10058 pthread_mutex_unlock(&adev->lock);
10059 ret = -EINVAL;
10060 goto done;
10061 }
10062 ALOGV("%s: Fetched stream info with io_handle %d", __func__, io_handle);
10063 s_info->patch_handle = *handle;
10064 stream = s_info->stream;
10065 }
10066 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010067
10068 // Update routing for stream
10069 if (stream != NULL) {
10070 if (p_info->patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010071 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010072 else if (p_info->patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010073 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010074 if (ret < 0) {
10075 pthread_mutex_lock(&adev->lock);
10076 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10077 if (new_patch)
10078 free(p_info);
10079 pthread_mutex_unlock(&adev->lock);
10080 ALOGE("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10081 goto done;
10082 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010083 }
10084
10085 // Add new patch to patch map
10086 if (!ret && new_patch) {
10087 pthread_mutex_lock(&adev->lock);
10088 hashmapPut(adev->patch_map, (void *) (intptr_t) *handle, (void *) p_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010089 ALOGD("%s: Added a new patch with handle %d", __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010090 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010091 }
10092
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010093done:
10094 audio_extn_hw_loopback_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010095 num_sources,
10096 sources,
10097 num_sinks,
10098 sinks,
10099 handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010100 audio_extn_auto_hal_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010101 num_sources,
10102 sources,
10103 num_sinks,
10104 sinks,
10105 handle);
10106 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010107}
10108
10109int adev_release_audio_patch(struct audio_hw_device *dev,
10110 audio_patch_handle_t handle)
10111{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010112 struct audio_device *adev = (struct audio_device *) dev;
10113 int ret = 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010114 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010115 struct audio_stream *stream = NULL;
Derek Chenf939fb72018-11-13 13:34:41 -080010116
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010117 if (handle == AUDIO_PATCH_HANDLE_NONE) {
10118 ALOGE("%s: Invalid patch handle %d", __func__, handle);
10119 ret = -EINVAL;
10120 goto done;
10121 }
10122
10123 ALOGD("%s: Remove patch with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010124 pthread_mutex_lock(&adev->lock);
10125 struct audio_patch_info *p_info = fetch_patch_info_l(adev, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010126 if (p_info == NULL) {
10127 ALOGE("%s: Patch info not found with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010128 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010129 ret = -EINVAL;
10130 goto done;
10131 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010132 struct audio_patch *patch = p_info->patch;
10133 if (patch == NULL) {
10134 ALOGE("%s: Patch not found for handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010135 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010136 ret = -EINVAL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010137 goto done;
10138 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010139 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10140 switch (patch->sources[0].type) {
10141 case AUDIO_PORT_TYPE_MIX:
10142 io_handle = patch->sources[0].ext.mix.handle;
10143 break;
10144 case AUDIO_PORT_TYPE_DEVICE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010145 if (p_info->patch_type == PATCH_CAPTURE)
10146 io_handle = patch->sinks[0].ext.mix.handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010147 break;
10148 case AUDIO_PORT_TYPE_SESSION:
10149 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010150 pthread_mutex_unlock(&adev->lock);
10151 ret = -EINVAL;
10152 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010153 }
10154
10155 // Remove patch and reset patch handle in stream info
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010156 patch_type_t patch_type = p_info->patch_type;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010157 patch_map_remove_l(adev, handle);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010158 if (patch_type == PATCH_PLAYBACK ||
10159 patch_type == PATCH_CAPTURE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010160 struct audio_stream_info *s_info =
10161 hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10162 if (s_info == NULL) {
10163 ALOGE("%s: stream for io_handle %d is not available", __func__, io_handle);
10164 pthread_mutex_unlock(&adev->lock);
10165 goto done;
10166 }
10167 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10168 stream = s_info->stream;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010169 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010170 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010171
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010172 if (stream != NULL) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010173 struct listnode devices;
10174 list_init(&devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010175 if (patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010176 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010177 else if (patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010178 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010179 }
10180
10181 if (ret < 0)
10182 ALOGW("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10183
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010184done:
10185 audio_extn_hw_loopback_release_audio_patch(dev, handle);
10186 audio_extn_auto_hal_release_audio_patch(dev, handle);
10187
10188 ALOGV("%s: Successfully released patch %d", __func__, handle);
Derek Chenf939fb72018-11-13 13:34:41 -080010189 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010190}
10191
10192int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
10193{
Derek Chenf13dd492018-11-13 14:53:51 -080010194 int ret = 0;
10195
10196 ret = audio_extn_hw_loopback_get_audio_port(dev, config);
10197 ret |= audio_extn_auto_hal_get_audio_port(dev, config);
10198 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010199}
10200
10201int adev_set_audio_port_config(struct audio_hw_device *dev,
10202 const struct audio_port_config *config)
10203{
Derek Chenf13dd492018-11-13 14:53:51 -080010204 int ret = 0;
10205
10206 ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
10207 ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
10208 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010209}
10210
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -070010211static int adev_dump(const audio_hw_device_t *device __unused,
10212 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010213{
10214 return 0;
10215}
10216
10217static int adev_close(hw_device_t *device)
10218{
Aalique Grahame22e49102018-12-18 14:23:57 -080010219 size_t i;
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010220 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -070010221
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010222 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -070010223 return 0;
10224
10225 pthread_mutex_lock(&adev_init_lock);
10226
10227 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +053010228 if (audio_extn_spkr_prot_is_enabled())
10229 audio_extn_spkr_prot_deinit();
Jaideep Sharmaa2b49672019-09-10 20:37:03 +053010230 audio_extn_battery_properties_listener_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010231 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010232 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -080010233 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010234 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -080010235 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010236 audio_extn_utils_release_streams_cfg_lists(
10237 &adev->streams_output_cfg_list,
10238 &adev->streams_input_cfg_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010239 if (audio_extn_qap_is_enabled())
10240 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010241 if (audio_extn_qaf_is_enabled())
10242 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -070010243 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +080010244 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -070010245 free(adev->snd_dev_ref_cnt);
10246 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010247 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
10248 pcm_params_free(adev->use_case_table[i]);
10249 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010250 if (adev->adm_deinit)
10251 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010252 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010253 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010254 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010255 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010256 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010257 if (adev->device_cfg_params) {
10258 free(adev->device_cfg_params);
10259 adev->device_cfg_params = NULL;
10260 }
Derek Chend2530072014-11-24 12:39:14 -080010261 if(adev->ext_hw_plugin)
10262 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -080010263 audio_extn_auto_hal_deinit();
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010264 free_map(adev->patch_map);
10265 free_map(adev->io_streams_map);
Kiran Kandi910e1862013-10-29 13:29:42 -070010266 free(device);
10267 adev = NULL;
10268 }
10269 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +053010270 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010271 return 0;
10272}
10273
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010274/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
10275 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
10276 * just that it _might_ work.
10277 */
10278static int period_size_is_plausible_for_low_latency(int period_size)
10279{
10280 switch (period_size) {
10281 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -070010282 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010283 case 240:
10284 case 320:
10285 case 480:
10286 return 1;
10287 default:
10288 return 0;
10289 }
10290}
10291
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010292static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
10293{
10294 bool is_snd_card_status = false;
10295 bool is_ext_device_status = false;
10296 char value[32];
10297 int card = -1;
10298 card_status_t status;
10299
10300 if (cookie != adev || !parms)
10301 return;
10302
10303 if (!parse_snd_card_status(parms, &card, &status)) {
10304 is_snd_card_status = true;
10305 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
10306 is_ext_device_status = true;
10307 } else {
10308 // not a valid event
10309 return;
10310 }
10311
10312 pthread_mutex_lock(&adev->lock);
10313 if (card == adev->snd_card || is_ext_device_status) {
10314 if (is_snd_card_status && adev->card_status != status) {
10315 adev->card_status = status;
10316 platform_snd_card_update(adev->platform, status);
10317 audio_extn_fm_set_parameters(adev, parms);
Derek Chend6f371d2019-03-01 13:45:58 -080010318 audio_extn_auto_hal_set_parameters(adev, parms);
Zhou Song4f43e352019-07-02 00:32:23 +080010319 if (status == CARD_STATUS_OFFLINE)
10320 audio_extn_sco_reset_configuration();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010321 } else if (is_ext_device_status) {
10322 platform_set_parameters(adev->platform, parms);
10323 }
10324 }
10325 pthread_mutex_unlock(&adev->lock);
10326 return;
10327}
10328
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010329/* out and adev lock held */
10330static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
10331{
10332 struct audio_usecase *uc_info;
10333 float left_p;
10334 float right_p;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010335 struct listnode devices;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010336
10337 uc_info = get_usecase_from_list(adev, out->usecase);
10338 if (uc_info == NULL) {
10339 ALOGE("%s: Could not find the usecase (%d) in the list",
10340 __func__, out->usecase);
10341 return -EINVAL;
10342 }
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010343 list_init(&devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010344
10345 ALOGD("%s: enter: usecase(%d: %s)", __func__,
10346 out->usecase, use_case_table[out->usecase]);
10347
10348 if (restore) {
10349 // restore A2DP device for active usecases and unmute if required
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010350 if (is_a2dp_out_device_type(&out->device_list)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010351 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
Zhou Songe5225132019-09-26 15:33:36 +080010352 if (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)
10353 select_devices(adev, uc_info->id);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010354 pthread_mutex_lock(&out->compr_mute_lock);
10355 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Manisha Agarwalc2188fb2019-05-27 10:00:29 +053010356 (out->a2dp_compress_mute) && (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010357 out->a2dp_compress_mute = false;
10358 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
10359 }
10360 pthread_mutex_unlock(&out->compr_mute_lock);
10361 }
10362 } else {
Zhou Songc576a452019-09-09 14:17:40 +080010363 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
10364 // mute compress stream if suspended
10365 pthread_mutex_lock(&out->compr_mute_lock);
10366 if (!out->a2dp_compress_mute && !out->standby) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010367 ALOGD("%s: selecting speaker and muting stream", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010368 assign_devices(&devices, &out->device_list);
10369 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010370 left_p = out->volume_l;
10371 right_p = out->volume_r;
10372 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10373 compress_pause(out->compr);
10374 out_set_compr_volume(&out->stream, (float)0, (float)0);
10375 out->a2dp_compress_mute = true;
10376 select_devices(adev, out->usecase);
10377 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10378 compress_resume(out->compr);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010379 assign_devices(&out->device_list, &devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010380 out->volume_l = left_p;
10381 out->volume_r = right_p;
10382 }
Zhou Songc576a452019-09-09 14:17:40 +080010383 pthread_mutex_unlock(&out->compr_mute_lock);
10384 } else {
10385 // tear down a2dp path for non offloaded streams
10386 if (audio_extn_a2dp_source_is_suspended())
10387 out_standby_l(&out->stream.common);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010388 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010389 }
10390 ALOGV("%s: exit", __func__);
10391 return 0;
10392}
10393
10394int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
10395{
10396 int ret = 0;
10397
10398 lock_output_stream(out);
10399 pthread_mutex_lock(&adev->lock);
10400
10401 ret = check_a2dp_restore_l(adev, out, restore);
10402
10403 pthread_mutex_unlock(&adev->lock);
10404 pthread_mutex_unlock(&out->lock);
10405 return ret;
10406}
10407
Haynes Mathew George01156f92018-04-13 15:29:54 -070010408void adev_on_battery_status_changed(bool charging)
10409{
10410 pthread_mutex_lock(&adev->lock);
10411 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
10412 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +080010413 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -070010414 pthread_mutex_unlock(&adev->lock);
10415}
10416
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010417static int adev_open(const hw_module_t *module, const char *name,
10418 hw_device_t **device)
10419{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010420 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -080010421 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010422 char mixer_ctl_name[128] = {0};
10423 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010424
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080010425 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010426 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
10427
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010428 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -070010429 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010430 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -070010431 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010432 ALOGD("%s: returning existing instance of adev", __func__);
10433 ALOGD("%s: exit", __func__);
10434 pthread_mutex_unlock(&adev_init_lock);
10435 return 0;
10436 }
10437
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010438 adev = calloc(1, sizeof(struct audio_device));
10439
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -070010440 if (!adev) {
10441 pthread_mutex_unlock(&adev_init_lock);
10442 return -ENOMEM;
10443 }
10444
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -070010445 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
10446
Weiyin Jiange6ce6312019-01-28 18:28:22 +080010447 // register audio ext hidl at the earliest
10448 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053010449#ifdef DYNAMIC_LOG_ENABLED
10450 register_for_dynamic_logging("hal");
10451#endif
10452
Derek Chenf939fb72018-11-13 13:34:41 -080010453 /* default audio HAL major version */
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010454 uint32_t maj_version = 3;
Derek Chenf939fb72018-11-13 13:34:41 -080010455 if(property_get("vendor.audio.hal.maj.version", value, NULL))
10456 maj_version = atoi(value);
10457
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010458 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -080010459 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010460 adev->device.common.module = (struct hw_module_t *)module;
10461 adev->device.common.close = adev_close;
10462
10463 adev->device.init_check = adev_init_check;
10464 adev->device.set_voice_volume = adev_set_voice_volume;
10465 adev->device.set_master_volume = adev_set_master_volume;
10466 adev->device.get_master_volume = adev_get_master_volume;
10467 adev->device.set_master_mute = adev_set_master_mute;
10468 adev->device.get_master_mute = adev_get_master_mute;
10469 adev->device.set_mode = adev_set_mode;
10470 adev->device.set_mic_mute = adev_set_mic_mute;
10471 adev->device.get_mic_mute = adev_get_mic_mute;
10472 adev->device.set_parameters = adev_set_parameters;
10473 adev->device.get_parameters = adev_get_parameters;
10474 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
10475 adev->device.open_output_stream = adev_open_output_stream;
10476 adev->device.close_output_stream = adev_close_output_stream;
10477 adev->device.open_input_stream = adev_open_input_stream;
10478 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010479 adev->device.create_audio_patch = adev_create_audio_patch;
10480 adev->device.release_audio_patch = adev_release_audio_patch;
10481 adev->device.get_audio_port = adev_get_audio_port;
10482 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010483 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +053010484 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010485
10486 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010487 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -080010488 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010489 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010490 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -080010491 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -070010492 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +053010493 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -070010494 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -070010495 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -070010496 /* Init audio and voice feature */
10497 audio_extn_feature_init();
10498 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070010499 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -080010500 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -080010501 list_init(&adev->active_inputs_list);
10502 list_init(&adev->active_outputs_list);
Rahul Sharma99770982019-03-06 17:05:26 +053010503 list_init(&adev->audio_patch_record_list);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010504 adev->io_streams_map = hashmapCreate(AUDIO_IO_PORTS_MAX, audio_extn_utils_hash_fn,
10505 audio_extn_utils_hash_eq);
10506 if (!adev->io_streams_map) {
10507 ALOGE("%s: Could not create io streams map", __func__);
10508 ret = -ENOMEM;
10509 goto adev_open_err;
10510 }
10511 adev->patch_map = hashmapCreate(AUDIO_PATCH_PORTS_MAX, audio_extn_utils_hash_fn,
10512 audio_extn_utils_hash_eq);
10513 if (!adev->patch_map) {
10514 ALOGE("%s: Could not create audio patch map", __func__);
10515 ret = -ENOMEM;
10516 goto adev_open_err;
10517 }
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -080010518 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -070010519 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +053010520 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +053010521 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +053010522 adev->perf_lock_opts[0] = 0x101;
10523 adev->perf_lock_opts[1] = 0x20E;
10524 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010525 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -070010526 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010527 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010528 adev->adm_routing_changed = false;
Revathi Uddarajub26e3932020-06-10 14:51:02 +053010529 adev->a2dp_started = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +053010530
Zhou Song68ebc352019-12-05 17:11:15 +080010531 audio_extn_perf_lock_init();
10532
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010533 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -070010534 adev->platform = platform_init(adev);
10535 if (!adev->platform) {
Eric Laurentb23d5282013-05-14 15:27:20 -070010536 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010537 ret = -EINVAL;
10538 goto adev_open_err;
Eric Laurentb23d5282013-05-14 15:27:20 -070010539 }
Eric Laurentc4aef752013-09-12 17:45:53 -070010540
Aalique Grahame22e49102018-12-18 14:23:57 -080010541 adev->extspk = audio_extn_extspk_init(adev);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010542 if (audio_extn_qap_is_enabled()) {
10543 ret = audio_extn_qap_init(adev);
10544 if (ret < 0) {
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010545 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010546 goto adev_open_err;
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010547 }
10548 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
10549 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
10550 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010551
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010552 if (audio_extn_qaf_is_enabled()) {
10553 ret = audio_extn_qaf_init(adev);
10554 if (ret < 0) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010555 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010556 goto adev_open_err;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010557 }
10558
10559 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
10560 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
10561 }
10562
Derek Chenae7b0342019-02-08 15:17:04 -080010563 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -080010564 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
10565
Eric Laurentc4aef752013-09-12 17:45:53 -070010566 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
10567 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
10568 if (adev->visualizer_lib == NULL) {
10569 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
10570 } else {
10571 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
10572 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010573 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010574 "visualizer_hal_start_output");
10575 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010576 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010577 "visualizer_hal_stop_output");
10578 }
10579 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +053010580 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010581 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -080010582 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +080010583 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010584 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010585 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -070010586
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010587 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
10588 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
10589 if (adev->offload_effects_lib == NULL) {
10590 ALOGE("%s: DLOPEN failed for %s", __func__,
10591 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10592 } else {
10593 ALOGV("%s: DLOPEN successful for %s", __func__,
10594 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10595 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +053010596 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010597 "offload_effects_bundle_hal_start_output");
10598 adev->offload_effects_stop_output =
10599 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
10600 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080010601 adev->offload_effects_set_hpx_state =
10602 (int (*)(bool))dlsym(adev->offload_effects_lib,
10603 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +053010604 adev->offload_effects_get_parameters =
10605 (void (*)(struct str_parms *, struct str_parms *))
10606 dlsym(adev->offload_effects_lib,
10607 "offload_effects_bundle_get_parameters");
10608 adev->offload_effects_set_parameters =
10609 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
10610 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010611 }
10612 }
10613
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010614 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
10615 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
10616 if (adev->adm_lib == NULL) {
10617 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
10618 } else {
10619 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
10620 adev->adm_init = (adm_init_t)
10621 dlsym(adev->adm_lib, "adm_init");
10622 adev->adm_deinit = (adm_deinit_t)
10623 dlsym(adev->adm_lib, "adm_deinit");
10624 adev->adm_register_input_stream = (adm_register_input_stream_t)
10625 dlsym(adev->adm_lib, "adm_register_input_stream");
10626 adev->adm_register_output_stream = (adm_register_output_stream_t)
10627 dlsym(adev->adm_lib, "adm_register_output_stream");
10628 adev->adm_deregister_stream = (adm_deregister_stream_t)
10629 dlsym(adev->adm_lib, "adm_deregister_stream");
10630 adev->adm_request_focus = (adm_request_focus_t)
10631 dlsym(adev->adm_lib, "adm_request_focus");
10632 adev->adm_abandon_focus = (adm_abandon_focus_t)
10633 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010634 adev->adm_set_config = (adm_set_config_t)
10635 dlsym(adev->adm_lib, "adm_set_config");
10636 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
10637 dlsym(adev->adm_lib, "adm_request_focus_v2");
10638 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
10639 dlsym(adev->adm_lib, "adm_is_noirq_avail");
10640 adev->adm_on_routing_change = (adm_on_routing_change_t)
10641 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010642 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
10643 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010644 }
10645 }
10646
Aalique Grahame22e49102018-12-18 14:23:57 -080010647 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010648 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +080010649 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -080010650 //initialize this to false for now,
10651 //this will be set to true through set param
10652 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010653
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -070010654 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010655 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -080010656
10657 if (k_enable_extended_precision)
10658 adev_verify_devices(adev);
10659
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010660 adev->dsp_bit_width_enforce_mode =
10661 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010662
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010663 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
10664 &adev->streams_output_cfg_list,
10665 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070010666
Kiran Kandi910e1862013-10-29 13:29:42 -070010667 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010668
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010669 int trial;
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010670 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010671 trial = atoi(value);
10672 if (period_size_is_plausible_for_low_latency(trial)) {
10673 pcm_config_low_latency.period_size = trial;
10674 pcm_config_low_latency.start_threshold = trial / 4;
10675 pcm_config_low_latency.avail_min = trial / 4;
10676 configured_low_latency_capture_period_size = trial;
10677 }
10678 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010679 if ((property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) ||
10680 (property_get("audio_hal.in_period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010681 trial = atoi(value);
10682 if (period_size_is_plausible_for_low_latency(trial)) {
10683 configured_low_latency_capture_period_size = trial;
10684 }
10685 }
10686
Vignesh Kulothungan7d374312018-02-21 17:12:00 -080010687 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
10688
Eric Laurent4b084132018-10-19 17:33:43 -070010689 adev->camera_orientation = CAMERA_DEFAULT;
10690
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010691 if (property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010692 af_period_multiplier = atoi(value);
10693 if (af_period_multiplier < 0)
10694 af_period_multiplier = 2;
10695 else if (af_period_multiplier > 4)
10696 af_period_multiplier = 4;
10697
10698 ALOGV("new period_multiplier = %d", af_period_multiplier);
10699 }
10700
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010701 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010702
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -070010703 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Zhou Song62ea0282020-03-22 19:53:01 +080010704 adev->ha_proxy_enable = property_get_bool("persist.vendor.audio.ha_proxy.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010705 pthread_mutex_unlock(&adev_init_lock);
10706
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010707 if (adev->adm_init)
10708 adev->adm_data = adev->adm_init();
10709
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010710 qahwi_init(*device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010711 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010712
10713 audio_extn_snd_mon_init();
10714 pthread_mutex_lock(&adev->lock);
10715 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
10716 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -070010717 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
10718 /*
10719 * if the battery state callback happens before charging can be queried,
10720 * it will be guarded with the adev->lock held in the cb function and so
10721 * the callback value will reflect the latest state
10722 */
10723 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010724 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +080010725 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -070010726 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +080010727 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010728 /* Allocate memory for Device config params */
10729 adev->device_cfg_params = (struct audio_device_config_param*)
10730 calloc(platform_get_max_codec_backend(),
10731 sizeof(struct audio_device_config_param));
10732 if (adev->device_cfg_params == NULL)
10733 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010734
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010735 /*
10736 * Check if new PSPD matrix mixer control is supported. If not
10737 * supported, then set flag so that old mixer ctrl is sent while
10738 * sending pspd coefficients on older kernel version. Query mixer
10739 * control for default pcm id and channel value one.
10740 */
10741 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
10742 "AudStr %d ChMixer Weight Ch %d", 0, 1);
10743
10744 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
10745 if (!ctl) {
10746 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
10747 __func__, mixer_ctl_name);
10748 adev->use_old_pspd_mix_ctrl = true;
10749 }
10750
Eric Laurent994a6932013-07-17 11:51:42 -070010751 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010752 return 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010753
10754adev_open_err:
10755 free_map(adev->patch_map);
10756 free_map(adev->io_streams_map);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010757 free(adev->snd_dev_ref_cnt);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010758 pthread_mutex_destroy(&adev->lock);
10759 free(adev);
10760 adev = NULL;
10761 *device = NULL;
10762 pthread_mutex_unlock(&adev_init_lock);
10763 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010764}
10765
10766static struct hw_module_methods_t hal_module_methods = {
10767 .open = adev_open,
10768};
10769
10770struct audio_module HAL_MODULE_INFO_SYM = {
10771 .common = {
10772 .tag = HARDWARE_MODULE_TAG,
10773 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
10774 .hal_api_version = HARDWARE_HAL_API_VERSION,
10775 .id = AUDIO_HARDWARE_MODULE_ID,
10776 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -080010777 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010778 .methods = &hal_module_methods,
10779 },
10780};