blob: f441d3b2eaa5920b46d66967f69c40f7edca56a1 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07002 * Copyright (c) 2013-2020, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070039#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041/*#define VERY_VERY_VERBOSE_LOGGING*/
42#ifdef VERY_VERY_VERBOSE_LOGGING
43#define ALOGVV ALOGV
44#else
45#define ALOGVV(a...) do { } while(0)
46#endif
George Gao3018ede2019-10-23 13:23:00 -070047#include <limits.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080048#include <errno.h>
49#include <pthread.h>
50#include <stdint.h>
51#include <sys/time.h>
52#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070054#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include <sys/resource.h>
56#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
Aalique Grahame22e49102018-12-18 14:23:57 -080058#include <log/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070059#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080060#include <cutils/str_parms.h>
61#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062#include <cutils/atomic.h>
63#include <cutils/sched_policy.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070064#include <hardware/audio_effect.h>
Haynes Mathew George484e8d22017-07-31 18:55:17 -070065#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070066#include <system/thread_defs.h>
Haynes Mathew George16081042017-05-31 17:16:49 -070067#include <tinyalsa/asoundlib.h>
Andy Hunga1f48fa2019-07-01 18:14:53 -070068#include <utils/Timers.h> // systemTime
Eric Laurentb23d5282013-05-14 15:27:20 -070069#include <audio_effects/effect_aec.h>
70#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053071#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080072#include "audio_hw.h"
Wei Wangf7ca6c92017-11-21 14:51:20 -080073#include "audio_perf.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070074#include "platform_api.h"
75#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070076#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080077#include "voice_extn.h"
Ashish Jaind5694242017-09-05 20:09:06 +053078#include "ip_hdlr_intf.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080079
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070080#include "sound/compress_params.h"
Xiaojun Sang782e5b12020-06-29 21:13:06 +080081
82#ifdef AUDIO_GKI_ENABLED
83#include "sound/audio_compressed_formats.h"
84#endif
85
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080086#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080087
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053088#ifdef DYNAMIC_LOG_ENABLED
89#include <log_xml_parser.h>
90#define LOG_MASK HAL_MOD_FILE_AUDIO_HW
91#include <log_utils.h>
92#endif
93
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070094#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053095/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
96#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070097#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Vikram Panduranga93f080e2017-06-07 18:16:14 -070098#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Arun Mirpuri5d170872019-03-26 13:21:31 -070099#define MMAP_PLAYBACK_VOLUME_MAX 0x2000
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530100#define PCM_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530101#define DSD_VOLUME_MIN_DB (-110)
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700102#define INVALID_OUT_VOLUME -1
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700103#define AUDIO_IO_PORTS_MAX 32
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700104
Aalique Grahame22e49102018-12-18 14:23:57 -0800105#define RECORD_GAIN_MIN 0.0f
106#define RECORD_GAIN_MAX 1.0f
107#define RECORD_VOLUME_CTL_MAX 0x2000
108
109/* treat as unsigned Q1.13 */
110#define APP_TYPE_GAIN_DEFAULT 0x2000
111
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700112#define PROXY_OPEN_RETRY_COUNT 100
113#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800114
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800115#define GET_USECASE_AUDIO_PLAYBACK_PRIMARY(db) \
116 (db)? USECASE_AUDIO_PLAYBACK_DEEP_BUFFER : \
117 USECASE_AUDIO_PLAYBACK_LOW_LATENCY
118#define GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(db) \
119 (db)? pcm_config_deep_buffer : pcm_config_low_latency
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800120
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700121#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700122#define DEFAULT_VOIP_BUF_DURATION_MS 20
123#define DEFAULT_VOIP_BIT_DEPTH_BYTE sizeof(int16_t)
124#define DEFAULT_VOIP_SAMP_RATE 48000
125
126#define VOIP_IO_BUF_SIZE(SR, DURATION_MS, BIT_DEPTH) (SR)/1000 * DURATION_MS * BIT_DEPTH
127
128struct pcm_config default_pcm_config_voip_copp = {
129 .channels = 1,
130 .rate = DEFAULT_VOIP_SAMP_RATE, /* changed when the stream is opened */
131 .period_size = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
132 .period_count = 2,
133 .format = PCM_FORMAT_S16_LE,
kunleiz95b597a2017-10-23 17:07:33 +0800134 .avail_min = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
135 .stop_threshold = INT_MAX,
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700136};
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700137
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700138#define MIN_CHANNEL_COUNT 1
139#define DEFAULT_CHANNEL_COUNT 2
140#define MAX_HIFI_CHANNEL_COUNT 8
141
Aalique Grahame22e49102018-12-18 14:23:57 -0800142#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
143#define MAX_CHANNEL_COUNT 1
144#else
145#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
146#define XSTR(x) STR(x)
147#define STR(x) #x
148#endif
149
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700150static unsigned int configured_low_latency_capture_period_size =
151 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
152
Haynes Mathew George16081042017-05-31 17:16:49 -0700153#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
154#define MMAP_PERIOD_COUNT_MIN 32
155#define MMAP_PERIOD_COUNT_MAX 512
156#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
157
Aalique Grahame22e49102018-12-18 14:23:57 -0800158/* This constant enables extended precision handling.
159 * TODO The flag is off until more testing is done.
160 */
161static const bool k_enable_extended_precision = false;
Arun Mirpurie008ed22019-03-21 11:21:04 -0700162extern int AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Aalique Grahame22e49102018-12-18 14:23:57 -0800163
Eric Laurentb23d5282013-05-14 15:27:20 -0700164struct pcm_config pcm_config_deep_buffer = {
165 .channels = 2,
166 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
167 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
168 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
169 .format = PCM_FORMAT_S16_LE,
170 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
171 .stop_threshold = INT_MAX,
172 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
173};
174
175struct pcm_config pcm_config_low_latency = {
176 .channels = 2,
177 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
178 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
179 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
180 .format = PCM_FORMAT_S16_LE,
181 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
182 .stop_threshold = INT_MAX,
183 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
184};
185
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800186struct pcm_config pcm_config_haptics_audio = {
187 .channels = 1,
188 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
189 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
190 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
191 .format = PCM_FORMAT_S16_LE,
192 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
193 .stop_threshold = INT_MAX,
194 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
195};
196
197struct pcm_config pcm_config_haptics = {
198 .channels = 1,
199 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
200 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
201 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
202 .format = PCM_FORMAT_S16_LE,
203 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
204 .stop_threshold = INT_MAX,
205 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
206};
207
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700208static int af_period_multiplier = 4;
209struct pcm_config pcm_config_rt = {
210 .channels = 2,
211 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
212 .period_size = ULL_PERIOD_SIZE, //1 ms
213 .period_count = 512, //=> buffer size is 512ms
214 .format = PCM_FORMAT_S16_LE,
215 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
216 .stop_threshold = INT_MAX,
217 .silence_threshold = 0,
218 .silence_size = 0,
219 .avail_min = ULL_PERIOD_SIZE, //1 ms
220};
221
Eric Laurentb23d5282013-05-14 15:27:20 -0700222struct pcm_config pcm_config_hdmi_multi = {
223 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
224 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
225 .period_size = HDMI_MULTI_PERIOD_SIZE,
226 .period_count = HDMI_MULTI_PERIOD_COUNT,
227 .format = PCM_FORMAT_S16_LE,
228 .start_threshold = 0,
229 .stop_threshold = INT_MAX,
230 .avail_min = 0,
231};
232
Haynes Mathew George16081042017-05-31 17:16:49 -0700233struct pcm_config pcm_config_mmap_playback = {
234 .channels = 2,
235 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
236 .period_size = MMAP_PERIOD_SIZE,
237 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
238 .format = PCM_FORMAT_S16_LE,
239 .start_threshold = MMAP_PERIOD_SIZE*8,
240 .stop_threshold = INT32_MAX,
241 .silence_threshold = 0,
242 .silence_size = 0,
243 .avail_min = MMAP_PERIOD_SIZE, //1 ms
244};
245
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700246struct pcm_config pcm_config_hifi = {
247 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
248 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
249 .period_size = HIFI_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
250 .period_count = HIFI_BUFFER_OUTPUT_PERIOD_COUNT,
251 .format = PCM_FORMAT_S24_3LE,
252 .start_threshold = 0,
253 .stop_threshold = INT_MAX,
254 .avail_min = 0,
255};
256
Eric Laurentb23d5282013-05-14 15:27:20 -0700257struct pcm_config pcm_config_audio_capture = {
258 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700259 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
260 .format = PCM_FORMAT_S16_LE,
261};
262
Haynes Mathew George16081042017-05-31 17:16:49 -0700263struct pcm_config pcm_config_mmap_capture = {
264 .channels = 2,
265 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
266 .period_size = MMAP_PERIOD_SIZE,
267 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
268 .format = PCM_FORMAT_S16_LE,
269 .start_threshold = 0,
270 .stop_threshold = INT_MAX,
271 .silence_threshold = 0,
272 .silence_size = 0,
273 .avail_min = MMAP_PERIOD_SIZE, //1 ms
274};
275
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700276#define AFE_PROXY_CHANNEL_COUNT 2
277#define AFE_PROXY_SAMPLING_RATE 48000
278
279#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
280#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
281
282struct pcm_config pcm_config_afe_proxy_playback = {
283 .channels = AFE_PROXY_CHANNEL_COUNT,
284 .rate = AFE_PROXY_SAMPLING_RATE,
285 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
286 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
287 .format = PCM_FORMAT_S16_LE,
288 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
289 .stop_threshold = INT_MAX,
290 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
291};
292
293#define AFE_PROXY_RECORD_PERIOD_SIZE 768
294#define AFE_PROXY_RECORD_PERIOD_COUNT 4
295
Aalique Grahame22e49102018-12-18 14:23:57 -0800296struct pcm_config pcm_config_audio_capture_rt = {
297 .channels = 2,
298 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
299 .period_size = ULL_PERIOD_SIZE,
300 .period_count = 512,
301 .format = PCM_FORMAT_S16_LE,
302 .start_threshold = 0,
303 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
304 .silence_threshold = 0,
305 .silence_size = 0,
306 .avail_min = ULL_PERIOD_SIZE, //1 ms
307};
308
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700309struct pcm_config pcm_config_afe_proxy_record = {
310 .channels = AFE_PROXY_CHANNEL_COUNT,
311 .rate = AFE_PROXY_SAMPLING_RATE,
312 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
313 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
314 .format = PCM_FORMAT_S16_LE,
315 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
316 .stop_threshold = INT_MAX,
317 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
318};
319
Ashish Jainf1eaa582016-05-23 20:54:24 +0530320#define AUDIO_MAX_PCM_FORMATS 7
321
322const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
323 [AUDIO_FORMAT_DEFAULT] = 0,
324 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
325 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
326 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
327 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
328 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
329 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
330};
331
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800332const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700333 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
334 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800335 [USECASE_AUDIO_PLAYBACK_WITH_HAPTICS] = "audio-with-haptics-playback",
Meng Wang51d8c2a2020-04-27 15:23:21 +0800336 [USECASE_AUDIO_PLAYBACK_HAPTICS] = "haptics-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700337 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
338 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700339 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700340 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700341 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
342 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
343 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
344 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
345 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
346 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
347 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
348 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
Haynes Mathew George16081042017-05-31 17:16:49 -0700349 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
350 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700351 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Aalique Grahame22e49102018-12-18 14:23:57 -0800352 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
vivek mehta0ea887a2015-08-26 14:01:20 -0700353
Eric Laurentb23d5282013-05-14 15:27:20 -0700354 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700355 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530356 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
357 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
358 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Dhananjay Kumar376e38b2017-09-28 22:26:23 +0530359 [USECASE_AUDIO_RECORD_COMPRESS5] = "audio-record-compress5",
360 [USECASE_AUDIO_RECORD_COMPRESS6] = "audio-record-compress6",
Eric Laurentb23d5282013-05-14 15:27:20 -0700361 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700362 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700363 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700364 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700365
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800366 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800367 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Derek Chenf7092792017-05-23 12:23:53 -0400368 [USECASE_AUDIO_HFP_SCO_DOWNLINK] = "hfp-sco-downlink",
369 [USECASE_AUDIO_HFP_SCO_WB_DOWNLINK] = "hfp-sco-wb-downlink",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700370
Derek Chenf7092792017-05-23 12:23:53 -0400371 [USECASE_VOICE_CALL] = "voice-call",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700372 [USECASE_VOICE2_CALL] = "voice2-call",
373 [USECASE_VOLTE_CALL] = "volte-call",
374 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800375 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800376 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
377 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800378 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700379 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
380 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
381 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800382 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
383 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
384 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
385
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700386 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
387 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700388 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
389 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700390
391 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
392 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Zhou Song62ea0282020-03-22 19:53:01 +0800393 [USECASE_AUDIO_RECORD_AFE_PROXY2] = "afe-proxy-record2",
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +0530394 [USECASE_AUDIO_PLAYBACK_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700395
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530396 /* Transcode loopback cases */
Surendar Karka93cd25a2018-08-28 14:21:37 +0530397 [USECASE_AUDIO_TRANSCODE_LOOPBACK_RX] = "audio-transcode-loopback-rx",
398 [USECASE_AUDIO_TRANSCODE_LOOPBACK_TX] = "audio-transcode-loopback-tx",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700399
400 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
401 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Revathi Uddarajud9f23d92020-07-27 10:55:06 +0530402 [USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY] = "audio-record-voip-low-latency",
Varun Balaraje49253e2017-07-06 19:48:56 +0530403 /* For Interactive Audio Streams */
404 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
405 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
406 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
407 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
408 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
409 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
410 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
411 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700412
Aniket Kumar Lata7fd86e12018-02-20 19:26:10 -0800413 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture",
414
Derek Chenf6318be2017-06-12 17:16:24 -0400415 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
416
417 [USECASE_AUDIO_PLAYBACK_MEDIA] = "media-playback",
418 [USECASE_AUDIO_PLAYBACK_SYS_NOTIFICATION] = "sys-notification-playback",
419 [USECASE_AUDIO_PLAYBACK_NAV_GUIDANCE] = "nav-guidance-playback",
420 [USECASE_AUDIO_PLAYBACK_PHONE] = "phone-playback",
Derek Chen1bcdc6b2020-02-06 22:44:53 -0800421 [USECASE_AUDIO_PLAYBACK_FRONT_PASSENGER] = "front-passenger-playback",
Derek Chendf05eea2019-08-01 13:57:49 -0700422 [USECASE_AUDIO_PLAYBACK_REAR_SEAT] = "rear-seat-playback",
Rahul Sharma99770982019-03-06 17:05:26 +0530423 [USECASE_AUDIO_FM_TUNER_EXT] = "fm-tuner-ext",
Derek Chena30a5f42019-12-03 11:17:09 -0500424 [USECASE_ICC_CALL] = "icc-call",
Eric Laurentb23d5282013-05-14 15:27:20 -0700425};
426
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700427static const audio_usecase_t offload_usecases[] = {
428 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700429 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
430 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
431 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
432 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
433 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
434 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
435 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
436 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700437};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800438
Varun Balaraje49253e2017-07-06 19:48:56 +0530439static const audio_usecase_t interactive_usecases[] = {
440 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
441 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
442 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
443 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
444 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
445 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
446 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
447 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
448};
449
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800450#define STRING_TO_ENUM(string) { #string, string }
451
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800452struct string_to_enum {
453 const char *name;
454 uint32_t value;
455};
456
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700457static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800458 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800459 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
460 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
461 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700462 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800463 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
464 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800465 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700466 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
467 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
468 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
469 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
470 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
471 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
472 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
473 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
474 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
475 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
476 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800477};
478
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700479static const struct string_to_enum formats_name_to_enum_table[] = {
480 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
481 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
482 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700483 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
484 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
485 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700486 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800487 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
488 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700489 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800490};
491
492//list of all supported sample rates by HDMI specification.
493static const int out_hdmi_sample_rates[] = {
494 32000, 44100, 48000, 88200, 96000, 176400, 192000,
495};
496
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700497static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800498 STRING_TO_ENUM(32000),
499 STRING_TO_ENUM(44100),
500 STRING_TO_ENUM(48000),
501 STRING_TO_ENUM(88200),
502 STRING_TO_ENUM(96000),
503 STRING_TO_ENUM(176400),
504 STRING_TO_ENUM(192000),
Mingshu pange8aedf12019-10-25 15:38:27 +0800505 STRING_TO_ENUM(352800),
506 STRING_TO_ENUM(384000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700507};
508
Carter Hsu2e429db2019-05-14 18:50:52 +0800509struct in_effect_list {
510 struct listnode list;
511 effect_handle_t handle;
512};
513
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700514static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700515static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700516static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700517//cache last MBDRC cal step level
518static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700519
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530520static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Arun Mirpuri5d170872019-03-26 13:21:31 -0700521static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800522static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530523static int out_set_pcm_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530524
Derek Chen6f293672019-04-01 01:40:24 -0700525static void adev_snd_mon_cb(void *cookie, struct str_parms *parms);
526static void in_snd_mon_cb(void * stream, struct str_parms * parms);
527static void out_snd_mon_cb(void * stream, struct str_parms * parms);
528
Zhou Song331c8e52019-08-26 14:16:12 +0800529static int configure_btsco_sample_rate(snd_device_t snd_device);
530
Vatsal Buchac09ae062018-11-14 13:25:08 +0530531#ifdef AUDIO_FEATURE_ENABLED_GCOV
532extern void __gcov_flush();
533static void enable_gcov()
534{
535 __gcov_flush();
536}
537#else
538static void enable_gcov()
539{
540}
541#endif
542
justinweng20fb6d82019-02-21 18:49:00 -0700543static int in_set_microphone_direction(const struct audio_stream_in *stream,
544 audio_microphone_direction_t dir);
545static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom);
546
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700547static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
548 int flags __unused)
549{
550 int dir = 0;
551 switch (uc_id) {
552 case USECASE_AUDIO_RECORD_LOW_LATENCY:
Revathi Uddarajud9f23d92020-07-27 10:55:06 +0530553 case USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY:
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700554 dir = 1;
555 case USECASE_AUDIO_PLAYBACK_ULL:
556 break;
557 default:
558 return false;
559 }
560
561 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
562 PCM_PLAYBACK : PCM_CAPTURE);
563 if (adev->adm_is_noirq_avail)
564 return adev->adm_is_noirq_avail(adev->adm_data,
565 adev->snd_card, dev_id, dir);
566 return false;
567}
568
569static void register_out_stream(struct stream_out *out)
570{
571 struct audio_device *adev = out->dev;
572 if (is_offload_usecase(out->usecase) ||
573 !adev->adm_register_output_stream)
574 return;
575
576 // register stream first for backward compatibility
577 adev->adm_register_output_stream(adev->adm_data,
578 out->handle,
579 out->flags);
580
581 if (!adev->adm_set_config)
582 return;
583
584 if (out->realtime)
585 adev->adm_set_config(adev->adm_data,
586 out->handle,
587 out->pcm, &out->config);
588}
589
590static void register_in_stream(struct stream_in *in)
591{
592 struct audio_device *adev = in->dev;
593 if (!adev->adm_register_input_stream)
594 return;
595
596 adev->adm_register_input_stream(adev->adm_data,
597 in->capture_handle,
598 in->flags);
599
600 if (!adev->adm_set_config)
601 return;
602
603 if (in->realtime)
604 adev->adm_set_config(adev->adm_data,
605 in->capture_handle,
606 in->pcm,
607 &in->config);
608}
609
610static void request_out_focus(struct stream_out *out, long ns)
611{
612 struct audio_device *adev = out->dev;
613
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700614 if (adev->adm_request_focus_v2)
615 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
616 else if (adev->adm_request_focus)
617 adev->adm_request_focus(adev->adm_data, out->handle);
618}
619
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700620static int request_in_focus(struct stream_in *in, long ns)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700621{
622 struct audio_device *adev = in->dev;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700623 int ret = 0;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700624
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700625 if (adev->adm_request_focus_v2_1)
626 ret = adev->adm_request_focus_v2_1(adev->adm_data, in->capture_handle, ns);
627 else if (adev->adm_request_focus_v2)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700628 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
629 else if (adev->adm_request_focus)
630 adev->adm_request_focus(adev->adm_data, in->capture_handle);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700631
632 return ret;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700633}
634
635static void release_out_focus(struct stream_out *out)
636{
637 struct audio_device *adev = out->dev;
638
639 if (adev->adm_abandon_focus)
640 adev->adm_abandon_focus(adev->adm_data, out->handle);
641}
642
643static void release_in_focus(struct stream_in *in)
644{
645 struct audio_device *adev = in->dev;
646 if (adev->adm_abandon_focus)
647 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
648}
649
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530650static int parse_snd_card_status(struct str_parms *parms, int *card,
651 card_status_t *status)
652{
653 char value[32]={0};
654 char state[32]={0};
655
656 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
657 if (ret < 0)
658 return -1;
659
660 // sscanf should be okay as value is of max length 32.
661 // same as sizeof state.
662 if (sscanf(value, "%d,%s", card, state) < 2)
663 return -1;
664
665 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
666 CARD_STATUS_OFFLINE;
667 return 0;
668}
669
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700670static inline void adjust_frames_for_device_delay(struct stream_out *out,
671 uint32_t *dsp_frames) {
672 // Adjustment accounts for A2dp encoder latency with offload usecases
673 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -0800674 if (is_a2dp_out_device_type(&out->device_list)) {
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700675 unsigned long offset =
676 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
677 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
678 }
679}
680
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700681static inline bool free_entry(void *key __unused,
682 void *value, void *context __unused)
683{
684 free(value);
685 return true;
686}
687
688static inline void free_map(Hashmap *map)
689{
690 if (map) {
691 hashmapForEach(map, free_entry, (void *) NULL);
692 hashmapFree(map);
693 }
694}
695
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800696static inline void patch_map_remove_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700697 audio_patch_handle_t patch_handle)
698{
699 if (patch_handle == AUDIO_PATCH_HANDLE_NONE)
700 return;
701
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700702 struct audio_patch_info *p_info =
703 hashmapGet(adev->patch_map, (void *) (intptr_t) patch_handle);
704 if (p_info) {
705 ALOGV("%s: Remove patch %d", __func__, patch_handle);
706 hashmapRemove(adev->patch_map, (void *) (intptr_t) patch_handle);
707 free(p_info->patch);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700708 free(p_info);
709 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700710}
711
712static inline int io_streams_map_insert(struct audio_device *adev,
713 struct audio_stream *stream,
714 audio_io_handle_t handle,
715 audio_patch_handle_t patch_handle)
716{
717 struct audio_stream_info *s_info =
718 (struct audio_stream_info *) calloc(1, sizeof(struct audio_stream_info));
719
720 if (s_info == NULL) {
721 ALOGE("%s: Could not allocate stream info", __func__);
722 return -ENOMEM;
723 }
724 s_info->stream = stream;
725 s_info->patch_handle = patch_handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700726
727 pthread_mutex_lock(&adev->lock);
728 struct audio_stream_info *stream_info =
729 hashmapPut(adev->io_streams_map, (void *) (intptr_t) handle, (void *) s_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700730 if (stream_info != NULL)
731 free(stream_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800732 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Latad13758f2020-08-06 15:11:36 -0700733 ALOGV("%s: Added stream in io_streams_map with handle %d", __func__, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700734 return 0;
735}
736
737static inline void io_streams_map_remove(struct audio_device *adev,
738 audio_io_handle_t handle)
739{
740 pthread_mutex_lock(&adev->lock);
741 struct audio_stream_info *s_info =
742 hashmapRemove(adev->io_streams_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700743 if (s_info == NULL)
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800744 goto done;
Aniket Kumar Latad13758f2020-08-06 15:11:36 -0700745 ALOGV("%s: Removed stream with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800746 patch_map_remove_l(adev, s_info->patch_handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700747 free(s_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800748done:
749 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700750 return;
751}
752
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800753static struct audio_patch_info* fetch_patch_info_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700754 audio_patch_handle_t handle)
755{
756 struct audio_patch_info *p_info = NULL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700757 p_info = (struct audio_patch_info *)
758 hashmapGet(adev->patch_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700759 return p_info;
760}
761
vivek mehtaa76401a2015-04-24 14:12:15 -0700762__attribute__ ((visibility ("default")))
763bool audio_hw_send_gain_dep_calibration(int level) {
764 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700765 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700766
767 pthread_mutex_lock(&adev_init_lock);
768
769 if (adev != NULL && adev->platform != NULL) {
770 pthread_mutex_lock(&adev->lock);
771 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700772
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530773 // cache level info for any of the use case which
774 // was not started.
775 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700776
vivek mehtaa76401a2015-04-24 14:12:15 -0700777 pthread_mutex_unlock(&adev->lock);
778 } else {
779 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
780 }
781
782 pthread_mutex_unlock(&adev_init_lock);
783
784 return ret_val;
785}
786
Ashish Jain5106d362016-05-11 19:23:33 +0530787static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
788{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800789 bool gapless_enabled = false;
790 const char *mixer_ctl_name = "Compress Gapless Playback";
791 struct mixer_ctl *ctl;
792
793 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700794 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530795
796 /*Disable gapless if its AV playback*/
797 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800798
799 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
800 if (!ctl) {
801 ALOGE("%s: Could not get ctl for mixer cmd - %s",
802 __func__, mixer_ctl_name);
803 return -EINVAL;
804 }
805
806 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
807 ALOGE("%s: Could not set gapless mode %d",
808 __func__, gapless_enabled);
809 return -EINVAL;
810 }
811 return 0;
812}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700813
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700814__attribute__ ((visibility ("default")))
815int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
816 int table_size) {
817 int ret_val = 0;
818 ALOGV("%s: enter ... ", __func__);
819
820 pthread_mutex_lock(&adev_init_lock);
821 if (adev == NULL) {
822 ALOGW("%s: adev is NULL .... ", __func__);
823 goto done;
824 }
825
826 pthread_mutex_lock(&adev->lock);
827 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
828 pthread_mutex_unlock(&adev->lock);
829done:
830 pthread_mutex_unlock(&adev_init_lock);
831 ALOGV("%s: exit ... ", __func__);
832 return ret_val;
833}
834
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800835bool audio_hw_send_qdsp_parameter(int stream_type, float vol, bool active)
Aalique Grahame22e49102018-12-18 14:23:57 -0800836{
837 bool ret = false;
838 ALOGV("%s: enter ...", __func__);
839
840 pthread_mutex_lock(&adev_init_lock);
841
842 if (adev != NULL && adev->platform != NULL) {
843 pthread_mutex_lock(&adev->lock);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800844 ret = audio_extn_qdsp_set_state(adev, stream_type, vol, active);
Aalique Grahame22e49102018-12-18 14:23:57 -0800845 pthread_mutex_unlock(&adev->lock);
846 }
847
848 pthread_mutex_unlock(&adev_init_lock);
849
850 ALOGV("%s: exit with ret %d", __func__, ret);
851 return ret;
852}
Aalique Grahame22e49102018-12-18 14:23:57 -0800853
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700854static bool is_supported_format(audio_format_t format)
855{
Eric Laurent86e17132013-09-12 17:49:30 -0700856 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530857 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530858 format == AUDIO_FORMAT_AAC_LC ||
859 format == AUDIO_FORMAT_AAC_HE_V1 ||
860 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530861 format == AUDIO_FORMAT_AAC_ADTS_LC ||
862 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
863 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530864 format == AUDIO_FORMAT_AAC_LATM_LC ||
865 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
866 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530867 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
868 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530869 format == AUDIO_FORMAT_PCM_FLOAT ||
870 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700871 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530872 format == AUDIO_FORMAT_AC3 ||
873 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700874 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530875 format == AUDIO_FORMAT_DTS ||
876 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800877 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530878 format == AUDIO_FORMAT_ALAC ||
879 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530880 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530881 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800882 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530883 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700884 format == AUDIO_FORMAT_APTX ||
885 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800886 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700887
888 return false;
889}
890
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700891static inline bool is_mmap_usecase(audio_usecase_t uc_id)
892{
893 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
Zhou Song62ea0282020-03-22 19:53:01 +0800894 (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY2) ||
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700895 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
896}
897
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700898static inline bool is_valid_volume(float left, float right)
899{
900 return ((left >= 0.0f && right >= 0.0f) ? true : false);
901}
902
Avinash Vaish71a8b972014-07-24 15:36:33 +0530903static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
904 struct audio_usecase *uc_info)
905{
906 struct listnode *node;
907 struct audio_usecase *usecase;
908
909 if (uc_info == NULL)
910 return -EINVAL;
911
912 /* Re-route all voice usecases on the shared backend other than the
913 specified usecase to new snd devices */
914 list_for_each(node, &adev->usecase_list) {
915 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800916 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530917 enable_audio_route(adev, usecase);
918 }
919 return 0;
920}
921
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530922static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530923{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530924 ALOGV("%s", __func__);
925 audio_route_apply_and_update_path(adev->audio_route,
926 "asrc-mode");
927 adev->asrc_mode_enabled = true;
928}
929
930static void disable_asrc_mode(struct audio_device *adev)
931{
932 ALOGV("%s", __func__);
933 audio_route_reset_and_update_path(adev->audio_route,
934 "asrc-mode");
935 adev->asrc_mode_enabled = false;
936}
937
938/*
939 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
940 * 44.1 or Native DSD backends are enabled for any of current use case.
941 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
942 * - Disable current mix path use case(Headphone backend) and re-enable it with
943 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
944 * e.g. Naitve DSD or Headphone 44.1 -> + 48
945 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530946static void check_and_set_asrc_mode(struct audio_device *adev,
947 struct audio_usecase *uc_info,
948 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530949{
950 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530951 int i, num_new_devices = 0;
952 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
953 /*
954 *Split snd device for new combo use case
955 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
956 */
957 if (platform_split_snd_device(adev->platform,
958 snd_device,
959 &num_new_devices,
960 split_new_snd_devices) == 0) {
961 for (i = 0; i < num_new_devices; i++)
962 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
963 } else {
964 int new_backend_idx = platform_get_backend_index(snd_device);
965 if (((new_backend_idx == HEADPHONE_BACKEND) ||
966 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
967 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
968 !adev->asrc_mode_enabled) {
969 struct listnode *node = NULL;
970 struct audio_usecase *uc = NULL;
971 struct stream_out *curr_out = NULL;
972 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
973 int i, num_devices, ret = 0;
974 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530975
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530976 list_for_each(node, &adev->usecase_list) {
977 uc = node_to_item(node, struct audio_usecase, list);
978 curr_out = (struct stream_out*) uc->stream.out;
979 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
980 /*
981 *Split snd device for existing combo use case
982 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
983 */
984 ret = platform_split_snd_device(adev->platform,
985 uc->out_snd_device,
986 &num_devices,
987 split_snd_devices);
988 if (ret < 0 || num_devices == 0) {
989 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
990 split_snd_devices[0] = uc->out_snd_device;
991 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800992 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530993 for (i = 0; i < num_devices; i++) {
994 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
995 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
996 if((new_backend_idx == HEADPHONE_BACKEND) &&
997 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
998 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
Aniket Kumar Latad13758f2020-08-06 15:11:36 -0700999 ALOGV("%s:DSD or native stream detected enabling asrcmode in hardware",
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301000 __func__);
1001 enable_asrc_mode(adev);
1002 break;
1003 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
1004 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
1005 (usecase_backend_idx == HEADPHONE_BACKEND)) {
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07001006 ALOGV("%s: 48K stream detected, disabling and enabling it \
1007 with asrcmode in hardware", __func__);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301008 disable_audio_route(adev, uc);
1009 disable_snd_device(adev, uc->out_snd_device);
1010 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
1011 if (new_backend_idx == DSD_NATIVE_BACKEND)
1012 audio_route_apply_and_update_path(adev->audio_route,
1013 "hph-true-highquality-mode");
1014 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
1015 (curr_out->bit_width >= 24))
1016 audio_route_apply_and_update_path(adev->audio_route,
1017 "hph-highquality-mode");
1018 enable_asrc_mode(adev);
1019 enable_snd_device(adev, uc->out_snd_device);
1020 enable_audio_route(adev, uc);
1021 break;
1022 }
1023 }
1024 // reset split devices count
1025 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -08001026 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301027 if (adev->asrc_mode_enabled)
1028 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301029 }
1030 }
1031 }
1032}
1033
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001034static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
1035 struct audio_effect_config effect_config,
1036 unsigned int param_value)
1037{
1038 char mixer_ctl_name[] = "Audio Effect";
1039 struct mixer_ctl *ctl;
1040 long set_values[6];
Eric Laurent637e2d42018-11-15 12:24:31 -08001041 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001042
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001043 if (in == NULL) {
1044 ALOGE("%s: active input stream is NULL", __func__);
1045 return -EINVAL;
1046 }
1047
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001048 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1049 if (!ctl) {
1050 ALOGE("%s: Could not get mixer ctl - %s",
1051 __func__, mixer_ctl_name);
1052 return -EINVAL;
1053 }
1054
1055 set_values[0] = 1; //0:Rx 1:Tx
1056 set_values[1] = in->app_type_cfg.app_type;
1057 set_values[2] = (long)effect_config.module_id;
1058 set_values[3] = (long)effect_config.instance_id;
1059 set_values[4] = (long)effect_config.param_id;
1060 set_values[5] = param_value;
1061
1062 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
1063
1064 return 0;
1065
1066}
1067
1068static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
1069 int effect_type, unsigned int *param_value)
1070{
1071 int ret = 0;
1072 struct audio_effect_config other_effect_config;
1073 struct audio_usecase *usecase = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08001074 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001075
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001076 if (in == NULL) {
1077 ALOGE("%s: active input stream is NULL", __func__);
1078 return -EINVAL;
1079 }
1080
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001081 usecase = get_usecase_from_list(adev, in->usecase);
1082 if (!usecase)
1083 return -EINVAL;
1084
1085 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
1086 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
1087 if (ret < 0) {
1088 ALOGE("%s Failed to get effect params %d", __func__, ret);
1089 return ret;
1090 }
1091
1092 if (module_id == other_effect_config.module_id) {
1093 //Same module id for AEC/NS. Values need to be combined
1094 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
1095 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
1096 *param_value |= other_effect_config.param_value;
1097 }
1098 }
1099
1100 return ret;
1101}
1102
1103static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
Gangadhar Sb0210342019-02-22 17:39:41 +05301104{
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001105 struct audio_effect_config effect_config;
1106 struct audio_usecase *usecase = NULL;
1107 int ret = 0;
1108 unsigned int param_value = 0;
Eric Laurent637e2d42018-11-15 12:24:31 -08001109 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001110
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001111 if(!voice_extn_is_dynamic_ecns_enabled())
1112 return ENOSYS;
1113
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001114 if (!in) {
1115 ALOGE("%s: Invalid input stream", __func__);
1116 return -EINVAL;
1117 }
1118
1119 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
1120
1121 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +08001122 if (usecase == NULL) {
1123 ALOGE("%s: Could not find the usecase (%d) in the list",
1124 __func__, in->usecase);
1125 return -EINVAL;
1126 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001127
1128 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
1129 if (ret < 0) {
1130 ALOGE("%s Failed to get module id %d", __func__, ret);
1131 return ret;
1132 }
1133 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
1134 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
1135
1136 if(enable)
1137 param_value = effect_config.param_value;
1138
1139 /*Special handling for AEC & NS effects Param values need to be
1140 updated if module ids are same*/
1141
1142 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
1143 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
1144 if (ret < 0)
1145 return ret;
1146 }
1147
1148 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
1149
1150 return ret;
1151}
1152
1153static void check_and_enable_effect(struct audio_device *adev)
1154{
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001155 if(!voice_extn_is_dynamic_ecns_enabled())
1156 return;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001157
Eric Laurent637e2d42018-11-15 12:24:31 -08001158 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001159
Eric Laurent637e2d42018-11-15 12:24:31 -08001160 if (in != NULL && !in->standby) {
1161 if (in->enable_aec)
1162 enable_disable_effect(adev, EFFECT_AEC, true);
1163
1164 if (in->enable_ns &&
1165 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1166 enable_disable_effect(adev, EFFECT_NS, true);
1167 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001168 }
1169}
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001170
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001171int pcm_ioctl(struct pcm *pcm, int request, ...)
1172{
1173 va_list ap;
1174 void * arg;
1175 int pcm_fd = *(int*)pcm;
1176
1177 va_start(ap, request);
1178 arg = va_arg(ap, void *);
1179 va_end(ap);
1180
1181 return ioctl(pcm_fd, request, arg);
1182}
1183
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001184int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001185 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001186{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001187 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001188 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +05301189 struct stream_out *out = NULL;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301190 struct stream_in *in = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001191 struct listnode out_devices;
Soumya Managoli6993b762018-06-28 16:04:57 +05301192 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001193
1194 if (usecase == NULL)
1195 return -EINVAL;
1196
1197 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
1198
Carter Hsu2e429db2019-05-14 18:50:52 +08001199 if (usecase->type == PCM_CAPTURE) {
1200 struct stream_in *in = usecase->stream.in;
1201 struct audio_usecase *uinfo;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001202 snd_device = usecase->in_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001203
1204 if (in) {
1205 if (in->enable_aec || in->enable_ec_port) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001206 list_init(&out_devices);
1207 update_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "", true);
Carter Hsu2e429db2019-05-14 18:50:52 +08001208 struct listnode *node;
1209 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1210 USECASE_AUDIO_PLAYBACK_VOIP);
1211 if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001212 assign_devices(&out_devices,
1213 &voip_usecase->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001214 } else if (adev->primary_output &&
1215 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001216 assign_devices(&out_devices,
1217 &adev->primary_output->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001218 } else {
1219 list_for_each(node, &adev->usecase_list) {
1220 uinfo = node_to_item(node, struct audio_usecase, list);
1221 if (uinfo->type != PCM_CAPTURE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001222 assign_devices(&out_devices,
1223 &uinfo->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001224 break;
1225 }
1226 }
1227 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001228
1229 platform_set_echo_reference(adev, true, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001230 in->ec_opened = true;
1231 }
1232 }
Guodong Huf5e614d2019-06-24 18:42:03 +08001233 } else if ((usecase->type == TRANSCODE_LOOPBACK_TX) || ((usecase->type == PCM_HFP_CALL) &&
1234 ((usecase->id == USECASE_AUDIO_HFP_SCO) || (usecase->id == USECASE_AUDIO_HFP_SCO_WB)) &&
1235 (usecase->in_snd_device == SND_DEVICE_IN_VOICE_SPEAKER_MIC_HFP_MMSECNS))) {
Carter Hsu2e429db2019-05-14 18:50:52 +08001236 snd_device = usecase->in_snd_device;
1237 } else {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001238 snd_device = usecase->out_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001239 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001240
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001241#ifdef DS1_DOLBY_DAP_ENABLED
1242 audio_extn_dolby_set_dmid(adev);
1243 audio_extn_dolby_set_endpoint(adev);
1244#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001245 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001246 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301247 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001248 audio_extn_utils_send_app_type_cfg(adev, usecase);
Jasmine Cha4dcc1092019-03-04 18:12:47 +08001249 if (audio_extn_is_maxx_audio_enabled())
1250 audio_extn_ma_set_device(usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301251 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +05301252 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1253 out = usecase->stream.out;
1254 if (out && out->compr)
1255 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1256 }
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301257
1258 if (usecase->type == PCM_CAPTURE) {
1259 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001260 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301261 ALOGD("%s: set custom mtmx params v1", __func__);
1262 audio_extn_set_custom_mtmx_params_v1(adev, usecase, true);
1263 }
1264 } else {
1265 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
1266 }
Manish Dewangan58229382017-02-02 15:48:41 +05301267
Andy Hung756ecc12018-10-19 17:47:12 -07001268 // we shouldn't truncate mixer_path
1269 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1270 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1271 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001272 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001273 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301274 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1275 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1276 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1277 if (parms) {
1278 audio_extn_fm_set_parameters(adev, parms);
1279 str_parms_destroy(parms);
1280 }
1281 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001282 ALOGV("%s: exit", __func__);
1283 return 0;
1284}
1285
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001286int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001287 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001288{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001289 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001290 char mixer_path[MIXER_PATH_MAX_LENGTH];
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301291 struct stream_in *in = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001292
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301293 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001294 return -EINVAL;
1295
1296 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301297 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001298 snd_device = usecase->in_snd_device;
1299 else
1300 snd_device = usecase->out_snd_device;
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001301
1302 /* disable island and power mode on supported device for voice call */
1303 if (usecase->type == VOICE_CALL) {
1304 if (usecase->in_snd_device != SND_DEVICE_NONE) {
1305 if (platform_get_island_cfg_on_device(adev->platform, usecase->in_snd_device) &&
1306 platform_get_power_mode_on_device(adev->platform, usecase->in_snd_device)) {
1307 platform_set_island_cfg_on_device(adev, usecase->in_snd_device, false);
1308 platform_set_power_mode_on_device(adev, usecase->in_snd_device, false);
1309 platform_reset_island_power_status(adev->platform, usecase->in_snd_device);
Kunlei Zhang91c4b332020-07-20 17:53:14 +08001310 if (voice_is_lte_call_active(adev))
1311 platform_set_tx_lpi_mode(adev->platform, false);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001312 ALOGD("%s: disable island cfg and power mode in voice tx path",
1313 __func__);
1314 }
1315 }
1316 if (usecase->out_snd_device != SND_DEVICE_NONE) {
1317 if (platform_get_island_cfg_on_device(adev->platform, usecase->out_snd_device) &&
1318 platform_get_power_mode_on_device(adev->platform, usecase->out_snd_device)) {
1319 platform_set_island_cfg_on_device(adev, usecase->out_snd_device, false);
1320 platform_set_power_mode_on_device(adev, usecase->out_snd_device, false);
1321 platform_reset_island_power_status(adev->platform, usecase->out_snd_device);
1322 ALOGD("%s: disable island cfg and power mode in voice rx path",
1323 __func__);
1324 }
1325 }
1326 }
1327
Andy Hung756ecc12018-10-19 17:47:12 -07001328 // we shouldn't truncate mixer_path
1329 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1330 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1331 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001332 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001333 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001334 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Carter Hsu2e429db2019-05-14 18:50:52 +08001335 if (usecase->type == PCM_CAPTURE) {
1336 struct stream_in *in = usecase->stream.in;
1337 if (in && in->ec_opened) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001338 struct listnode out_devices;
1339 list_init(&out_devices);
1340 platform_set_echo_reference(in->dev, false, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001341 in->ec_opened = false;
1342 }
1343 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001344 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301345 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301346
1347 if (usecase->type == PCM_CAPTURE) {
1348 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001349 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301350 ALOGD("%s: reset custom mtmx params v1", __func__);
1351 audio_extn_set_custom_mtmx_params_v1(adev, usecase, false);
1352 }
1353 } else {
1354 audio_extn_set_custom_mtmx_params_v2(adev, usecase, false);
1355 }
1356
Weiyin Jiang298ffd92019-06-03 14:29:30 +08001357 if ((usecase->type == PCM_PLAYBACK) &&
1358 (usecase->stream.out != NULL))
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05301359 usecase->stream.out->pspd_coeff_sent = false;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301360
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001361 ALOGV("%s: exit", __func__);
1362 return 0;
1363}
1364
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001365int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001366 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001367{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301368 int i, num_devices = 0;
1369 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001370 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1371
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001372 if (snd_device < SND_DEVICE_MIN ||
1373 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001374 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001375 return -EINVAL;
1376 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001377
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001378 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001379 ALOGE("%s: Invalid sound device returned", __func__);
1380 return -EINVAL;
1381 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001382
1383 adev->snd_dev_ref_cnt[snd_device]++;
1384
1385 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1386 (platform_split_snd_device(adev->platform,
1387 snd_device,
1388 &num_devices,
1389 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001390 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001391 __func__, snd_device, device_name);
Aniket Kumar Lata990de552019-07-11 14:20:23 -07001392 /* Set backend config for A2DP to ensure slimbus configuration
1393 is correct if A2DP is already active and backend is closed
1394 and re-opened */
1395 if (snd_device == SND_DEVICE_OUT_BT_A2DP)
1396 audio_extn_a2dp_set_source_backend_cfg();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001397 return 0;
1398 }
1399
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001400 if (audio_extn_spkr_prot_is_enabled())
1401 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001402
Aalique Grahame22e49102018-12-18 14:23:57 -08001403 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1404
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001405 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1406 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001407 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1408 goto err;
1409 }
1410 audio_extn_dev_arbi_acquire(snd_device);
1411 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001412 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001413 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001414 goto err;
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001415 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001416 } else if (platform_split_snd_device(adev->platform,
1417 snd_device,
1418 &num_devices,
1419 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301420 for (i = 0; i < num_devices; i++) {
1421 enable_snd_device(adev, new_snd_devices[i]);
1422 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001423 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001424 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001425 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301426
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001427 /* enable island and power mode on supported device */
1428 if (platform_get_island_cfg_on_device(adev->platform, snd_device) &&
1429 platform_get_power_mode_on_device(adev->platform, snd_device)) {
1430 platform_set_island_cfg_on_device(adev, snd_device, true);
1431 platform_set_power_mode_on_device(adev, snd_device, true);
Kunlei Zhang91c4b332020-07-20 17:53:14 +08001432 if (voice_is_lte_call_active(adev) &&
1433 (snd_device >= SND_DEVICE_IN_BEGIN &&
1434 snd_device < SND_DEVICE_IN_END))
1435 platform_set_tx_lpi_mode(adev->platform, true);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001436 ALOGD("%s: enable island cfg and power mode on: %s",
1437 __func__, device_name);
1438 }
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301439
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301440 if (SND_DEVICE_OUT_BT_A2DP == snd_device) {
1441 if (audio_extn_a2dp_start_playback() < 0) {
1442 ALOGE(" fail to configure A2dp Source control path ");
1443 goto err;
1444 } else {
1445 adev->a2dp_started = true;
1446 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001447 }
Florian Pfister1a84f312018-07-19 14:38:18 +02001448
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001449 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1450 (audio_extn_a2dp_start_capture() < 0)) {
1451 ALOGE(" fail to configure A2dp Sink control path ");
1452 goto err;
1453 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301454
Mingshu Pang7be5b1d2020-03-04 15:24:38 +08001455 if ((SND_DEVICE_OUT_BT_SCO_SWB == snd_device) ||
1456 (SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC == snd_device) ||
1457 (SND_DEVICE_IN_BT_SCO_MIC_SWB == snd_device)) {
1458 if (!adev->bt_sco_on || (audio_extn_sco_start_configuration() < 0)) {
1459 ALOGE(" fail to configure sco control path ");
1460 goto err;
1461 }
Zhou Song12c29502019-03-16 10:37:18 +08001462 }
1463
Zhou Song331c8e52019-08-26 14:16:12 +08001464 configure_btsco_sample_rate(snd_device);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001465 /* due to the possibility of calibration overwrite between listen
1466 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001467 audio_extn_sound_trigger_update_device_status(snd_device,
1468 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301469 audio_extn_listen_update_device_status(snd_device,
1470 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001471 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001472 audio_extn_sound_trigger_update_device_status(snd_device,
1473 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301474 audio_extn_listen_update_device_status(snd_device,
1475 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001476 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001477 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001478 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001479 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301480
1481 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1482 !adev->native_playback_enabled &&
1483 audio_is_true_native_stream_active(adev)) {
1484 ALOGD("%s: %d: napb: enabling native mode in hardware",
1485 __func__, __LINE__);
1486 audio_route_apply_and_update_path(adev->audio_route,
1487 "true-native-mode");
1488 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301489 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301490 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1491 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001492 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001493 ALOGD("%s: init ec ref loopback", __func__);
1494 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1495 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001496 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001497 return 0;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001498err:
1499 adev->snd_dev_ref_cnt[snd_device]--;
1500 return -EINVAL;;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001501}
1502
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001503int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001504 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001505{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301506 int i, num_devices = 0;
1507 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001508 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1509
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001510 if (snd_device < SND_DEVICE_MIN ||
1511 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001512 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001513 return -EINVAL;
1514 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001515
1516 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1517 ALOGE("%s: Invalid sound device returned", __func__);
1518 return -EINVAL;
1519 }
1520
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001521 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1522 ALOGE("%s: device ref cnt is already 0", __func__);
1523 return -EINVAL;
1524 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001525
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001526 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001527
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001528
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001529 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001530 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301531
Aalique Grahame22e49102018-12-18 14:23:57 -08001532 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1533
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001534 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1535 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001536 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001537
1538 // when speaker device is disabled, reset swap.
1539 // will be renabled on usecase start
1540 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001541 } else if (platform_split_snd_device(adev->platform,
1542 snd_device,
1543 &num_devices,
1544 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301545 for (i = 0; i < num_devices; i++) {
1546 disable_snd_device(adev, new_snd_devices[i]);
1547 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001548 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001549 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001550 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001551 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001552
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301553 if (snd_device == SND_DEVICE_OUT_BT_A2DP) {
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301554 audio_extn_a2dp_stop_playback();
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301555 adev->a2dp_started = false;
1556 } else if (snd_device == SND_DEVICE_IN_BT_A2DP)
Florian Pfister1a84f312018-07-19 14:38:18 +02001557 audio_extn_a2dp_stop_capture();
Zhou Songd6d71752019-05-21 18:08:51 +08001558 else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001559 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
Ashish Jain81eb2a82015-05-13 10:52:34 +05301560 adev->is_channel_status_set = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001561 else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301562 adev->native_playback_enabled) {
1563 ALOGD("%s: %d: napb: disabling native mode in hardware",
1564 __func__, __LINE__);
1565 audio_route_reset_and_update_path(adev->audio_route,
1566 "true-native-mode");
1567 adev->native_playback_enabled = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001568 } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301569 adev->asrc_mode_enabled) {
1570 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301571 disable_asrc_mode(adev);
1572 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001573 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301574 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001575 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001576 ALOGD("%s: deinit ec ref loopback", __func__);
1577 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1578 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001579
1580 audio_extn_utils_release_snd_device(snd_device);
1581 } else {
1582 if (platform_split_snd_device(adev->platform,
1583 snd_device,
1584 &num_devices,
1585 new_snd_devices) == 0) {
1586 for (i = 0; i < num_devices; i++) {
1587 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1588 }
1589 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001590 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001591
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001592 return 0;
1593}
1594
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001595/*
1596 legend:
1597 uc - existing usecase
1598 new_uc - new usecase
1599 d1, d11, d2 - SND_DEVICE enums
1600 a1, a2 - corresponding ANDROID device enums
1601 B1, B2 - backend strings
1602
1603case 1
1604 uc->dev d1 (a1) B1
1605 new_uc->dev d1 (a1), d2 (a2) B1, B2
1606
1607 resolution: disable and enable uc->dev on d1
1608
1609case 2
1610 uc->dev d1 (a1) B1
1611 new_uc->dev d11 (a1) B1
1612
1613 resolution: need to switch uc since d1 and d11 are related
1614 (e.g. speaker and voice-speaker)
1615 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1616
1617case 3
1618 uc->dev d1 (a1) B1
1619 new_uc->dev d2 (a2) B2
1620
1621 resolution: no need to switch uc
1622
1623case 4
1624 uc->dev d1 (a1) B1
1625 new_uc->dev d2 (a2) B1
1626
1627 resolution: disable enable uc-dev on d2 since backends match
1628 we cannot enable two streams on two different devices if they
1629 share the same backend. e.g. if offload is on speaker device using
1630 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1631 using the same backend, offload must also be switched to voice-handset.
1632
1633case 5
1634 uc->dev d1 (a1) B1
1635 new_uc->dev d1 (a1), d2 (a2) B1
1636
1637 resolution: disable enable uc-dev on d2 since backends match
1638 we cannot enable two streams on two different devices if they
1639 share the same backend.
1640
1641case 6
1642 uc->dev d1 (a1) B1
1643 new_uc->dev d2 (a1) B2
1644
1645 resolution: no need to switch
1646
1647case 7
1648 uc->dev d1 (a1), d2 (a2) B1, B2
1649 new_uc->dev d1 (a1) B1
1650
1651 resolution: no need to switch
1652
Zhou Song4ba65882018-07-09 14:48:07 +08001653case 8
1654 uc->dev d1 (a1) B1
1655 new_uc->dev d11 (a1), d2 (a2) B1, B2
1656 resolution: compared to case 1, for this case, d1 and d11 are related
1657 then need to do the same as case 2 to siwtch to new uc
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301658
1659case 9
1660 uc->dev d1 (a1), d2(a2) B1 B2
1661 new_uc->dev d1 (a1), d22 (a2) B1, B2
1662 resolution: disable enable uc-dev on d2 since backends match
1663 we cannot enable two streams on two different devices if they
1664 share the same backend. This is special case for combo use case
1665 with a2dp and sco devices which uses same backend.
1666 e.g. speaker-a2dp and speaker-btsco
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001667*/
1668static snd_device_t derive_playback_snd_device(void * platform,
1669 struct audio_usecase *uc,
1670 struct audio_usecase *new_uc,
1671 snd_device_t new_snd_device)
1672{
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001673 struct listnode a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001674
1675 snd_device_t d1 = uc->out_snd_device;
1676 snd_device_t d2 = new_snd_device;
1677
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001678 list_init(&a1);
1679 list_init(&a2);
1680
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301681 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301682 case TRANSCODE_LOOPBACK_RX :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001683 assign_devices(&a1, &uc->stream.inout->out_config.device_list);
1684 assign_devices(&a2, &new_uc->stream.inout->out_config.device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301685 break;
1686 default :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001687 assign_devices(&a1, &uc->stream.out->device_list);
1688 assign_devices(&a2, &new_uc->stream.out->device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301689 break;
1690 }
1691
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001692 // Treat as a special case when a1 and a2 are not disjoint
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001693 if (!compare_devices(&a1, &a2) &&
1694 compare_devices_for_any_match(&a1 ,&a2)) {
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001695 snd_device_t d3[2];
1696 int num_devices = 0;
1697 int ret = platform_split_snd_device(platform,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001698 list_length(&a1) > 1 ? d1 : d2,
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001699 &num_devices,
1700 d3);
1701 if (ret < 0) {
1702 if (ret != -ENOSYS) {
1703 ALOGW("%s failed to split snd_device %d",
1704 __func__,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001705 list_length(&a1) > 1 ? d1 : d2);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001706 }
1707 goto end;
1708 }
1709
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001710 if (platform_check_backends_match(d3[0], d3[1])) {
1711 return d2; // case 5
1712 } else {
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301713 if ((list_length(&a1) > 1) && (list_length(&a2) > 1) &&
1714 platform_check_backends_match(d1, d2))
1715 return d2; //case 9
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001716 if (list_length(&a1) > 1)
Samyak Jaind826b502019-07-17 16:16:42 +05301717 return d1; //case 7
Garmond Leungb9eeba42018-09-18 11:10:41 -07001718 // check if d1 is related to any of d3's
1719 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001720 return d1; // case 1
1721 else
1722 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001723 }
1724 } else {
1725 if (platform_check_backends_match(d1, d2)) {
1726 return d2; // case 2, 4
1727 } else {
1728 return d1; // case 6, 3
1729 }
1730 }
1731
1732end:
1733 return d2; // return whatever was calculated before.
1734}
1735
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001736static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301737 struct audio_usecase *uc_info,
1738 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001739{
1740 struct listnode *node;
1741 struct audio_usecase *usecase;
1742 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301743 snd_device_t uc_derive_snd_device;
1744 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001745 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1746 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001747 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301748 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001749 /*
1750 * This function is to make sure that all the usecases that are active on
1751 * the hardware codec backend are always routed to any one device that is
1752 * handled by the hardware codec.
1753 * For example, if low-latency and deep-buffer usecases are currently active
1754 * on speaker and out_set_parameters(headset) is received on low-latency
1755 * output, then we have to make sure deep-buffer is also switched to headset,
1756 * because of the limitation that both the devices cannot be enabled
1757 * at the same time as they share the same backend.
1758 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001759 /*
1760 * This call is to check if we need to force routing for a particular stream
1761 * If there is a backend configuration change for the device when a
1762 * new stream starts, then ADM needs to be closed and re-opened with the new
1763 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001764 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001765 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001766 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1767 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301768 /* For a2dp device reconfigure all active sessions
1769 * with new AFE encoder format based on a2dp state
1770 */
1771 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301772 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device ||
1773 SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP == snd_device) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301774 audio_extn_a2dp_is_force_device_switch()) {
1775 force_routing = true;
1776 force_restart_session = true;
1777 }
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001778
1779 /*
1780 * Island cfg and power mode config needs to set before AFE port start.
1781 * Set force routing in case of voice device was enable before.
1782 */
1783 if (uc_info->type == VOICE_CALL &&
1784 voice_extn_is_voice_power_mode_supported() &&
1785 platform_check_and_update_island_power_status(adev->platform,
1786 uc_info,
1787 snd_device)) {
1788 force_routing = true;
1789 ALOGD("%s:becf: force routing %d for power mode supported device",
1790 __func__, force_routing);
1791 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301792 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1793
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001794 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001795 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001796 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001797 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1798 switch_device[i] = false;
1799
1800 list_for_each(node, &adev->usecase_list) {
1801 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001802
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301803 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1804 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301805 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301806 platform_get_snd_device_name(usecase->out_snd_device),
1807 platform_check_backends_match(snd_device, usecase->out_snd_device));
Rahul Sharma99770982019-03-06 17:05:26 +05301808 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
1809 (usecase->type != PCM_PASSTHROUGH)) {
Ashish Jain6a65b352017-03-21 17:24:40 +05301810 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1811 usecase, uc_info, snd_device);
1812 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001813 (is_codec_backend_out_device_type(&usecase->device_list) ||
1814 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1815 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_DEVICE) ||
1816 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_HEADSET) ||
1817 is_a2dp_out_device_type(&usecase->device_list) ||
1818 is_sco_out_device_type(&usecase->device_list)) &&
Ashish Jain6a65b352017-03-21 17:24:40 +05301819 ((force_restart_session) ||
1820 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301821 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1822 __func__, use_case_table[usecase->id],
1823 platform_get_snd_device_name(usecase->out_snd_device));
1824 disable_audio_route(adev, usecase);
1825 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301826 /* Enable existing usecase on derived playback device */
1827 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301828 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301829 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001830 }
1831 }
1832
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301833 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1834 num_uc_to_switch);
1835
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001836 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001837 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001838
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301839 /* Make sure the previous devices to be disabled first and then enable the
1840 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001841 list_for_each(node, &adev->usecase_list) {
1842 usecase = node_to_item(node, struct audio_usecase, list);
1843 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001844 /* Check if output sound device to be switched can be split and if any
1845 of the split devices match with derived sound device */
1846 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1847 &num_devices, split_snd_devices) == 0) {
1848 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
1849 for (i = 0; i < num_devices; i++) {
1850 /* Disable devices that do not match with derived sound device */
1851 if (split_snd_devices[i] != derive_snd_device[usecase->id])
1852 disable_snd_device(adev, split_snd_devices[i]);
1853 }
1854 } else {
1855 disable_snd_device(adev, usecase->out_snd_device);
1856 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001857 }
1858 }
1859
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001860 list_for_each(node, &adev->usecase_list) {
1861 usecase = node_to_item(node, struct audio_usecase, list);
1862 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001863 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1864 &num_devices, split_snd_devices) == 0) {
1865 /* Enable derived sound device only if it does not match with
1866 one of the split sound devices. This is because the matching
1867 sound device was not disabled */
1868 bool should_enable = true;
1869 for (i = 0; i < num_devices; i++) {
1870 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
1871 should_enable = false;
1872 break;
1873 }
1874 }
1875 if (should_enable)
1876 enable_snd_device(adev, derive_snd_device[usecase->id]);
1877 } else {
1878 enable_snd_device(adev, derive_snd_device[usecase->id]);
1879 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001880 }
1881 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001882
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001883 /* Re-route all the usecases on the shared backend other than the
1884 specified usecase to new snd devices */
1885 list_for_each(node, &adev->usecase_list) {
1886 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301887 /* Update the out_snd_device only before enabling the audio route */
1888 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301889 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301890 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301891 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301892 use_case_table[usecase->id],
1893 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001894 /* Update voc calibration before enabling VoIP route */
1895 if (usecase->type == VOIP_CALL)
1896 status = platform_switch_voice_call_device_post(adev->platform,
Eric Laurent637e2d42018-11-15 12:24:31 -08001897 usecase->out_snd_device,
1898 platform_get_input_snd_device(
1899 adev->platform, NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05301900 &uc_info->device_list,
1901 usecase->type));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301902 enable_audio_route(adev, usecase);
Sujin Panicker390724d2019-04-26 10:43:36 +05301903 if (usecase->stream.out && usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
kunleiz46c47dd2018-03-19 16:28:09 +08001904 out_set_voip_volume(&usecase->stream.out->stream,
1905 usecase->stream.out->volume_l,
1906 usecase->stream.out->volume_r);
1907 }
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301908 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001909 }
1910 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001911 }
1912}
1913
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301914static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001915 struct audio_usecase *uc_info,
1916 snd_device_t snd_device)
1917{
1918 struct listnode *node;
1919 struct audio_usecase *usecase;
1920 bool switch_device[AUDIO_USECASE_MAX];
1921 int i, num_uc_to_switch = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001922 int backend_check_cond = is_codec_backend_out_device_type(&uc_info->device_list);
kunleiz5cd52b82016-11-07 17:22:52 +08001923 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001924
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301925 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1926 snd_device);
1927 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301928
1929 /*
1930 * Make sure out devices is checked against out codec backend device and
1931 * also in devices against in codec backend. Checking out device against in
1932 * codec backend or vice versa causes issues.
1933 */
1934 if (uc_info->type == PCM_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001935 backend_check_cond = is_codec_backend_in_device_type(&uc_info->device_list);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001936
1937 /*
1938 * Island cfg and power mode config needs to set before AFE port start.
1939 * Set force routing in case of voice device was enable before.
1940 */
1941
1942 if (uc_info->type == VOICE_CALL &&
1943 voice_extn_is_voice_power_mode_supported() &&
1944 platform_check_and_update_island_power_status(adev->platform,
1945 uc_info,
1946 snd_device)) {
1947 force_routing = true;
1948 ALOGD("%s:becf: force routing %d for power mode supported device",
1949 __func__, force_routing);
1950 }
1951
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001952 /*
1953 * This function is to make sure that all the active capture usecases
1954 * are always routed to the same input sound device.
1955 * For example, if audio-record and voice-call usecases are currently
1956 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1957 * is received for voice call then we have to make sure that audio-record
1958 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1959 * because of the limitation that two devices cannot be enabled
1960 * at the same time if they share the same backend.
1961 */
1962 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1963 switch_device[i] = false;
1964
1965 list_for_each(node, &adev->usecase_list) {
1966 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301967 /*
1968 * TODO: Enhance below condition to handle BT sco/USB multi recording
1969 */
Jaideep Sharma477917f2020-03-13 18:13:33 +05301970
1971 bool capture_uc_needs_routing = usecase->type != PCM_PLAYBACK && (usecase != uc_info &&
1972 (usecase->in_snd_device != snd_device || force_routing));
1973 bool call_proxy_snd_device = platform_is_call_proxy_snd_device(snd_device) ||
1974 platform_is_call_proxy_snd_device(usecase->in_snd_device);
1975 if (capture_uc_needs_routing && !call_proxy_snd_device &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001976 ((backend_check_cond &&
1977 (is_codec_backend_in_device_type(&usecase->device_list) ||
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08001978 (usecase->type == VOIP_CALL))) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08001979 ((uc_info->type == VOICE_CALL &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001980 is_single_device_type_equal(&usecase->device_list,
1981 AUDIO_DEVICE_IN_VOICE_CALL)) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08001982 platform_check_backends_match(snd_device,\
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001983 usecase->in_snd_device))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001984 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05301985 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..",
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001986 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001987 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001988 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001989 switch_device[usecase->id] = true;
1990 num_uc_to_switch++;
1991 }
1992 }
1993
1994 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001995 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001996
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301997 /* Make sure the previous devices to be disabled first and then enable the
1998 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001999 list_for_each(node, &adev->usecase_list) {
2000 usecase = node_to_item(node, struct audio_usecase, list);
2001 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002002 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08002003 }
2004 }
2005
2006 list_for_each(node, &adev->usecase_list) {
2007 usecase = node_to_item(node, struct audio_usecase, list);
2008 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002009 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002010 }
2011 }
2012
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002013 /* Re-route all the usecases on the shared backend other than the
2014 specified usecase to new snd devices */
2015 list_for_each(node, &adev->usecase_list) {
2016 usecase = node_to_item(node, struct audio_usecase, list);
2017 /* Update the in_snd_device only before enabling the audio route */
2018 if (switch_device[usecase->id] ) {
2019 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08002020 if (usecase->type != VOICE_CALL) {
2021 /* Update voc calibration before enabling VoIP route */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302022 if (usecase->type == VOIP_CALL) {
2023 snd_device_t voip_snd_device;
2024 voip_snd_device = platform_get_output_snd_device(adev->platform,
2025 uc_info->stream.out,
2026 usecase->type);
kunleiz5cd52b82016-11-07 17:22:52 +08002027 status = platform_switch_voice_call_device_post(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302028 voip_snd_device,
kunleiz5cd52b82016-11-07 17:22:52 +08002029 usecase->in_snd_device);
Jaideep Sharma477917f2020-03-13 18:13:33 +05302030 }
Avinash Vaish71a8b972014-07-24 15:36:33 +05302031 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08002032 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002033 }
2034 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002035 }
2036}
2037
Mingming Yin3a941d42016-02-17 18:08:05 -08002038static void reset_hdmi_sink_caps(struct stream_out *out) {
2039 int i = 0;
2040
2041 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
2042 out->supported_channel_masks[i] = 0;
2043 }
2044 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
2045 out->supported_formats[i] = 0;
2046 }
2047 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
2048 out->supported_sample_rates[i] = 0;
2049 }
2050}
2051
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002052/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08002053static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002054{
Mingming Yin3a941d42016-02-17 18:08:05 -08002055 int ret = 0, i = 0, j = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002056 int channels = platform_edid_get_max_channels_v2(out->dev->platform,
2057 out->extconn.cs.controller,
2058 out->extconn.cs.stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002059
Mingming Yin3a941d42016-02-17 18:08:05 -08002060 reset_hdmi_sink_caps(out);
2061
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002062 /* Cache ext disp type */
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002063 ret = platform_get_ext_disp_type_v2(adev->platform,
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002064 out->extconn.cs.controller,
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002065 out->extconn.cs.stream);
2066 if(ret < 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002067 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07002068 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002069 }
2070
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002071 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002072 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08002073 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002074 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08002075 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
2076 case 6:
2077 ALOGV("%s: HDMI supports 5.1 channels", __func__);
2078 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
2079 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
2080 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
2081 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
2082 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002083 break;
2084 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08002085 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002086 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002087 break;
2088 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002089
2090 // check channel format caps
2091 i = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002092 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_AC3,
2093 out->extconn.cs.controller,
2094 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002095 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
2096 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
2097 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
2098 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
2099 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
2100 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
2101 }
2102
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002103 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD,
2104 out->extconn.cs.controller,
2105 out->extconn.cs.stream)) {
Ben Romberger1aaaf862017-04-06 17:49:46 -07002106 ALOGV(":%s HDMI supports TRUE HD format", __func__);
2107 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
2108 }
2109
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002110 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS,
2111 out->extconn.cs.controller,
2112 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002113 ALOGV(":%s HDMI supports DTS format", __func__);
2114 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
2115 }
2116
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002117 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS_HD,
2118 out->extconn.cs.controller,
2119 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002120 ALOGV(":%s HDMI supports DTS HD format", __func__);
2121 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
2122 }
2123
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002124 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_IEC61937,
2125 out->extconn.cs.controller,
2126 out->extconn.cs.stream)) {
Naresh Tanniru928f0862017-04-07 16:44:23 -07002127 ALOGV(":%s HDMI supports IEC61937 format", __func__);
2128 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
2129 }
2130
Mingming Yin3a941d42016-02-17 18:08:05 -08002131
2132 // check sample rate caps
2133 i = 0;
2134 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002135 if (platform_is_edid_supported_sample_rate_v2(out->dev->platform, out_hdmi_sample_rates[j],
2136 out->extconn.cs.controller,
2137 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002138 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
2139 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
2140 }
2141 }
2142
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002143 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002144}
2145
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002146static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
2147 uint32_t *supported_sample_rates __unused,
2148 uint32_t max_rates __unused)
2149{
2150 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
2151 supported_sample_rates,
2152 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05302153 ssize_t i = 0;
2154
2155 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002156 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
2157 supported_sample_rates[i]);
2158 }
2159 return count;
2160}
2161
2162static inline int read_usb_sup_channel_masks(bool is_playback,
2163 audio_channel_mask_t *supported_channel_masks,
2164 uint32_t max_masks)
2165{
2166 int channels = audio_extn_usb_get_max_channels(is_playback);
2167 int channel_count;
2168 uint32_t num_masks = 0;
2169 if (channels > MAX_HIFI_CHANNEL_COUNT)
2170 channels = MAX_HIFI_CHANNEL_COUNT;
2171
2172 if (is_playback) {
Eric Laurent68a87112019-05-01 18:07:29 -07002173 // start from 2 channels as framework currently doesn't support mono.
2174 if (channels >= FCC_2) {
2175 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(FCC_2);
2176 }
2177 for (channel_count = FCC_2;
2178 channel_count <= channels && num_masks < max_masks;
2179 ++channel_count) {
2180 supported_channel_masks[num_masks++] =
2181 audio_channel_mask_for_index_assignment_from_count(channel_count);
2182 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002183 } else {
vincenttewf51c94e2019-05-07 10:28:53 +08002184 // For capture we report all supported channel masks from 1 channel up.
2185 channel_count = MIN_CHANNEL_COUNT;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002186 // audio_channel_in_mask_from_count() does the right conversion to either positional or
2187 // indexed mask
Eric Laurent68a87112019-05-01 18:07:29 -07002188 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
2189 audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
2190 if (channel_count <= FCC_2) {
2191 mask = audio_channel_in_mask_from_count(channel_count);
2192 supported_channel_masks[num_masks++] = mask;
2193 }
2194 const audio_channel_mask_t index_mask =
2195 audio_channel_mask_for_index_assignment_from_count(channel_count);
2196 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
2197 supported_channel_masks[num_masks++] = index_mask;
2198 }
2199 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002200 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302201
vincenttewf51c94e2019-05-07 10:28:53 +08002202 for (size_t i = 0; i < num_masks; ++i) {
2203 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
2204 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302205 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002206 return num_masks;
2207}
2208
2209static inline int read_usb_sup_formats(bool is_playback __unused,
2210 audio_format_t *supported_formats,
2211 uint32_t max_formats __unused)
2212{
2213 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
2214 switch (bitwidth) {
2215 case 24:
2216 // XXX : usb.c returns 24 for s24 and s24_le?
2217 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
2218 break;
2219 case 32:
2220 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
2221 break;
2222 case 16:
2223 default :
2224 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
2225 break;
2226 }
2227 ALOGV("%s: %s supported format %d", __func__,
2228 is_playback ? "P" : "C", bitwidth);
2229 return 1;
2230}
2231
2232static inline int read_usb_sup_params_and_compare(bool is_playback,
2233 audio_format_t *format,
2234 audio_format_t *supported_formats,
2235 uint32_t max_formats,
2236 audio_channel_mask_t *mask,
2237 audio_channel_mask_t *supported_channel_masks,
2238 uint32_t max_masks,
2239 uint32_t *rate,
2240 uint32_t *supported_sample_rates,
2241 uint32_t max_rates) {
2242 int ret = 0;
2243 int num_formats;
2244 int num_masks;
2245 int num_rates;
2246 int i;
2247
2248 num_formats = read_usb_sup_formats(is_playback, supported_formats,
2249 max_formats);
2250 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
2251 max_masks);
2252
2253 num_rates = read_usb_sup_sample_rates(is_playback,
2254 supported_sample_rates, max_rates);
2255
2256#define LUT(table, len, what, dflt) \
2257 for (i=0; i<len && (table[i] != what); i++); \
2258 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
2259
2260 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
2261 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
2262 LUT(supported_sample_rates, num_rates, *rate, 0);
2263
2264#undef LUT
2265 return ret < 0 ? -EINVAL : 0; // HACK TBD
2266}
2267
Alexy Josephb1379942016-01-29 15:49:38 -08002268audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002269 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002270{
2271 struct audio_usecase *usecase;
2272 struct listnode *node;
2273
2274 list_for_each(node, &adev->usecase_list) {
2275 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002276 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002277 ALOGV("%s: usecase id %d", __func__, usecase->id);
2278 return usecase->id;
2279 }
2280 }
2281 return USECASE_INVALID;
2282}
2283
Alexy Josephb1379942016-01-29 15:49:38 -08002284struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002285 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002286{
2287 struct audio_usecase *usecase;
2288 struct listnode *node;
2289
2290 list_for_each(node, &adev->usecase_list) {
2291 usecase = node_to_item(node, struct audio_usecase, list);
2292 if (usecase->id == uc_id)
2293 return usecase;
2294 }
2295 return NULL;
2296}
2297
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302298/*
2299 * is a true native playback active
2300 */
2301bool audio_is_true_native_stream_active(struct audio_device *adev)
2302{
2303 bool active = false;
2304 int i = 0;
2305 struct listnode *node;
2306
2307 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
2308 ALOGV("%s:napb: not in true mode or non hdphones device",
2309 __func__);
2310 active = false;
2311 goto exit;
2312 }
2313
2314 list_for_each(node, &adev->usecase_list) {
2315 struct audio_usecase *uc;
2316 uc = node_to_item(node, struct audio_usecase, list);
2317 struct stream_out *curr_out =
2318 (struct stream_out*) uc->stream.out;
2319
2320 if (curr_out && PCM_PLAYBACK == uc->type) {
2321 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
2322 "(%d) device %s", __func__, i++, use_case_table[uc->id],
2323 uc->id, curr_out->sample_rate,
2324 curr_out->bit_width,
2325 platform_get_snd_device_name(uc->out_snd_device));
2326
2327 if (is_offload_usecase(uc->id) &&
2328 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
2329 active = true;
2330 ALOGD("%s:napb:native stream detected", __func__);
2331 }
2332 }
2333 }
2334exit:
2335 return active;
2336}
2337
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002338uint32_t adev_get_dsp_bit_width_enforce_mode()
2339{
2340 if (adev == NULL) {
2341 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
2342 return 0;
2343 }
2344 return adev->dsp_bit_width_enforce_mode;
2345}
2346
2347static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
2348{
2349 char value[PROPERTY_VALUE_MAX];
2350 int trial;
2351 uint32_t dsp_bit_width_enforce_mode = 0;
2352
2353 if (!mixer) {
2354 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
2355 __func__);
2356 return 0;
2357 }
2358
2359 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
2360 value, NULL) > 0) {
2361 trial = atoi(value);
2362 switch (trial) {
2363 case 16:
2364 dsp_bit_width_enforce_mode = 16;
2365 break;
2366 case 24:
2367 dsp_bit_width_enforce_mode = 24;
2368 break;
2369 case 32:
2370 dsp_bit_width_enforce_mode = 32;
2371 break;
2372 default:
2373 dsp_bit_width_enforce_mode = 0;
2374 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
2375 break;
2376 }
2377 }
2378
2379 return dsp_bit_width_enforce_mode;
2380}
2381
2382static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
2383 uint32_t enforce_mode,
2384 bool enable)
2385{
2386 struct mixer_ctl *ctl = NULL;
2387 const char *mixer_ctl_name = "ASM Bit Width";
2388 uint32_t asm_bit_width_mode = 0;
2389
2390 if (enforce_mode == 0) {
2391 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
2392 return;
2393 }
2394
2395 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
2396 if (!ctl) {
2397 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2398 __func__, mixer_ctl_name);
2399 return;
2400 }
2401
2402 if (enable)
2403 asm_bit_width_mode = enforce_mode;
2404 else
2405 asm_bit_width_mode = 0;
2406
2407 ALOGV("%s DSP bit width feature status is %d width=%d",
2408 __func__, enable, asm_bit_width_mode);
2409 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2410 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2411 asm_bit_width_mode);
2412
2413 return;
2414}
2415
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302416/*
2417 * if native DSD playback active
2418 */
2419bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2420{
2421 bool active = false;
2422 struct listnode *node = NULL;
2423 struct audio_usecase *uc = NULL;
2424 struct stream_out *curr_out = NULL;
2425
2426 list_for_each(node, &adev->usecase_list) {
2427 uc = node_to_item(node, struct audio_usecase, list);
2428 curr_out = (struct stream_out*) uc->stream.out;
2429
2430 if (curr_out && PCM_PLAYBACK == uc->type &&
2431 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2432 active = true;
2433 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302434 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302435 }
2436 }
2437 return active;
2438}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302439
2440static bool force_device_switch(struct audio_usecase *usecase)
2441{
2442 bool ret = false;
2443 bool is_it_true_mode = false;
2444
Zhou Song30f2c3e2018-02-08 14:02:15 +08002445 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302446 usecase->type == TRANSCODE_LOOPBACK_RX ||
2447 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002448 return false;
2449 }
2450
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002451 if(usecase->stream.out == NULL) {
2452 ALOGE("%s: stream.out is NULL", __func__);
2453 return false;
2454 }
2455
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302456 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002457 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002458 (compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADSET) ||
2459 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADPHONE))) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302460 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2461 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2462 (!is_it_true_mode && adev->native_playback_enabled)){
2463 ret = true;
2464 ALOGD("napb: time to toggle native mode");
2465 }
2466 }
2467
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302468 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302469 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2470 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002471 if(is_a2dp_out_device_type(&usecase->stream.out->device_list) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302472 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302473 ALOGD("Force a2dp device switch to update new encoder config");
2474 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002475 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302476
Florian Pfister1a84f312018-07-19 14:38:18 +02002477 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302478 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2479 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002480 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302481 return ret;
2482}
2483
Aalique Grahame22e49102018-12-18 14:23:57 -08002484static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2485{
2486 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2487}
2488
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302489bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2490{
2491 bool ret=false;
2492 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
Zhou Song5657f492019-08-07 11:30:39 +08002493 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
2494 out_snd_device == SND_DEVICE_OUT_BT_SCO_SWB) ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302495 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2496 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
Zhou Song5657f492019-08-07 11:30:39 +08002497 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302498 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
Mingshu Pang16093502020-04-20 11:21:16 +08002499 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC ||
2500 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC)
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302501 ret = true;
2502
2503 return ret;
2504}
2505
2506bool is_a2dp_device(snd_device_t out_snd_device)
2507{
2508 bool ret=false;
2509 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2510 ret = true;
2511
2512 return ret;
2513}
2514
2515bool is_bt_soc_on(struct audio_device *adev)
2516{
2517 struct mixer_ctl *ctl;
2518 char *mixer_ctl_name = "BT SOC status";
2519 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2520 bool bt_soc_status = true;
2521 if (!ctl) {
2522 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2523 __func__, mixer_ctl_name);
2524 /*This is to ensure we dont break targets which dont have the kernel change*/
2525 return true;
2526 }
2527 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2528 ALOGD("BT SOC status: %d",bt_soc_status);
2529 return bt_soc_status;
2530}
2531
Zhou Song331c8e52019-08-26 14:16:12 +08002532static int configure_btsco_sample_rate(snd_device_t snd_device)
2533{
2534 struct mixer_ctl *ctl = NULL;
2535 struct mixer_ctl *ctl_sr_rx = NULL, *ctl_sr_tx = NULL, *ctl_sr = NULL;
2536 char *rate_str = NULL;
2537 bool is_rx_dev = true;
2538
2539 if (is_btsco_device(snd_device, snd_device)) {
2540 ctl_sr_tx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate TX");
2541 ctl_sr_rx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate RX");
2542 if (!ctl_sr_tx || !ctl_sr_rx) {
2543 ctl_sr = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate");
2544 if (!ctl_sr)
2545 return -ENOSYS;
2546 }
2547
2548 switch (snd_device) {
2549 case SND_DEVICE_OUT_BT_SCO:
2550 rate_str = "KHZ_8";
2551 break;
2552 case SND_DEVICE_IN_BT_SCO_MIC_NREC:
2553 case SND_DEVICE_IN_BT_SCO_MIC:
2554 rate_str = "KHZ_8";
2555 is_rx_dev = false;
2556 break;
2557 case SND_DEVICE_OUT_BT_SCO_WB:
2558 rate_str = "KHZ_16";
2559 break;
2560 case SND_DEVICE_IN_BT_SCO_MIC_WB_NREC:
2561 case SND_DEVICE_IN_BT_SCO_MIC_WB:
2562 rate_str = "KHZ_16";
2563 is_rx_dev = false;
2564 break;
2565 default:
2566 return 0;
2567 }
2568
2569 ctl = (ctl_sr == NULL) ? (is_rx_dev ? ctl_sr_rx : ctl_sr_tx) : ctl_sr;
2570 if (mixer_ctl_set_enum_by_string(ctl, rate_str) != 0)
2571 return -ENOSYS;
2572 }
2573 return 0;
2574}
2575
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302576int out_standby_l(struct audio_stream *stream);
2577
Eric Laurent637e2d42018-11-15 12:24:31 -08002578struct stream_in *adev_get_active_input(const struct audio_device *adev)
2579{
2580 struct listnode *node;
2581 struct stream_in *last_active_in = NULL;
2582
2583 /* Get last added active input.
2584 * TODO: We may use a priority mechanism to pick highest priority active source */
2585 list_for_each(node, &adev->usecase_list)
2586 {
2587 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2588 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL)
2589 last_active_in = usecase->stream.in;
2590 }
2591
2592 return last_active_in;
2593}
2594
2595struct stream_in *get_voice_communication_input(const struct audio_device *adev)
2596{
2597 struct listnode *node;
2598
2599 /* First check active inputs with voice communication source and then
2600 * any input if audio mode is in communication */
2601 list_for_each(node, &adev->usecase_list)
2602 {
2603 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2604 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
2605 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
2606 return usecase->stream.in;
2607 }
2608 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION)
2609 return adev_get_active_input(adev);
2610
2611 return NULL;
2612}
2613
Carter Hsu2e429db2019-05-14 18:50:52 +08002614/*
2615 * Aligned with policy.h
2616 */
2617static inline int source_priority(int inputSource)
2618{
2619 switch (inputSource) {
2620 case AUDIO_SOURCE_VOICE_COMMUNICATION:
2621 return 9;
2622 case AUDIO_SOURCE_CAMCORDER:
2623 return 8;
2624 case AUDIO_SOURCE_VOICE_PERFORMANCE:
2625 return 7;
2626 case AUDIO_SOURCE_UNPROCESSED:
2627 return 6;
2628 case AUDIO_SOURCE_MIC:
2629 return 5;
2630 case AUDIO_SOURCE_ECHO_REFERENCE:
2631 return 4;
2632 case AUDIO_SOURCE_FM_TUNER:
2633 return 3;
2634 case AUDIO_SOURCE_VOICE_RECOGNITION:
2635 return 2;
2636 case AUDIO_SOURCE_HOTWORD:
2637 return 1;
2638 default:
2639 break;
2640 }
2641 return 0;
2642}
2643
2644static struct stream_in *get_priority_input(struct audio_device *adev)
2645{
2646 struct listnode *node;
2647 struct audio_usecase *usecase;
2648 int last_priority = 0, priority;
2649 struct stream_in *priority_in = NULL;
2650 struct stream_in *in;
2651
2652 list_for_each(node, &adev->usecase_list) {
2653 usecase = node_to_item(node, struct audio_usecase, list);
2654 if (usecase->type == PCM_CAPTURE) {
2655 in = usecase->stream.in;
2656 if (!in)
2657 continue;
2658 priority = source_priority(in->source);
2659
2660 if (priority > last_priority) {
2661 last_priority = priority;
2662 priority_in = in;
2663 }
2664 }
2665 }
2666 return priority_in;
2667}
2668
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002669int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002670{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002671 snd_device_t out_snd_device = SND_DEVICE_NONE;
2672 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002673 struct audio_usecase *usecase = NULL;
2674 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002675 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002676 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302677 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002678 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002679 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002680
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302681 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2682
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002683 usecase = get_usecase_from_list(adev, uc_id);
2684 if (usecase == NULL) {
2685 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2686 return -EINVAL;
2687 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002688
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002689 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002690 (usecase->type == VOIP_CALL) ||
Derek Chena30a5f42019-12-03 11:17:09 -05002691 (usecase->type == PCM_HFP_CALL)||
2692 (usecase->type == ICC_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302693 if(usecase->stream.out == NULL) {
2694 ALOGE("%s: stream.out is NULL", __func__);
2695 return -EINVAL;
2696 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002697 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS)) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002698 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev,
2699 uc_id);
2700 in_snd_device = audio_extn_auto_hal_get_input_snd_device(adev,
2701 uc_id);
2702 } else {
2703 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302704 usecase->stream.out, usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002705 in_snd_device = platform_get_input_snd_device(adev->platform,
2706 NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302707 &usecase->stream.out->device_list,
2708 usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002709 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002710 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302711 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302712 if (usecase->stream.inout == NULL) {
2713 ALOGE("%s: stream.inout is NULL", __func__);
2714 return -EINVAL;
2715 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002716 assign_devices(&stream_out.device_list, &usecase->stream.inout->out_config.device_list);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302717 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2718 stream_out.format = usecase->stream.inout->out_config.format;
2719 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
Jaideep Sharma477917f2020-03-13 18:13:33 +05302720 out_snd_device = platform_get_output_snd_device(adev->platform, &stream_out, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002721 assign_devices(&usecase->device_list,
2722 &usecase->stream.inout->out_config.device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302723 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2724 if (usecase->stream.inout == NULL) {
2725 ALOGE("%s: stream.inout is NULL", __func__);
2726 return -EINVAL;
2727 }
Manisha Agarwal03297972020-04-17 15:36:55 +05302728 struct listnode out_devices;
2729 list_init(&out_devices);
2730 in_snd_device = platform_get_input_snd_device(adev->platform, NULL,
2731 &out_devices, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002732 assign_devices(&usecase->device_list,
2733 &usecase->stream.inout->in_config.device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002734 } else {
2735 /*
2736 * If the voice call is active, use the sound devices of voice call usecase
2737 * so that it would not result any device switch. All the usecases will
2738 * be switched to new device when select_devices() is called for voice call
2739 * usecase. This is to avoid switching devices for voice call when
2740 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002741 * choose voice call device only if the use case device is
2742 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002743 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002744 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002745 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002746 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002747 if ((vc_usecase) && ((is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2748 is_codec_backend_out_device_type(&usecase->device_list)) ||
2749 (is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2750 is_codec_backend_in_device_type(&usecase->device_list)) ||
2751 is_single_device_type_equal(&vc_usecase->device_list,
2752 AUDIO_DEVICE_OUT_HEARING_AID) ||
2753 is_single_device_type_equal(&usecase->device_list,
Robert Lee8a6aaf32019-09-20 16:40:19 +08002754 AUDIO_DEVICE_IN_VOICE_CALL) ||
2755 (is_single_device_type_equal(&usecase->device_list,
2756 AUDIO_DEVICE_IN_USB_HEADSET) &&
2757 is_single_device_type_equal(&vc_usecase->device_list,
2758 AUDIO_DEVICE_OUT_USB_HEADSET)))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002759 in_snd_device = vc_usecase->in_snd_device;
2760 out_snd_device = vc_usecase->out_snd_device;
2761 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002762 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002763 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002764 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002765 if ((voip_usecase != NULL) &&
2766 (usecase->type == PCM_PLAYBACK) &&
2767 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002768 out_snd_device_backend_match = platform_check_backends_match(
2769 voip_usecase->out_snd_device,
2770 platform_get_output_snd_device(
2771 adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302772 usecase->stream.out, usecase->type));
yidongh02ef86f2017-04-21 15:36:04 +08002773 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002774 if ((voip_usecase) && (is_codec_backend_out_device_type(&voip_usecase->device_list) &&
2775 (is_codec_backend_out_device_type(&usecase->device_list) ||
2776 is_codec_backend_in_device_type(&usecase->device_list)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002777 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002778 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002779 in_snd_device = voip_usecase->in_snd_device;
2780 out_snd_device = voip_usecase->out_snd_device;
2781 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002782 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002783 hfp_ucid = audio_extn_hfp_get_usecase();
2784 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002785 if ((hfp_usecase) && is_codec_backend_out_device_type(&hfp_usecase->device_list)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002786 in_snd_device = hfp_usecase->in_snd_device;
2787 out_snd_device = hfp_usecase->out_snd_device;
2788 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002789 }
2790 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302791 if (usecase->stream.out == NULL) {
2792 ALOGE("%s: stream.out is NULL", __func__);
2793 return -EINVAL;
2794 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002795 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002796 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002797 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002798 struct stream_out *voip_out = adev->primary_output;
2799 struct stream_in *voip_in = get_voice_communication_input(adev);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002800 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS))
Guodong Hu267bdf82019-08-12 19:22:32 +08002801 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev, uc_id);
2802 else
2803 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302804 usecase->stream.out,
2805 usecase->type);
kunleizdcf967a2018-08-07 17:09:11 +08002806 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizdcf967a2018-08-07 17:09:11 +08002807
Eric Laurent637e2d42018-11-15 12:24:31 -08002808 if (voip_usecase)
2809 voip_out = voip_usecase->stream.out;
2810
2811 if (usecase->stream.out == voip_out && voip_in != NULL)
2812 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002813 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002814 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302815 if (usecase->stream.in == NULL) {
2816 ALOGE("%s: stream.in is NULL", __func__);
2817 return -EINVAL;
2818 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002819 assign_devices(&usecase->device_list, &usecase->stream.in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002820 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002821 if (in_snd_device == SND_DEVICE_NONE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002822 struct listnode out_devices;
Eric Laurent637e2d42018-11-15 12:24:31 -08002823 struct stream_in *voip_in = get_voice_communication_input(adev);
Carter Hsu2e429db2019-05-14 18:50:52 +08002824 struct stream_in *priority_in = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08002825
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002826 list_init(&out_devices);
Eric Laurent637e2d42018-11-15 12:24:31 -08002827 if (voip_in != NULL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002828 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
2829 USECASE_AUDIO_PLAYBACK_VOIP);
2830
Carter Hsu2e429db2019-05-14 18:50:52 +08002831 usecase->stream.in->enable_ec_port = false;
2832
Zhou Song62ea0282020-03-22 19:53:01 +08002833 bool is_ha_usecase = adev->ha_proxy_enable ?
2834 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY2 :
2835 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY;
2836 if (is_ha_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002837 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_TELEPHONY_TX, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002838 } else if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002839 assign_devices(&out_devices, &voip_usecase->stream.out->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002840 } else if (adev->primary_output &&
2841 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002842 assign_devices(&out_devices, &adev->primary_output->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002843 } else {
2844 /* forcing speaker o/p device to get matching i/p pair
2845 in case o/p is not routed from same primary HAL */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002846 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002847 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002848 priority_in = voip_in;
2849 } else {
2850 /* get the input with the highest priority source*/
2851 priority_in = get_priority_input(adev);
2852
2853 if (!priority_in)
2854 priority_in = usecase->stream.in;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002855 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002856
Eric Laurent637e2d42018-11-15 12:24:31 -08002857 in_snd_device = platform_get_input_snd_device(adev->platform,
Carter Hsu2e429db2019-05-14 18:50:52 +08002858 priority_in,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302859 &out_devices,
2860 usecase->type);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002861 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002862 }
2863 }
2864
2865 if (out_snd_device == usecase->out_snd_device &&
2866 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302867
2868 if (!force_device_switch(usecase))
2869 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002870 }
2871
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002872 if (!compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS) &&
Guodong Hu267bdf82019-08-12 19:22:32 +08002873 ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002874 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready()))) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002875 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2876 return 0;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302877 }
2878
Aalique Grahame22e49102018-12-18 14:23:57 -08002879 if (out_snd_device != SND_DEVICE_NONE &&
2880 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
2881 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2882 __func__,
2883 use_case_table[uc_id],
2884 adev->last_logged_snd_device[uc_id][0],
2885 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
2886 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
2887 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
2888 -1,
2889 out_snd_device,
2890 platform_get_snd_device_name(out_snd_device),
2891 platform_get_snd_device_acdb_id(out_snd_device));
2892 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
2893 }
2894 if (in_snd_device != SND_DEVICE_NONE &&
2895 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
2896 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2897 __func__,
2898 use_case_table[uc_id],
2899 adev->last_logged_snd_device[uc_id][1],
2900 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
2901 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
2902 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
2903 -1,
2904 in_snd_device,
2905 platform_get_snd_device_name(in_snd_device),
2906 platform_get_snd_device_acdb_id(in_snd_device));
2907 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
2908 }
2909
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002910
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002911 /*
2912 * Limitation: While in call, to do a device switch we need to disable
2913 * and enable both RX and TX devices though one of them is same as current
2914 * device.
2915 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002916 if ((usecase->type == VOICE_CALL) &&
2917 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2918 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002919 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002920 }
2921
2922 if (((usecase->type == VOICE_CALL) ||
2923 (usecase->type == VOIP_CALL)) &&
2924 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2925 /* Disable sidetone only if voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302926 if (voice_is_call_state_active_in_call(adev) ||
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002927 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002928 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002929
2930 /* Disable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302931 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002932 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002933 }
2934
Aalique Grahame22e49102018-12-18 14:23:57 -08002935 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
2936 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02002937 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302938 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08002939 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
2940 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
2941 else
2942 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302943 }
2944
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002945 /* Disable current sound devices */
2946 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002947 disable_audio_route(adev, usecase);
2948 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002949 }
2950
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002951 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002952 disable_audio_route(adev, usecase);
2953 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002954 }
2955
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002956 /* Applicable only on the targets that has external modem.
2957 * New device information should be sent to modem before enabling
2958 * the devices to reduce in-call device switch time.
2959 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002960 if ((usecase->type == VOICE_CALL) &&
2961 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2962 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002963 status = platform_switch_voice_call_enable_device_config(adev->platform,
2964 out_snd_device,
2965 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002966 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002967
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002968 /* Enable new sound devices */
2969 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002970 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302971 if (platform_check_codec_asrc_support(adev->platform))
2972 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002973 enable_snd_device(adev, out_snd_device);
Zhou Songd9bd9302020-08-04 16:34:45 +08002974 /* Enable haptics device for haptic usecase */
2975 if (usecase->id == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
2976 enable_snd_device(adev, SND_DEVICE_OUT_HAPTICS);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002977 }
2978
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002979 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302980 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002981 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002982 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002983
Avinash Vaish71a8b972014-07-24 15:36:33 +05302984 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002985 status = platform_switch_voice_call_device_post(adev->platform,
2986 out_snd_device,
2987 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05302988 enable_audio_route_for_voice_usecases(adev, usecase);
2989 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002990
sangwoo170731f2013-06-08 15:36:36 +09002991 usecase->in_snd_device = in_snd_device;
2992 usecase->out_snd_device = out_snd_device;
2993
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302994 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2995 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302996 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002997 if ((24 == usecase->stream.out->bit_width) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002998 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_SPEAKER)) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002999 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3000 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
3001 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
3002 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
3003 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
3004 /*
3005 * To best utlize DSP, check if the stream sample rate is supported/multiple of
3006 * configured device sample rate, if not update the COPP rate to be equal to the
3007 * device sample rate, else open COPP at stream sample rate
3008 */
3009 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
3010 usecase->stream.out->sample_rate,
3011 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05303012 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
Preetam Singh Ranawat590d0432019-09-30 14:39:47 +05303013 out_snd_device != SND_DEVICE_OUT_HEADPHONES &&
3014 out_snd_device != SND_DEVICE_OUT_HEADPHONES_HIFI_FILTER &&
Ashish Jain4826f6c2017-02-06 13:33:20 +05303015 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003016 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
3017 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
3018 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3019 }
Weiyin Jiangcdece202019-07-08 16:13:16 +08003020 }
3021 enable_audio_route(adev, usecase);
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003022
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08003023 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08003024
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003025 /* If input stream is already running then effect needs to be
3026 applied on the new input device that's being enabled here. */
Eric Laurent637e2d42018-11-15 12:24:31 -08003027 if (in_snd_device != SND_DEVICE_NONE)
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003028 check_and_enable_effect(adev);
3029
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003030 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003031 /* Enable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303032 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003033 voice_check_and_update_aanc_path(adev, out_snd_device, true);
3034
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003035 /* Enable sidetone only if other voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303036 if (voice_is_call_state_active_in_call(adev) ||
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003037 voice_extn_compress_voip_is_started(adev))
3038 voice_set_sidetone(adev, out_snd_device, true);
3039 }
3040
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003041 /* Applicable only on the targets that has external modem.
3042 * Enable device command should be sent to modem only after
3043 * enabling voice call mixer controls
3044 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07003045 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003046 status = platform_switch_voice_call_usecase_route_post(adev->platform,
3047 out_snd_device,
3048 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303049
3050 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003051 struct stream_in *in = adev_get_active_input(adev);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303052 if (usecase->type == VOIP_CALL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003053 if (in != NULL && !in->standby) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303054 if (is_bt_soc_on(adev) == false){
3055 ALOGD("BT SCO MIC disconnected while in connection");
Eric Laurent637e2d42018-11-15 12:24:31 -08003056 if (in->pcm != NULL)
3057 pcm_stop(in->pcm);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303058 }
3059 }
3060 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
3061 && usecase->stream.out->started) {
3062 if (is_bt_soc_on(adev) == false) {
3063 ALOGD("BT SCO/A2DP disconnected while in connection");
3064 out_standby_l(&usecase->stream.out->stream.common);
3065 }
3066 }
3067 } else if ((usecase->stream.out != NULL) &&
3068 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05303069 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
3070 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Weiyin Jiang0d373242019-07-25 13:18:17 +08003071 (usecase->type != PCM_CAPTURE) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303072 usecase->stream.out->started) {
3073 if (is_bt_soc_on(adev) == false) {
3074 ALOGD("BT SCO/A2dp disconnected while in connection");
3075 out_standby_l(&usecase->stream.out->stream.common);
3076 }
3077 }
3078 }
3079
Yung Ti Su70cb8242018-06-22 17:38:47 +08003080 if (usecase->type != PCM_CAPTURE && usecase == voip_usecase) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003081 struct stream_out *voip_out = voip_usecase->stream.out;
3082 audio_extn_utils_send_app_type_gain(adev,
3083 voip_out->app_type_cfg.app_type,
3084 &voip_out->app_type_cfg.gain[0]);
3085 }
3086
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07003087 ALOGV("%s: done",__func__);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303088
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003089 return status;
3090}
3091
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003092static int stop_input_stream(struct stream_in *in)
3093{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303094 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003095 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05303096
3097 if (in == NULL) {
3098 ALOGE("%s: stream_in ptr is NULL", __func__);
3099 return -EINVAL;
3100 }
3101
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003102 struct audio_device *adev = in->dev;
Carter Hsu2e429db2019-05-14 18:50:52 +08003103 struct stream_in *priority_in = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003104
Eric Laurent994a6932013-07-17 11:51:42 -07003105 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003106 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003107 uc_info = get_usecase_from_list(adev, in->usecase);
3108 if (uc_info == NULL) {
3109 ALOGE("%s: Could not find the usecase (%d) in the list",
3110 __func__, in->usecase);
3111 return -EINVAL;
3112 }
3113
Carter Hsu2e429db2019-05-14 18:50:52 +08003114 priority_in = get_priority_input(adev);
3115
Derek Chenea197282019-01-07 17:35:01 -08003116 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3117 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003118
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003119 /* Close in-call recording streams */
3120 voice_check_and_stop_incall_rec_usecase(adev, in);
3121
Eric Laurent150dbfe2013-02-27 14:31:02 -08003122 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003123 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003124
3125 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003126 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003127
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003128 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303129 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_PRIMARY);
3130
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003131 list_remove(&uc_info->list);
3132 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003133
Carter Hsu2e429db2019-05-14 18:50:52 +08003134 if (priority_in == in) {
3135 priority_in = get_priority_input(adev);
3136 if (priority_in)
3137 select_devices(adev, priority_in->usecase);
3138 }
3139
Vatsal Buchac09ae062018-11-14 13:25:08 +05303140 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07003141 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003142 return ret;
3143}
3144
3145int start_input_stream(struct stream_in *in)
3146{
3147 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08003148 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003149 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05303150
3151 if (in == NULL) {
3152 ALOGE("%s: stream_in ptr is NULL", __func__);
3153 return -EINVAL;
3154 }
3155
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003156 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07003157 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07003158 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003159
Mingming Yin2664a5b2015-09-03 10:53:11 -07003160 if (get_usecase_from_list(adev, usecase) == NULL)
3161 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303162 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
3163 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003164
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303165 if (CARD_STATUS_OFFLINE == in->card_status||
3166 CARD_STATUS_OFFLINE == adev->card_status) {
3167 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303168 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303169 goto error_config;
3170 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303171
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003172 if (is_sco_in_device_type(&in->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303173 if (!adev->bt_sco_on) {
3174 ALOGE("%s: SCO profile is not ready, return error", __func__);
3175 ret = -EIO;
3176 goto error_config;
3177 }
3178 }
3179
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003180 /* Check if source matches incall recording usecase criteria */
3181 ret = voice_check_and_set_incall_rec_usecase(adev, in);
3182 if (ret)
3183 goto error_config;
3184 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07003185 ALOGV("%s: usecase(%d)", __func__, in->usecase);
3186
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303187 if (audio_extn_cin_attached_usecase(in))
3188 audio_extn_cin_acquire_usecase(in);
3189
Mingming Yin2664a5b2015-09-03 10:53:11 -07003190 if (get_usecase_from_list(adev, in->usecase) != NULL) {
3191 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
3192 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Weiyin Jiang38c0e612020-09-10 16:10:51 +08003193 ret = -EINVAL;
3194 goto error_config;
Mingming Yin2664a5b2015-09-03 10:53:11 -07003195 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003196
Eric Laurentb23d5282013-05-14 15:27:20 -07003197 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003198 if (in->pcm_device_id < 0) {
3199 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
3200 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08003201 ret = -EINVAL;
3202 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003203 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003204
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003205 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003206
3207 if (!uc_info) {
3208 ret = -ENOMEM;
3209 goto error_config;
3210 }
3211
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003212 uc_info->id = in->usecase;
3213 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003214 uc_info->stream.in = in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003215 list_init(&uc_info->device_list);
3216 assign_devices(&uc_info->device_list, &in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003217 uc_info->in_snd_device = SND_DEVICE_NONE;
3218 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003219
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003220 list_add_tail(&adev->usecase_list, &uc_info->list);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003221 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303222 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3223 adev->perf_lock_opts,
3224 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003225 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003226
Derek Chenea197282019-01-07 17:35:01 -08003227 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3228 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003229
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05303230 android_atomic_acquire_cas(true, false, &(in->capture_stopped));
3231
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303232 if (audio_extn_cin_attached_usecase(in)) {
Manish Dewangan46e07982018-12-13 18:18:59 +05303233 ret = audio_extn_cin_open_input_stream(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303234 if (ret)
3235 goto error_open;
3236 else
3237 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003238 }
3239
Haynes Mathew George16081042017-05-31 17:16:49 -07003240 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003241 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003242 ALOGE("%s: pcm stream not ready", __func__);
3243 goto error_open;
3244 }
3245 ret = pcm_start(in->pcm);
3246 if (ret < 0) {
3247 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3248 goto error_open;
3249 }
3250 } else {
3251 unsigned int flags = PCM_IN | PCM_MONOTONIC;
3252 unsigned int pcm_open_retry_count = 0;
3253
Zhou Song62ea0282020-03-22 19:53:01 +08003254 if ((in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) ||
3255 (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003256 flags |= PCM_MMAP | PCM_NOIRQ;
3257 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
3258 } else if (in->realtime) {
3259 flags |= PCM_MMAP | PCM_NOIRQ;
3260 }
3261
Garmond Leunge2433c32017-09-28 21:51:22 -07003262 if (audio_extn_ffv_get_stream() == in) {
3263 ALOGD("%s: ffv stream, update pcm config", __func__);
3264 audio_extn_ffv_update_pcm_config(&config);
3265 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003266 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3267 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3268
3269 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003270 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07003271 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07003272 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003273 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303274 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303275 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3276 adev->card_status = CARD_STATUS_OFFLINE;
3277 in->card_status = CARD_STATUS_OFFLINE;
3278 ret = -EIO;
3279 goto error_open;
3280 }
3281
Haynes Mathew George16081042017-05-31 17:16:49 -07003282 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3283 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3284 if (in->pcm != NULL) {
3285 pcm_close(in->pcm);
3286 in->pcm = NULL;
3287 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003288 if (pcm_open_retry_count == 0) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003289 ret = -EIO;
3290 goto error_open;
3291 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003292 pcm_open_retry_count--;
Haynes Mathew George16081042017-05-31 17:16:49 -07003293 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3294 continue;
3295 }
3296 break;
3297 }
3298
3299 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003300 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07003301 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003302 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003303 if (ret < 0) {
3304 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3305 pcm_close(in->pcm);
3306 in->pcm = NULL;
3307 goto error_open;
3308 }
3309 register_in_stream(in);
3310 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003311 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07003312 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003313 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003314 if (ret < 0) {
3315 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003316 pcm_close(in->pcm);
3317 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003318 goto error_open;
3319 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003320 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003321 }
3322
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003323 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07003324 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
3325 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003326
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003327 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303328 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
3329
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303330done_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003331 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303332 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07003333 ALOGV("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303334 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003335 return ret;
3336
3337error_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003338 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303339 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003340 stop_input_stream(in);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003341
Eric Laurentc8400632013-02-14 19:04:54 -08003342error_config:
Weiyin Jiang38c0e612020-09-10 16:10:51 +08003343 if (audio_extn_cin_attached_usecase(in))
3344 audio_extn_cin_close_input_stream(in);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303345 /*
3346 * sleep 50ms to allow sufficient time for kernel
3347 * drivers to recover incases like SSR.
3348 */
3349 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003350 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303351 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003352 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003353}
3354
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003355void lock_input_stream(struct stream_in *in)
3356{
3357 pthread_mutex_lock(&in->pre_lock);
3358 pthread_mutex_lock(&in->lock);
3359 pthread_mutex_unlock(&in->pre_lock);
3360}
3361
3362void lock_output_stream(struct stream_out *out)
3363{
3364 pthread_mutex_lock(&out->pre_lock);
3365 pthread_mutex_lock(&out->lock);
3366 pthread_mutex_unlock(&out->pre_lock);
3367}
3368
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003369/* must be called with out->lock locked */
3370static int send_offload_cmd_l(struct stream_out* out, int command)
3371{
3372 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
3373
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003374 if (!cmd) {
3375 ALOGE("failed to allocate mem for command 0x%x", command);
3376 return -ENOMEM;
3377 }
3378
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003379 ALOGVV("%s %d", __func__, command);
3380
3381 cmd->cmd = command;
3382 list_add_tail(&out->offload_cmd_list, &cmd->node);
3383 pthread_cond_signal(&out->offload_cond);
3384 return 0;
3385}
3386
Weiyin Jiang280ea742020-09-08 20:28:22 +08003387/* must be called with out->lock and latch lock */
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003388static void stop_compressed_output_l(struct stream_out *out)
3389{
3390 out->offload_state = OFFLOAD_STATE_IDLE;
3391 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003392 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003393 if (out->compr != NULL) {
3394 compress_stop(out->compr);
3395 while (out->offload_thread_blocked) {
3396 pthread_cond_wait(&out->cond, &out->lock);
3397 }
3398 }
3399}
3400
Varun Balaraje49253e2017-07-06 19:48:56 +05303401bool is_interactive_usecase(audio_usecase_t uc_id)
3402{
3403 unsigned int i;
3404 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
3405 if (uc_id == interactive_usecases[i])
3406 return true;
3407 }
3408 return false;
3409}
3410
3411static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
3412{
3413 audio_usecase_t ret_uc = USECASE_INVALID;
3414 unsigned int intract_uc_index;
3415 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3416
3417 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
3418 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
3419 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
3420 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
3421 ret_uc = interactive_usecases[intract_uc_index];
3422 break;
3423 }
3424 }
3425
3426 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
3427 return ret_uc;
3428}
3429
3430static void free_interactive_usecase(struct audio_device *adev,
3431 audio_usecase_t uc_id)
3432{
3433 unsigned int interact_uc_index;
3434 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3435
3436 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
3437 if (interactive_usecases[interact_uc_index] == uc_id) {
3438 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
3439 break;
3440 }
3441 }
3442 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
3443}
3444
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003445bool is_offload_usecase(audio_usecase_t uc_id)
3446{
3447 unsigned int i;
3448 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
3449 if (uc_id == offload_usecases[i])
3450 return true;
3451 }
3452 return false;
3453}
3454
Dhananjay Kumarac341582017-02-23 23:42:25 +05303455static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003456{
vivek mehta446c3962015-09-14 10:57:35 -07003457 audio_usecase_t ret_uc = USECASE_INVALID;
3458 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003459 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003460 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05303461 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07003462 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
3463 else
3464 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003465
vivek mehta446c3962015-09-14 10:57:35 -07003466 pthread_mutex_lock(&adev->lock);
3467 if (get_usecase_from_list(adev, ret_uc) != NULL)
3468 ret_uc = USECASE_INVALID;
3469 pthread_mutex_unlock(&adev->lock);
3470
3471 return ret_uc;
3472 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003473
3474 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003475 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3476 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3477 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3478 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003479 break;
3480 }
3481 }
vivek mehta446c3962015-09-14 10:57:35 -07003482
3483 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3484 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003485}
3486
3487static void free_offload_usecase(struct audio_device *adev,
3488 audio_usecase_t uc_id)
3489{
vivek mehta446c3962015-09-14 10:57:35 -07003490 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003491 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003492
3493 if (!adev->multi_offload_enable)
3494 return;
3495
3496 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3497 if (offload_usecases[offload_uc_index] == uc_id) {
3498 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003499 break;
3500 }
3501 }
3502 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3503}
3504
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003505static void *offload_thread_loop(void *context)
3506{
3507 struct stream_out *out = (struct stream_out *) context;
3508 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003509 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003510
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003511 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08003512 set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003513 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3514
3515 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003516 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003517 out->offload_state = OFFLOAD_STATE_IDLE;
3518 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003519 for (;;) {
3520 struct offload_cmd *cmd = NULL;
3521 stream_callback_event_t event;
3522 bool send_callback = false;
3523
3524 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3525 __func__, list_empty(&out->offload_cmd_list),
3526 out->offload_state);
3527 if (list_empty(&out->offload_cmd_list)) {
3528 ALOGV("%s SLEEPING", __func__);
3529 pthread_cond_wait(&out->offload_cond, &out->lock);
3530 ALOGV("%s RUNNING", __func__);
3531 continue;
3532 }
3533
3534 item = list_head(&out->offload_cmd_list);
3535 cmd = node_to_item(item, struct offload_cmd, node);
3536 list_remove(item);
3537
3538 ALOGVV("%s STATE %d CMD %d out->compr %p",
3539 __func__, out->offload_state, cmd->cmd, out->compr);
3540
3541 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3542 free(cmd);
3543 break;
3544 }
3545
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003546 // allow OFFLOAD_CMD_ERROR reporting during standby
3547 // this is needed to handle failures during compress_open
3548 // Note however that on a pause timeout, the stream is closed
3549 // and no offload usecase will be active. Therefore this
3550 // special case is needed for compress_open failures alone
3551 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3552 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003553 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003554 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003555 pthread_cond_signal(&out->cond);
3556 continue;
3557 }
3558 out->offload_thread_blocked = true;
3559 pthread_mutex_unlock(&out->lock);
3560 send_callback = false;
3561 switch(cmd->cmd) {
3562 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003563 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003564 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003565 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003566 send_callback = true;
3567 event = STREAM_CBK_EVENT_WRITE_READY;
3568 break;
3569 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003570 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303571 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003572 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303573 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003574 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303575 if (ret < 0)
3576 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303577 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303578 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003579 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003580 else
3581 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003582 if (-ENETRESET != ret && !(-EINTR == ret &&
3583 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303584 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303585 pthread_mutex_lock(&out->lock);
3586 out->send_new_metadata = 1;
3587 out->send_next_track_params = true;
3588 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303589 event = STREAM_CBK_EVENT_DRAIN_READY;
3590 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3591 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303592 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003593 break;
3594 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003595 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003596 ret = compress_drain(out->compr);
3597 ALOGD("copl(%p):out of compress_drain", out);
3598 // EINTR check avoids drain interruption due to SSR
3599 if (-ENETRESET != ret && !(-EINTR == ret &&
3600 CARD_STATUS_OFFLINE == out->card_status)) {
3601 send_callback = true;
3602 event = STREAM_CBK_EVENT_DRAIN_READY;
3603 } else
3604 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003605 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303606 case OFFLOAD_CMD_ERROR:
3607 ALOGD("copl(%p): sending error callback to AF", out);
3608 send_callback = true;
3609 event = STREAM_CBK_EVENT_ERROR;
3610 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003611 default:
3612 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3613 break;
3614 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003615 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003616 out->offload_thread_blocked = false;
3617 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003618 if (send_callback && out->client_callback) {
3619 ALOGVV("%s: sending client_callback event %d", __func__, event);
3620 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003621 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003622 free(cmd);
3623 }
3624
3625 pthread_cond_signal(&out->cond);
3626 while (!list_empty(&out->offload_cmd_list)) {
3627 item = list_head(&out->offload_cmd_list);
3628 list_remove(item);
3629 free(node_to_item(item, struct offload_cmd, node));
3630 }
3631 pthread_mutex_unlock(&out->lock);
3632
3633 return NULL;
3634}
3635
3636static int create_offload_callback_thread(struct stream_out *out)
3637{
3638 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3639 list_init(&out->offload_cmd_list);
3640 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3641 offload_thread_loop, out);
3642 return 0;
3643}
3644
3645static int destroy_offload_callback_thread(struct stream_out *out)
3646{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003647 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08003648 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003649 stop_compressed_output_l(out);
3650 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3651
Weiyin Jiang280ea742020-09-08 20:28:22 +08003652 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003653 pthread_mutex_unlock(&out->lock);
3654 pthread_join(out->offload_thread, (void **) NULL);
3655 pthread_cond_destroy(&out->offload_cond);
3656
3657 return 0;
3658}
3659
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003660static int stop_output_stream(struct stream_out *out)
3661{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303662 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003663 struct audio_usecase *uc_info;
3664 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003665 bool has_voip_usecase =
3666 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003667
Eric Laurent994a6932013-07-17 11:51:42 -07003668 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003669 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003670 uc_info = get_usecase_from_list(adev, out->usecase);
3671 if (uc_info == NULL) {
3672 ALOGE("%s: Could not find the usecase (%d) in the list",
3673 __func__, out->usecase);
3674 return -EINVAL;
3675 }
3676
Derek Chenea197282019-01-07 17:35:01 -08003677 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3678 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003679
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003680 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303681 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003682 if (adev->visualizer_stop_output != NULL)
3683 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003684
3685 audio_extn_dts_remove_state_notifier_node(out->usecase);
3686
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003687 if (adev->offload_effects_stop_output != NULL)
3688 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07003689 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3690 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3691 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003692 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003693
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003694 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3695 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003696 voice_set_device_mute_flag(adev, false);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003697 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003698
Eric Laurent150dbfe2013-02-27 14:31:02 -08003699 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003700 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003701
3702 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003703 disable_snd_device(adev, uc_info->out_snd_device);
Zhou Songd9bd9302020-08-04 16:34:45 +08003704 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
3705 disable_snd_device(adev, SND_DEVICE_OUT_HAPTICS);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003706
Aalique Grahame22e49102018-12-18 14:23:57 -08003707 audio_extn_extspk_update(adev->extspk);
3708
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003709 if (is_offload_usecase(out->usecase)) {
3710 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3711 adev->dsp_bit_width_enforce_mode,
3712 false);
3713 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003714 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003715 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3716 false);
3717
3718 if (ret != 0)
3719 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3720 /* default service interval was successfully updated,
3721 reopen USB backend with new service interval */
3722 ret = 0;
3723 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003724
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003725 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303726 out->started = 0;
Weiyin Jiang280ea742020-09-08 20:28:22 +08003727 pthread_mutex_lock(&out->latch_lock);
3728 out->muted = false;
3729 pthread_mutex_unlock(&out->latch_lock);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003730 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303731 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003732 ALOGV("Disable passthrough , reset mixer to pcm");
3733 /* NO_PASSTHROUGH */
Meng Wang4c32fb42020-01-16 17:57:11 +08003734#ifdef AUDIO_GKI_ENABLED
3735 /* out->compr_config.codec->reserved[0] is for compr_passthr */
3736 out->compr_config.codec->reserved[0] = 0;
3737#else
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003738 out->compr_config.codec->compr_passthr = 0;
Meng Wang4c32fb42020-01-16 17:57:11 +08003739#endif
Mingming Yin21854652016-04-13 11:54:02 -07003740 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003741 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3742 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003743
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303744 /* Must be called after removing the usecase from list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003745 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL))
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303746 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303747
Manish Dewangan21a850a2017-08-14 12:03:55 +05303748 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003749 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3750 if (ret < 0)
3751 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3752 }
3753
juyuchen2d415992018-11-16 14:15:16 +08003754 /* 1) media + voip output routing to handset must route media back to
3755 speaker when voip stops.
3756 2) trigger voip input to reroute when voip output changes to
3757 hearing aid. */
Aalique Grahame22e49102018-12-18 14:23:57 -08003758 if (has_voip_usecase ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003759 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003760 struct listnode *node;
3761 struct audio_usecase *usecase;
3762 list_for_each(node, &adev->usecase_list) {
3763 usecase = node_to_item(node, struct audio_usecase, list);
juyuchen2d415992018-11-16 14:15:16 +08003764 if ((usecase->type == PCM_CAPTURE &&
Revathi Uddarajud9f23d92020-07-27 10:55:06 +05303765 usecase->id != USECASE_AUDIO_RECORD_VOIP &&
3766 usecase->id != USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY)
juyuchen2d415992018-11-16 14:15:16 +08003767 || usecase == uc_info)
Aalique Grahame22e49102018-12-18 14:23:57 -08003768 continue;
3769
3770 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
3771 __func__, usecase->id, use_case_table[usecase->id],
3772 out->usecase, use_case_table[out->usecase]);
3773 select_devices(adev, usecase->id);
3774 }
3775 }
3776
Garmond Leung5fd0b552018-04-17 11:56:12 -07003777 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003778 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003779 return ret;
3780}
3781
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003782struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
3783 unsigned int flags, unsigned int pcm_open_retry_count,
3784 struct pcm_config *config)
3785{
3786 struct pcm* pcm = NULL;
3787
3788 while (1) {
3789 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
3790 if (pcm == NULL || !pcm_is_ready(pcm)) {
3791 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
3792 if (pcm != NULL) {
3793 pcm_close(pcm);
3794 pcm = NULL;
3795 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003796 if (pcm_open_retry_count == 0)
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003797 return NULL;
3798
Weiyin Jiang72197252019-10-09 11:49:32 +08003799 pcm_open_retry_count--;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003800 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3801 continue;
3802 }
3803 break;
3804 }
3805
3806 if (pcm_is_ready(pcm)) {
3807 int ret = pcm_prepare(pcm);
3808 if (ret < 0) {
3809 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3810 pcm_close(pcm);
3811 pcm = NULL;
3812 }
3813 }
3814
3815 return pcm;
3816}
3817
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003818int start_output_stream(struct stream_out *out)
3819{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003820 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003821 struct audio_usecase *uc_info;
3822 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003823 char mixer_ctl_name[128];
3824 struct mixer_ctl *ctl = NULL;
3825 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303826 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003827 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003828
Haynes Mathew George380745d2017-10-04 15:27:45 -07003829 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003830 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3831 ret = -EINVAL;
3832 goto error_config;
3833 }
3834
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003835 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303836 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003837 get_device_types(&out->device_list), is_haptic_usecase);
3838
3839 bool is_speaker_active = compare_device_type(&out->device_list,
3840 AUDIO_DEVICE_OUT_SPEAKER);
3841 bool is_speaker_safe_active = compare_device_type(&out->device_list,
3842 AUDIO_DEVICE_OUT_SPEAKER_SAFE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303843
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303844 if (CARD_STATUS_OFFLINE == out->card_status ||
3845 CARD_STATUS_OFFLINE == adev->card_status) {
3846 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303847 ret = -EIO;
Mingshu Pang5fc696f2020-02-28 12:32:00 +08003848 goto error_fatal;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303849 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303850
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003851 //Update incall music usecase to reflect correct voice session
3852 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3853 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
3854 if (ret != 0) {
3855 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3856 __func__, ret);
3857 goto error_config;
3858 }
3859 }
3860
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003861 if (is_a2dp_out_device_type(&out->device_list)) {
Florian Pfister1a84f312018-07-19 14:38:18 +02003862 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003863 if (is_speaker_active || is_speaker_safe_active) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303864 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303865 } else {
Zhou Songd01e7a22020-09-23 22:49:01 +08003866 if (!is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303867 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3868 ret = -EAGAIN;
3869 goto error_config;
3870 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303871 }
3872 }
3873 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003874 if (is_sco_out_device_type(&out->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303875 if (!adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003876 if (is_speaker_active) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303877 //combo usecase just by pass a2dp
3878 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003879 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303880 } else {
3881 ALOGE("%s: SCO profile is not ready, return error", __func__);
3882 ret = -EAGAIN;
3883 goto error_config;
3884 }
3885 }
3886 }
3887
Eric Laurentb23d5282013-05-14 15:27:20 -07003888 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003889 if (out->pcm_device_id < 0) {
3890 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3891 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003892 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003893 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003894 }
3895
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003896 if (is_haptic_usecase) {
Meng Wang51d8c2a2020-04-27 15:23:21 +08003897 adev->haptic_pcm_device_id = platform_get_pcm_device_id(
3898 USECASE_AUDIO_PLAYBACK_HAPTICS, PCM_PLAYBACK);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003899 if (adev->haptic_pcm_device_id < 0) {
3900 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
3901 __func__, adev->haptic_pcm_device_id, out->usecase);
3902 ret = -EINVAL;
3903 goto error_config;
3904 }
3905 }
3906
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003907 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003908
3909 if (!uc_info) {
3910 ret = -ENOMEM;
3911 goto error_config;
3912 }
3913
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003914 uc_info->id = out->usecase;
3915 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003916 uc_info->stream.out = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003917 list_init(&uc_info->device_list);
3918 assign_devices(&uc_info->device_list, &out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003919 uc_info->in_snd_device = SND_DEVICE_NONE;
3920 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003921
3922 /* This must be called before adding this usecase to the list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003923 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003924 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3925 /* USB backend is not reopened immediately.
3926 This is eventually done as part of select_devices */
3927 }
3928
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003929 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003930
Wei Wangf7ca6c92017-11-21 14:51:20 -08003931 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303932 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3933 adev->perf_lock_opts,
3934 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303935
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003936 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303937 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303938 if (audio_extn_passthru_is_enabled() &&
3939 audio_extn_passthru_is_passthrough_stream(out)) {
3940 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303941 }
3942 }
3943
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003944 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003945 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303946 if (!a2dp_combo) {
3947 check_a2dp_restore_l(adev, out, false);
3948 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003949 struct listnode dev;
3950 list_init(&dev);
3951 assign_devices(&dev, &out->device_list);
3952 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
3953 reassign_device_list(&out->device_list,
3954 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aalique Grahame22e49102018-12-18 14:23:57 -08003955 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003956 reassign_device_list(&out->device_list,
3957 AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303958 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003959 assign_devices(&out->device_list, &dev);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303960 }
3961 } else {
Revathi Uddarajub26e3932020-06-10 14:51:02 +05303962 select_devices(adev, out->usecase);
3963 if (is_a2dp_out_device_type(&out->device_list) &&
3964 !adev->a2dp_started) {
3965 if (is_speaker_active || is_speaker_safe_active) {
3966 struct listnode dev;
3967 list_init(&dev);
3968 assign_devices(&dev, &out->device_list);
3969 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
3970 reassign_device_list(&out->device_list,
3971 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
3972 else
3973 reassign_device_list(&out->device_list,
3974 AUDIO_DEVICE_OUT_SPEAKER, "");
3975 select_devices(adev, out->usecase);
3976 assign_devices(&out->device_list, &dev);
3977 } else {
3978 ret = -EINVAL;
3979 goto error_open;
3980 }
3981 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303982 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003983
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003984 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3985 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003986 voice_set_device_mute_flag(adev, true);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003987 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003988
Derek Chenea197282019-01-07 17:35:01 -08003989 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3990 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003991
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003992 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3993 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003994
3995 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07003996 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07003997 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3998 ALOGE("%s: pcm stream not ready", __func__);
3999 goto error_open;
4000 }
4001 ret = pcm_start(out->pcm);
4002 if (ret < 0) {
4003 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
4004 goto error_open;
4005 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07004006 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07004007 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004008 unsigned int flags = PCM_OUT;
4009 unsigned int pcm_open_retry_count = 0;
4010 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
4011 flags |= PCM_MMAP | PCM_NOIRQ;
4012 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004013 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08004014 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004015 } else
4016 flags |= PCM_MONOTONIC;
4017
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004018 if ((adev->vr_audio_mode_enabled) &&
4019 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
4020 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4021 "PCM_Dev %d Topology", out->pcm_device_id);
4022 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4023 if (!ctl) {
4024 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
4025 __func__, mixer_ctl_name);
4026 } else {
4027 //if success use ULLPP
4028 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
4029 __func__, mixer_ctl_name, out->pcm_device_id);
4030 //There is a still a possibility that some sessions
4031 // that request for FAST|RAW when 3D audio is active
4032 //can go through ULLPP. Ideally we expects apps to
4033 //listen to audio focus and stop concurrent playback
4034 //Also, we will look for mode flag (voice_in_communication)
4035 //before enabling the realtime flag.
4036 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
4037 }
4038 }
4039
Surendar Karka91fa3682018-07-02 18:12:12 +05304040 if (out->realtime)
4041 platform_set_stream_channel_map(adev->platform, out->channel_mask,
4042 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
4043
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004044 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
4045 flags, pcm_open_retry_count,
4046 &(out->config));
4047 if (out->pcm == NULL) {
4048 ret = -EIO;
4049 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004050 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004051
4052 if (is_haptic_usecase) {
4053 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
4054 adev->haptic_pcm_device_id,
4055 flags, pcm_open_retry_count,
4056 &(adev->haptics_config));
4057 // failure to open haptics pcm shouldnt stop audio,
4058 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07004059
4060 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
4061 ALOGD("%s: enable haptic audio synchronization", __func__);
4062 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
4063 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004064 }
4065
Surendar Karka91fa3682018-07-02 18:12:12 +05304066 if (!out->realtime)
4067 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Surendar Karkaf51b5842018-04-26 11:28:38 +05304068 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004069
Zhou Song2b8f28f2017-09-11 10:51:38 +08004070 // apply volume for voip playback after path is set up
4071 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
4072 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05304073 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
4074 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304075 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
4076 out->apply_volume = false;
Derek Chenf13dd492018-11-13 14:53:51 -08004077 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
4078 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304079 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004080 } else {
Zhou Song79929fe2020-01-20 17:57:43 +08004081 /*
4082 * set custom channel map if:
4083 * 1. neither mono nor stereo clips i.e. channels > 2 OR
4084 * 2. custom channel map has been set by client
4085 * else default channel map of FC/FR/FL can always be set to DSP
4086 */
4087 if (popcount(out->channel_mask) > 2 || out->channel_map_param.channel_map[0])
4088 platform_set_stream_channel_map(adev->platform, out->channel_mask,
4089 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08004090 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
4091 adev->dsp_bit_width_enforce_mode,
4092 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004093 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07004094 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004095 out->compr = compress_open(adev->snd_card,
4096 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004097 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004098 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05304099 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05304100 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
4101 adev->card_status = CARD_STATUS_OFFLINE;
4102 out->card_status = CARD_STATUS_OFFLINE;
4103 ret = -EIO;
4104 goto error_open;
4105 }
4106
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004107 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004108 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004109 compress_close(out->compr);
4110 out->compr = NULL;
4111 ret = -EIO;
4112 goto error_open;
4113 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304114 /* compress_open sends params of the track, so reset the flag here */
4115 out->is_compr_metadata_avail = false;
4116
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004117 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004118 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07004119
Fred Oh3f43e742015-03-04 18:42:34 -08004120 /* Since small bufs uses blocking writes, a write will be blocked
4121 for the default max poll time (20s) in the event of an SSR.
4122 Reduce the poll time to observe and deal with SSR faster.
4123 */
Ashish Jain5106d362016-05-11 19:23:33 +05304124 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08004125 compress_set_max_poll_wait(out->compr, 1000);
4126 }
4127
Manish Dewangan69426c82017-01-30 17:35:36 +05304128 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05304129 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05304130
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004131 audio_extn_dts_create_state_notifier_node(out->usecase);
4132 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4133 popcount(out->channel_mask),
4134 out->playback_started);
4135
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004136#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304137 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004138 audio_extn_dolby_send_ddp_endp_params(adev);
4139#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05304140 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
4141 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004142 if (adev->visualizer_start_output != NULL)
4143 adev->visualizer_start_output(out->handle, out->pcm_device_id);
4144 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05304145 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004146 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004147 }
Derek Chenf13dd492018-11-13 14:53:51 -08004148
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004149 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf13dd492018-11-13 14:53:51 -08004150 /* Update cached volume from media to offload/direct stream */
4151 struct listnode *node = NULL;
4152 list_for_each(node, &adev->active_outputs_list) {
4153 streams_output_ctxt_t *out_ctxt = node_to_item(node,
4154 streams_output_ctxt_t,
4155 list);
4156 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
4157 out->volume_l = out_ctxt->output->volume_l;
4158 out->volume_r = out_ctxt->output->volume_r;
4159 }
4160 }
4161 out_set_compr_volume(&out->stream,
4162 out->volume_l, out->volume_r);
4163 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004164 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004165
4166 if (ret == 0) {
4167 register_out_stream(out);
4168 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07004169 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4170 ALOGE("%s: pcm stream not ready", __func__);
4171 goto error_open;
4172 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004173 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004174 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004175 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004176 if (ret < 0)
4177 goto error_open;
4178 }
4179 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004180 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304181 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07004182 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004183
vivek mehtad15d2bf2019-05-17 13:35:10 -07004184 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
4185 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4186 audio_low_latency_hint_start();
4187 }
4188
Manish Dewangan21a850a2017-08-14 12:03:55 +05304189 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07004190 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07004191 if (ret < 0)
4192 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
4193 }
4194
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004195 // consider a scenario where on pause lower layers are tear down.
4196 // so on resume, swap mixer control need to be sent only when
4197 // backend is active, hence rather than sending from enable device
4198 // sending it from start of streamtream
4199
4200 platform_set_swap_channels(adev, true);
4201
Haynes Mathew George380745d2017-10-04 15:27:45 -07004202 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304203 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004204 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004205error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004206 if (adev->haptic_pcm) {
4207 pcm_close(adev->haptic_pcm);
4208 adev->haptic_pcm = NULL;
4209 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004210 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304211 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004212 stop_output_stream(out);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004213error_fatal:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05304214 /*
4215 * sleep 50ms to allow sufficient time for kernel
4216 * drivers to recover incases like SSR.
4217 */
4218 usleep(50000);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004219error_config:
Haynes Mathew George380745d2017-10-04 15:27:45 -07004220 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304221 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004222 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004223}
4224
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004225static int check_input_parameters(uint32_t sample_rate,
4226 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08004227 int channel_count,
4228 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004229{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004230 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004231
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304232 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
4233 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
4234 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07004235 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02004236 !audio_extn_compr_cap_format_supported(format) &&
4237 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004238 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004239
Aalique Grahame22e49102018-12-18 14:23:57 -08004240 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
4241 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
4242 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
4243 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
4244 return -EINVAL;
4245 }
4246
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004247 switch (channel_count) {
4248 case 1:
4249 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304250 case 3:
4251 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004252 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07004253 case 8:
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05304254 case 10:
4255 case 12:
4256 case 14:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004257 break;
4258 default:
4259 ret = -EINVAL;
4260 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004261
4262 switch (sample_rate) {
4263 case 8000:
4264 case 11025:
4265 case 12000:
4266 case 16000:
4267 case 22050:
4268 case 24000:
4269 case 32000:
4270 case 44100:
4271 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004272 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304273 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004274 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304275 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004276 break;
4277 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004278 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004279 }
4280
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004281 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004282}
4283
Naresh Tanniru04f71882018-06-26 17:46:22 +05304284
4285/** Add a value in a list if not already present.
4286 * @return true if value was successfully inserted or already present,
4287 * false if the list is full and does not contain the value.
4288 */
4289static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
4290 for (size_t i = 0; i < list_length; i++) {
4291 if (list[i] == value) return true; // value is already present
4292 if (list[i] == 0) { // no values in this slot
4293 list[i] = value;
4294 return true; // value inserted
4295 }
4296 }
4297 return false; // could not insert value
4298}
4299
4300/** Add channel_mask in supported_channel_masks if not already present.
4301 * @return true if channel_mask was successfully inserted or already present,
4302 * false if supported_channel_masks is full and does not contain channel_mask.
4303 */
4304static void register_channel_mask(audio_channel_mask_t channel_mask,
4305 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
4306 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
4307 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
4308}
4309
4310/** Add format in supported_formats if not already present.
4311 * @return true if format was successfully inserted or already present,
4312 * false if supported_formats is full and does not contain format.
4313 */
4314static void register_format(audio_format_t format,
4315 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
4316 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
4317 "%s: stream can not declare supporting its format %x", __func__, format);
4318}
4319/** Add sample_rate in supported_sample_rates if not already present.
4320 * @return true if sample_rate was successfully inserted or already present,
4321 * false if supported_sample_rates is full and does not contain sample_rate.
4322 */
4323static void register_sample_rate(uint32_t sample_rate,
4324 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
4325 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
4326 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
4327}
4328
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004329static inline uint32_t lcm(uint32_t num1, uint32_t num2)
4330{
4331 uint32_t high = num1, low = num2, temp = 0;
4332
4333 if (!num1 || !num2)
4334 return 0;
4335
4336 if (num1 < num2) {
4337 high = num2;
4338 low = num1;
4339 }
4340
4341 while (low != 0) {
4342 temp = low;
4343 low = high % low;
4344 high = temp;
4345 }
4346 return (num1 * num2)/high;
4347}
4348
4349static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
4350{
4351 uint32_t remainder = 0;
4352
4353 if (!multiplier)
4354 return num;
4355
4356 remainder = num % multiplier;
4357 if (remainder)
4358 num += (multiplier - remainder);
4359
4360 return num;
4361}
4362
Aalique Grahame22e49102018-12-18 14:23:57 -08004363static size_t get_stream_buffer_size(size_t duration_ms,
4364 uint32_t sample_rate,
4365 audio_format_t format,
4366 int channel_count,
4367 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004368{
4369 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004370 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004371
Aalique Grahame22e49102018-12-18 14:23:57 -08004372 size = (sample_rate * duration_ms) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004373 if (is_low_latency)
4374 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304375
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004376 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08004377 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004378
Ralf Herzbd08d632018-09-28 15:50:49 +02004379 /* make sure the size is multiple of 32 bytes and additionally multiple of
4380 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004381 * At 48 kHz mono 16-bit PCM:
4382 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
4383 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004384 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004385 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004386 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07004387
4388 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004389}
4390
Aalique Grahame22e49102018-12-18 14:23:57 -08004391static size_t get_input_buffer_size(uint32_t sample_rate,
4392 audio_format_t format,
4393 int channel_count,
4394 bool is_low_latency)
4395{
4396 /* Don't know if USB HIFI in this context so use true to be conservative */
4397 if (check_input_parameters(sample_rate, format, channel_count,
4398 true /*is_usb_hifi */) != 0)
4399 return 0;
4400
4401 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4402 sample_rate,
4403 format,
4404 channel_count,
4405 is_low_latency);
4406}
4407
Derek Chenf6318be2017-06-12 17:16:24 -04004408size_t get_output_period_size(uint32_t sample_rate,
4409 audio_format_t format,
4410 int channel_count,
4411 int duration /*in millisecs*/)
Ashish Jain058165c2016-09-28 23:18:48 +05304412{
4413 size_t size = 0;
4414 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
4415
4416 if ((duration == 0) || (sample_rate == 0) ||
4417 (bytes_per_sample == 0) || (channel_count == 0)) {
4418 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
4419 bytes_per_sample, channel_count);
4420 return -EINVAL;
4421 }
4422
4423 size = (sample_rate *
4424 duration *
4425 bytes_per_sample *
4426 channel_count) / 1000;
4427 /*
4428 * To have same PCM samples for all channels, the buffer size requires to
4429 * be multiple of (number of channels * bytes per sample)
4430 * For writes to succeed, the buffer must be written at address which is multiple of 32
4431 */
4432 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
4433
4434 return (size/(channel_count * bytes_per_sample));
4435}
4436
Zhou Song48453a02018-01-10 17:50:59 +08004437static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05304438{
4439 uint64_t actual_frames_rendered = 0;
Weiyin Jiang4813da12020-05-28 00:37:28 +08004440 uint64_t written_frames = 0;
4441 uint64_t kernel_frames = 0;
4442 uint64_t dsp_frames = 0;
4443 uint64_t signed_frames = 0;
4444 size_t kernel_buffer_size = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304445
4446 /* This adjustment accounts for buffering after app processor.
4447 * It is based on estimated DSP latency per use case, rather than exact.
4448 */
George Gao9ba8a142020-07-23 14:30:03 -07004449 dsp_frames = platform_render_latency(out) *
Weiyin Jiang4813da12020-05-28 00:37:28 +08004450 out->sample_rate / 1000000LL;
Ashish Jain5106d362016-05-11 19:23:33 +05304451
Zhou Song48453a02018-01-10 17:50:59 +08004452 pthread_mutex_lock(&out->position_query_lock);
Weiyin Jiang4813da12020-05-28 00:37:28 +08004453 written_frames = out->written /
4454 (audio_bytes_per_sample(out->hal_ip_format) * popcount(out->channel_mask));
4455
Ashish Jain5106d362016-05-11 19:23:33 +05304456 /* not querying actual state of buffering in kernel as it would involve an ioctl call
4457 * which then needs protection, this causes delay in TS query for pcm_offload usecase
4458 * hence only estimate.
4459 */
Weiyin Jiang4813da12020-05-28 00:37:28 +08004460 kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
4461 kernel_frames = kernel_buffer_size /
4462 (audio_bytes_per_sample(out->hal_op_format) * popcount(out->channel_mask));
Ashish Jain5106d362016-05-11 19:23:33 +05304463
Weiyin Jiang4813da12020-05-28 00:37:28 +08004464 if (written_frames >= (kernel_frames + dsp_frames))
4465 signed_frames = written_frames - kernel_frames - dsp_frames;
Ashish Jain5106d362016-05-11 19:23:33 +05304466
Zhou Song48453a02018-01-10 17:50:59 +08004467 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05304468 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08004469 if (timestamp != NULL )
4470 *timestamp = out->writeAt;
4471 } else if (timestamp != NULL) {
4472 clock_gettime(CLOCK_MONOTONIC, timestamp);
4473 }
4474 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304475
Weiyin Jiang4813da12020-05-28 00:37:28 +08004476 ALOGVV("%s signed frames %lld written frames %lld kernel frames %lld dsp frames %lld",
4477 __func__, signed_frames, written_frames, kernel_frames, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05304478
4479 return actual_frames_rendered;
4480}
4481
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004482static uint32_t out_get_sample_rate(const struct audio_stream *stream)
4483{
4484 struct stream_out *out = (struct stream_out *)stream;
4485
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004486 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004487}
4488
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004489static int out_set_sample_rate(struct audio_stream *stream __unused,
4490 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004491{
4492 return -ENOSYS;
4493}
4494
4495static size_t out_get_buffer_size(const struct audio_stream *stream)
4496{
4497 struct stream_out *out = (struct stream_out *)stream;
4498
Varun Balaraje49253e2017-07-06 19:48:56 +05304499 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05304500 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05304501 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304502 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4503 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
4504 else
4505 return out->compr_config.fragment_size;
4506 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004507 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304508 else if (is_offload_usecase(out->usecase) &&
4509 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304510 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004511
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004512 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004513 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004514}
4515
4516static uint32_t out_get_channels(const struct audio_stream *stream)
4517{
4518 struct stream_out *out = (struct stream_out *)stream;
4519
4520 return out->channel_mask;
4521}
4522
4523static audio_format_t out_get_format(const struct audio_stream *stream)
4524{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004525 struct stream_out *out = (struct stream_out *)stream;
4526
4527 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004528}
4529
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004530static int out_set_format(struct audio_stream *stream __unused,
4531 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004532{
4533 return -ENOSYS;
4534}
4535
4536static int out_standby(struct audio_stream *stream)
4537{
4538 struct stream_out *out = (struct stream_out *)stream;
4539 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07004540 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004541
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304542 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4543 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004544
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004545 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004546 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004547 if (adev->adm_deregister_stream)
4548 adev->adm_deregister_stream(adev->adm_data, out->handle);
4549
Weiyin Jiang280ea742020-09-08 20:28:22 +08004550 if (is_offload_usecase(out->usecase)) {
4551 pthread_mutex_lock(&out->latch_lock);
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004552 stop_compressed_output_l(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08004553 pthread_mutex_unlock(&out->latch_lock);
4554 }
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004555
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004556 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004557 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004558 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4559 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304560 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08004561 pthread_mutex_unlock(&adev->lock);
4562 pthread_mutex_unlock(&out->lock);
4563 ALOGD("VOIP output entered standby");
4564 return 0;
4565 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004566 if (out->pcm) {
4567 pcm_close(out->pcm);
4568 out->pcm = NULL;
4569 }
Meng Wanga09da002020-04-20 12:56:04 +08004570 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4571 if (adev->haptic_pcm) {
4572 pcm_close(adev->haptic_pcm);
4573 adev->haptic_pcm = NULL;
4574 }
4575
4576 if (adev->haptic_buffer != NULL) {
4577 free(adev->haptic_buffer);
4578 adev->haptic_buffer = NULL;
4579 adev->haptic_buffer_size = 0;
4580 }
4581 adev->haptic_pcm_device_id = 0;
4582 }
4583
Haynes Mathew George16081042017-05-31 17:16:49 -07004584 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4585 do_stop = out->playback_started;
4586 out->playback_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07004587
4588 if (out->mmap_shared_memory_fd >= 0) {
4589 ALOGV("%s: closing mmap_shared_memory_fd = %d",
4590 __func__, out->mmap_shared_memory_fd);
4591 close(out->mmap_shared_memory_fd);
4592 out->mmap_shared_memory_fd = -1;
4593 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004594 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004595 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004596 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304597 out->send_next_track_params = false;
4598 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004599 out->gapless_mdata.encoder_delay = 0;
4600 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004601 if (out->compr != NULL) {
4602 compress_close(out->compr);
4603 out->compr = NULL;
4604 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004605 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004606 if (do_stop) {
4607 stop_output_stream(out);
4608 }
Lakshman Chaluvaraju06677b42019-06-24 10:04:52 +05304609 // if fm is active route on selected device in UI
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004610 audio_extn_fm_route_on_selected_device(adev, &out->device_list);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004611 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004612 }
4613 pthread_mutex_unlock(&out->lock);
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07004614 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004615 return 0;
4616}
4617
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304618static int out_on_error(struct audio_stream *stream)
4619{
4620 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004621 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304622
4623 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004624 // always send CMD_ERROR for offload streams, this
4625 // is needed e.g. when SSR happens within compress_open
4626 // since the stream is active, offload_callback_thread is also active.
4627 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Weiyin Jiang280ea742020-09-08 20:28:22 +08004628 pthread_mutex_lock(&out->latch_lock);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004629 stop_compressed_output_l(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08004630 pthread_mutex_unlock(&out->latch_lock);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004631 }
4632 pthread_mutex_unlock(&out->lock);
4633
4634 status = out_standby(&out->stream.common);
4635
4636 lock_output_stream(out);
4637 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004638 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304639 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05304640
4641 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
4642 ALOGD("Setting previous card status if offline");
4643 out->prev_card_status_offline = true;
4644 }
4645
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304646 pthread_mutex_unlock(&out->lock);
4647
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004648 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304649}
4650
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304651/*
Weiyin Jiang280ea742020-09-08 20:28:22 +08004652 * standby implementation without locks, assumes that the callee already
4653 * has taken adev and out lock.
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304654 */
4655int out_standby_l(struct audio_stream *stream)
4656{
4657 struct stream_out *out = (struct stream_out *)stream;
4658 struct audio_device *adev = out->dev;
4659
4660 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4661 stream, out->usecase, use_case_table[out->usecase]);
4662
4663 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07004664 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304665 if (adev->adm_deregister_stream)
4666 adev->adm_deregister_stream(adev->adm_data, out->handle);
4667
Weiyin Jiang280ea742020-09-08 20:28:22 +08004668 if (is_offload_usecase(out->usecase)) {
4669 pthread_mutex_lock(&out->latch_lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304670 stop_compressed_output_l(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08004671 pthread_mutex_unlock(&out->latch_lock);
4672 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304673
4674 out->standby = true;
4675 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4676 voice_extn_compress_voip_close_output_stream(stream);
4677 out->started = 0;
4678 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07004679 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304680 return 0;
4681 } else if (!is_offload_usecase(out->usecase)) {
4682 if (out->pcm) {
4683 pcm_close(out->pcm);
4684 out->pcm = NULL;
4685 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004686 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4687 if (adev->haptic_pcm) {
4688 pcm_close(adev->haptic_pcm);
4689 adev->haptic_pcm = NULL;
4690 }
4691
4692 if (adev->haptic_buffer != NULL) {
4693 free(adev->haptic_buffer);
4694 adev->haptic_buffer = NULL;
4695 adev->haptic_buffer_size = 0;
4696 }
4697 adev->haptic_pcm_device_id = 0;
4698 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304699 } else {
4700 ALOGD("copl(%p):standby", out);
4701 out->send_next_track_params = false;
4702 out->is_compr_metadata_avail = false;
4703 out->gapless_mdata.encoder_delay = 0;
4704 out->gapless_mdata.encoder_padding = 0;
4705 if (out->compr != NULL) {
4706 compress_close(out->compr);
4707 out->compr = NULL;
4708 }
4709 }
4710 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004711 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304712 }
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07004713 ALOGV("%s: exit", __func__);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304714 return 0;
4715}
4716
Aalique Grahame22e49102018-12-18 14:23:57 -08004717static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004718{
Aalique Grahame22e49102018-12-18 14:23:57 -08004719 struct stream_out *out = (struct stream_out *)stream;
4720
4721 // We try to get the lock for consistency,
4722 // but it isn't necessary for these variables.
4723 // If we're not in standby, we may be blocked on a write.
4724 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
4725 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
4726 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
4727
Andy Hunga1f48fa2019-07-01 18:14:53 -07004728 char buffer[256]; // for statistics formatting
4729 if (!is_offload_usecase(out->usecase)) {
4730 simple_stats_to_string(&out->fifo_underruns, buffer, sizeof(buffer));
4731 dprintf(fd, " Fifo frame underruns: %s\n", buffer);
4732 }
4733
Andy Hungc6bfd4a2019-07-01 18:26:00 -07004734 if (out->start_latency_ms.n > 0) {
4735 simple_stats_to_string(&out->start_latency_ms, buffer, sizeof(buffer));
4736 dprintf(fd, " Start latency ms: %s\n", buffer);
4737 }
4738
Aalique Grahame22e49102018-12-18 14:23:57 -08004739 if (locked) {
4740 pthread_mutex_unlock(&out->lock);
4741 }
4742
4743 // dump error info
4744 (void)error_log_dump(
4745 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
4746
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004747 return 0;
4748}
4749
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004750static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
4751{
4752 int ret = 0;
4753 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08004754
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004755 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004756 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004757 return -EINVAL;
4758 }
4759
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304760 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08004761
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004762 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
4763 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304764 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004765 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004766 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
4767 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304768 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004769 }
4770
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004771 ALOGV("%s new encoder delay %u and padding %u", __func__,
4772 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
4773
4774 return 0;
4775}
4776
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004777static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
4778{
4779 return out == adev->primary_output || out == adev->voice_tx_output;
4780}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004781
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304782// note: this call is safe only if the stream_cb is
4783// removed first in close_output_stream (as is done now).
4784static void out_snd_mon_cb(void * stream, struct str_parms * parms)
4785{
4786 if (!stream || !parms)
4787 return;
4788
4789 struct stream_out *out = (struct stream_out *)stream;
4790 struct audio_device *adev = out->dev;
4791
4792 card_status_t status;
4793 int card;
4794 if (parse_snd_card_status(parms, &card, &status) < 0)
4795 return;
4796
4797 pthread_mutex_lock(&adev->lock);
4798 bool valid_cb = (card == adev->snd_card);
4799 pthread_mutex_unlock(&adev->lock);
4800
4801 if (!valid_cb)
4802 return;
4803
4804 lock_output_stream(out);
4805 if (out->card_status != status)
4806 out->card_status = status;
4807 pthread_mutex_unlock(&out->lock);
4808
4809 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
4810 use_case_table[out->usecase],
4811 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4812
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304813 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304814 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304815 if (voice_is_call_state_active(adev) &&
4816 out == adev->primary_output) {
4817 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
4818 pthread_mutex_lock(&adev->lock);
4819 voice_stop_call(adev);
4820 adev->mode = AUDIO_MODE_NORMAL;
4821 pthread_mutex_unlock(&adev->lock);
4822 }
4823 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304824 return;
4825}
4826
Kevin Rocardfce19002017-08-07 19:21:36 -07004827static int get_alive_usb_card(struct str_parms* parms) {
4828 int card;
4829 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
4830 !audio_extn_usb_alive(card)) {
4831 return card;
4832 }
4833 return -ENODEV;
4834}
4835
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004836int route_output_stream(struct stream_out *out,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004837 struct listnode *devices)
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004838{
4839 struct audio_device *adev = out->dev;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004840 int ret = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004841 struct listnode new_devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004842 bool bypass_a2dp = false;
4843 bool reconfig = false;
4844 unsigned long service_interval = 0;
4845
4846 ALOGD("%s: enter: usecase(%d: %s) devices %x",
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004847 __func__, out->usecase, use_case_table[out->usecase], get_device_types(devices));
4848
4849 list_init(&new_devices);
4850 assign_devices(&new_devices, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004851
4852 lock_output_stream(out);
4853 pthread_mutex_lock(&adev->lock);
4854
4855 /*
4856 * When HDMI cable is unplugged the music playback is paused and
4857 * the policy manager sends routing=0. But the audioflinger continues
4858 * to write data until standby time (3sec). As the HDMI core is
4859 * turned off, the write gets blocked.
4860 * Avoid this by routing audio to speaker until standby.
4861 */
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08004862 if (is_single_device_type_equal(&out->device_list,
4863 AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004864 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004865 !audio_extn_passthru_is_passthrough_stream(out) &&
4866 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004867 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004868 }
4869 /*
4870 * When A2DP is disconnected the
4871 * music playback is paused and the policy manager sends routing=0
4872 * But the audioflinger continues to write data until standby time
4873 * (3sec). As BT is turned off, the write gets blocked.
4874 * Avoid this by routing audio to speaker until standby.
4875 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004876 if (is_a2dp_out_device_type(&out->device_list) &&
4877 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004878 !audio_extn_a2dp_source_is_ready() &&
4879 !adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004880 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004881 }
4882 /*
4883 * When USB headset is disconnected the music platback paused
4884 * and the policy manager send routing=0. But if the USB is connected
4885 * back before the standby time, AFE is not closed and opened
4886 * when USB is connected back. So routing to speker will guarantee
4887 * AFE reconfiguration and AFE will be opend once USB is connected again
4888 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004889 if (is_usb_out_device_type(&out->device_list) &&
4890 list_empty(&new_devices) &&
4891 !audio_extn_usb_connected(NULL)) {
4892 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
4893 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004894 /* To avoid a2dp to sco overlapping / BT device improper state
4895 * check with BT lib about a2dp streaming support before routing
4896 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004897 if (is_a2dp_out_device_type(&new_devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004898 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004899 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER) ||
4900 compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004901 //combo usecase just by pass a2dp
4902 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
4903 bypass_a2dp = true;
4904 } else {
4905 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
4906 /* update device to a2dp and don't route as BT returned error
4907 * However it is still possible a2dp routing called because
4908 * of current active device disconnection (like wired headset)
4909 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004910 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004911 pthread_mutex_unlock(&adev->lock);
4912 pthread_mutex_unlock(&out->lock);
4913 goto error;
4914 }
4915 }
4916 }
4917
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004918 // Workaround: If routing to an non existing usb device, fail gracefully
4919 // The routing request will otherwise block during 10 second
4920 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004921 if (is_usb_out_device_type(&new_devices)) {
4922 struct str_parms *parms =
4923 str_parms_create_str(get_usb_device_address(&new_devices));
4924 if (!parms)
4925 goto error;
4926 if ((card = get_alive_usb_card(parms)) >= 0) {
4927 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
4928 pthread_mutex_unlock(&adev->lock);
4929 pthread_mutex_unlock(&out->lock);
4930 str_parms_destroy(parms);
4931 ret = -ENOSYS;
4932 goto error;
4933 }
4934 str_parms_destroy(parms);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004935 }
4936
Weiyin Jiang80c8f9a2020-01-10 20:42:08 +08004937 // Workaround: If routing to an non existing hdmi device, fail gracefully
4938 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4939 (platform_get_edid_info_v2(adev->platform,
4940 out->extconn.cs.controller,
4941 out->extconn.cs.stream) != 0)) {
4942 ALOGW("out_set_parameters() ignoring rerouting to non existing HDMI/DP");
4943 pthread_mutex_unlock(&adev->lock);
4944 pthread_mutex_unlock(&out->lock);
4945 ret = -ENOSYS;
4946 goto error;
4947 }
4948
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004949 /*
4950 * select_devices() call below switches all the usecases on the same
4951 * backend to the new device. Refer to check_usecases_codec_backend() in
4952 * the select_devices(). But how do we undo this?
4953 *
4954 * For example, music playback is active on headset (deep-buffer usecase)
4955 * and if we go to ringtones and select a ringtone, low-latency usecase
4956 * will be started on headset+speaker. As we can't enable headset+speaker
4957 * and headset devices at the same time, select_devices() switches the music
4958 * playback to headset+speaker while starting low-lateny usecase for ringtone.
4959 * So when the ringtone playback is completed, how do we undo the same?
4960 *
4961 * We are relying on the out_set_parameters() call on deep-buffer output,
4962 * once the ringtone playback is ended.
4963 * NOTE: We should not check if the current devices are same as new devices.
4964 * Because select_devices() must be called to switch back the music
4965 * playback to headset.
4966 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004967 if (!list_empty(&new_devices)) {
4968 bool same_dev = compare_devices(&out->device_list, &new_devices);
4969 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004970
4971 if (output_drives_call(adev, out)) {
4972 if (!voice_is_call_state_active(adev)) {
4973 if (adev->mode == AUDIO_MODE_IN_CALL) {
4974 adev->current_call_output = out;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004975 ret = voice_start_call(adev);
4976 }
4977 } else {
4978 adev->current_call_output = out;
4979 voice_update_devices_for_all_voice_usecases(adev);
4980 }
4981 }
4982
Mingshu Pang971ff702020-09-09 15:28:22 +08004983 if (is_usb_out_device_type(&out->device_list)) {
4984 service_interval = audio_extn_usb_find_service_interval(false, true /*playback*/);
4985 audio_extn_usb_set_service_interval(true /*playback*/,
4986 service_interval,
4987 &reconfig);
4988 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
4989 }
4990
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004991 if (!out->standby) {
4992 if (!same_dev) {
4993 ALOGV("update routing change");
4994 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4995 adev->perf_lock_opts,
4996 adev->perf_lock_opts_size);
4997 if (adev->adm_on_routing_change)
4998 adev->adm_on_routing_change(adev->adm_data,
4999 out->handle);
5000 }
5001 if (!bypass_a2dp) {
5002 select_devices(adev, out->usecase);
5003 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005004 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
5005 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005006 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005007 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005008 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005009 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005010 }
5011
5012 if (!same_dev) {
5013 // on device switch force swap, lower functions will make sure
5014 // to check if swap is allowed or not.
5015 platform_set_swap_channels(adev, true);
5016 audio_extn_perf_lock_release(&adev->perf_lock_handle);
5017 }
Zhou Songd01e7a22020-09-23 22:49:01 +08005018 if (is_offload_usecase(out->usecase) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005019 (!is_a2dp_out_device_type(&out->device_list) || audio_extn_a2dp_source_is_ready())) {
Weiyin Jiang280ea742020-09-08 20:28:22 +08005020 pthread_mutex_lock(&out->latch_lock);
5021 if (out->a2dp_compress_mute) {
5022 out->a2dp_compress_mute = false;
5023 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5024 }
5025 pthread_mutex_unlock(&out->latch_lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005026 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
5027 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
5028 }
5029 }
5030 }
5031
5032 pthread_mutex_unlock(&adev->lock);
5033 pthread_mutex_unlock(&out->lock);
5034
5035 /*handles device and call state changes*/
5036 audio_extn_extspk_update(adev->extspk);
5037
5038error:
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005039 ALOGV("%s: exit: code(%d)", __func__, ret);
5040 return ret;
5041}
5042
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005043static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
5044{
5045 struct stream_out *out = (struct stream_out *)stream;
5046 struct audio_device *adev = out->dev;
5047 struct str_parms *parms;
5048 char value[32];
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005049 int ret = 0, err;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005050 int ext_controller = -1;
5051 int ext_stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005052
sangwoobc677242013-08-08 16:53:43 +09005053 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005054 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005055 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305056 if (!parms)
5057 goto error;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005058
5059 err = platform_get_controller_stream_from_params(parms, &ext_controller,
5060 &ext_stream);
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08005061 if (err == 0) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005062 out->extconn.cs.controller = ext_controller;
5063 out->extconn.cs.stream = ext_stream;
5064 ALOGD("%s: usecase(%s) new controller/stream (%d/%d)", __func__,
5065 use_case_table[out->usecase], out->extconn.cs.controller,
5066 out->extconn.cs.stream);
5067 }
5068
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005069 if (out == adev->primary_output) {
5070 pthread_mutex_lock(&adev->lock);
5071 audio_extn_set_parameters(adev, parms);
5072 pthread_mutex_unlock(&adev->lock);
5073 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005074 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005075 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005076 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005077
5078 audio_extn_dts_create_state_notifier_node(out->usecase);
5079 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5080 popcount(out->channel_mask),
5081 out->playback_started);
5082
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08005083 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005084 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005085
Surendar Karkaf51b5842018-04-26 11:28:38 +05305086 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
5087 sizeof(value));
5088 if (err >= 0) {
5089 if (!strncmp("true", value, sizeof("true")) || atoi(value))
5090 audio_extn_send_dual_mono_mixing_coefficients(out);
5091 }
5092
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305093 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5094 if (err >= 0) {
5095 strlcpy(out->profile, value, sizeof(out->profile));
5096 ALOGV("updating stream profile with value '%s'", out->profile);
5097 lock_output_stream(out);
5098 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
5099 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005100 &out->device_list, out->flags,
5101 out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305102 out->sample_rate, out->bit_width,
5103 out->channel_mask, out->profile,
5104 &out->app_type_cfg);
5105 pthread_mutex_unlock(&out->lock);
5106 }
5107
Alexy Joseph98988832017-01-13 14:56:59 -08005108 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005109 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
5110 // and vendor.audio.hal.output.suspend.supported is set to true
5111 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08005112 //check suspend parameter only for low latency and if the property
5113 //is enabled
5114 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
5115 ALOGI("%s: got suspend_playback %s", __func__, value);
5116 lock_output_stream(out);
5117 if (!strncmp(value, "false", 5)) {
5118 //suspend_playback=false is supposed to set QOS value back to 75%
5119 //the mixer control sent with value Enable will achieve that
5120 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5121 } else if (!strncmp (value, "true", 4)) {
5122 //suspend_playback=true is supposed to remove QOS value
5123 //resetting the mixer control will set the default value
5124 //for the mixer control which is Disable and this removes the QOS vote
5125 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5126 } else {
5127 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
5128 " got %s", __func__, value);
5129 ret = -1;
5130 }
5131
5132 if (ret != 0) {
5133 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
5134 __func__, out->pm_qos_mixer_path, ret);
5135 }
5136
5137 pthread_mutex_unlock(&out->lock);
5138 }
5139 }
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005140
Alexy Joseph98988832017-01-13 14:56:59 -08005141 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005142 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305143error:
Eric Laurent994a6932013-07-17 11:51:42 -07005144 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005145 return ret;
5146}
5147
Paul McLeana50b7332018-12-17 08:24:21 -07005148static int in_set_microphone_direction(const struct audio_stream_in *stream,
5149 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07005150 struct stream_in *in = (struct stream_in *)stream;
5151
5152 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
5153
5154 in->direction = dir;
5155
5156 if (in->standby)
5157 return 0;
5158
5159 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07005160}
5161
5162static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07005163 struct stream_in *in = (struct stream_in *)stream;
5164
5165 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
5166
5167 if (zoom > 1.0 || zoom < -1.0)
5168 return -EINVAL;
5169
5170 in->zoom = zoom;
5171
5172 if (in->standby)
5173 return 0;
5174
5175 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07005176}
5177
5178
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005179static bool stream_get_parameter_channels(struct str_parms *query,
5180 struct str_parms *reply,
5181 audio_channel_mask_t *supported_channel_masks) {
5182 int ret = -1;
5183 char value[512];
5184 bool first = true;
5185 size_t i, j;
5186
5187 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
5188 ret = 0;
5189 value[0] = '\0';
5190 i = 0;
5191 while (supported_channel_masks[i] != 0) {
5192 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5193 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
5194 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305195 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005196
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305197 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005198 first = false;
5199 break;
5200 }
5201 }
5202 i++;
5203 }
5204 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5205 }
5206 return ret == 0;
5207}
5208
5209static bool stream_get_parameter_formats(struct str_parms *query,
5210 struct str_parms *reply,
5211 audio_format_t *supported_formats) {
5212 int ret = -1;
5213 char value[256];
5214 size_t i, j;
5215 bool first = true;
5216
5217 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
5218 ret = 0;
5219 value[0] = '\0';
5220 i = 0;
5221 while (supported_formats[i] != 0) {
5222 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5223 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
5224 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305225 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005226 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305227 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005228 first = false;
5229 break;
5230 }
5231 }
5232 i++;
5233 }
5234 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
5235 }
5236 return ret == 0;
5237}
5238
5239static bool stream_get_parameter_rates(struct str_parms *query,
5240 struct str_parms *reply,
5241 uint32_t *supported_sample_rates) {
5242
5243 int i;
5244 char value[256];
5245 int ret = -1;
5246 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
5247 ret = 0;
5248 value[0] = '\0';
5249 i=0;
5250 int cursor = 0;
5251 while (supported_sample_rates[i]) {
5252 int avail = sizeof(value) - cursor;
5253 ret = snprintf(value + cursor, avail, "%s%d",
5254 cursor > 0 ? "|" : "",
5255 supported_sample_rates[i]);
5256 if (ret < 0 || ret >= avail) {
5257 // if cursor is at the last element of the array
5258 // overwrite with \0 is duplicate work as
5259 // snprintf already put a \0 in place.
5260 // else
5261 // we had space to write the '|' at value[cursor]
5262 // (which will be overwritten) or no space to fill
5263 // the first element (=> cursor == 0)
5264 value[cursor] = '\0';
5265 break;
5266 }
5267 cursor += ret;
5268 ++i;
5269 }
5270 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
5271 value);
5272 }
5273 return ret >= 0;
5274}
5275
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005276static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
5277{
5278 struct stream_out *out = (struct stream_out *)stream;
5279 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005280 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005281 char value[256];
5282 struct str_parms *reply = str_parms_create();
5283 size_t i, j;
5284 int ret;
5285 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005286
5287 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005288 if (reply) {
5289 str_parms_destroy(reply);
5290 }
5291 if (query) {
5292 str_parms_destroy(query);
5293 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005294 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
5295 return NULL;
5296 }
5297
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005298 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005299 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
5300 if (ret >= 0) {
5301 value[0] = '\0';
5302 i = 0;
5303 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005304 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5305 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005306 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005307 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005308 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005309 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005310 first = false;
5311 break;
5312 }
5313 }
5314 i++;
5315 }
5316 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5317 str = str_parms_to_str(reply);
5318 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005319 voice_extn_out_get_parameters(out, query, reply);
5320 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005321 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005322
Alexy Joseph62142aa2015-11-16 15:10:34 -08005323
5324 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
5325 if (ret >= 0) {
5326 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05305327 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
5328 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08005329 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305330 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005331 } else {
5332 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05305333 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005334 }
5335 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005336 if (str)
5337 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08005338 str = str_parms_to_str(reply);
5339 }
5340
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005341 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
5342 if (ret >= 0) {
5343 value[0] = '\0';
5344 i = 0;
5345 first = true;
5346 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005347 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5348 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005349 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005350 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005351 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005352 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005353 first = false;
5354 break;
5355 }
5356 }
5357 i++;
5358 }
5359 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005360 if (str)
5361 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005362 str = str_parms_to_str(reply);
5363 }
Mingming Yin3a941d42016-02-17 18:08:05 -08005364
5365 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
5366 if (ret >= 0) {
5367 value[0] = '\0';
5368 i = 0;
5369 first = true;
5370 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005371 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
5372 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005373 if (!first) {
5374 strlcat(value, "|", sizeof(value));
5375 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005376 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08005377 first = false;
5378 break;
5379 }
5380 }
5381 i++;
5382 }
5383 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
5384 if (str)
5385 free(str);
5386 str = str_parms_to_str(reply);
5387 }
5388
Alexy Joseph98988832017-01-13 14:56:59 -08005389 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
5390 //only low latency track supports suspend_resume
5391 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005392 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08005393 if (str)
5394 free(str);
5395 str = str_parms_to_str(reply);
5396 }
5397
5398
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005399 str_parms_destroy(query);
5400 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07005401 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005402 return str;
5403}
5404
5405static uint32_t out_get_latency(const struct audio_stream_out *stream)
5406{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005407 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005408 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08005409 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005410
Alexy Josephaa54c872014-12-03 02:46:47 -08005411 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05305412 lock_output_stream(out);
5413 latency = audio_extn_utils_compress_get_dsp_latency(out);
5414 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005415 } else if ((out->realtime) ||
5416 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005417 // since the buffer won't be filled up faster than realtime,
5418 // return a smaller number
5419 if (out->config.rate)
5420 period_ms = (out->af_period_multiplier * out->config.period_size *
5421 1000) / (out->config.rate);
5422 else
5423 period_ms = 0;
George Gao9ba8a142020-07-23 14:30:03 -07005424 latency = period_ms + platform_render_latency(out) / 1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005425 } else {
5426 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005427 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08005428 }
5429
Zhou Songd2537a02020-06-11 22:04:46 +08005430 if (!out->standby && is_a2dp_out_device_type(&out->device_list))
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08005431 latency += audio_extn_a2dp_get_encoder_latency();
5432
Anish Kumar50ebcbf2014-12-09 04:01:39 +05305433 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08005434 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005435}
5436
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305437static float AmpToDb(float amplification)
5438{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305439 float db = DSD_VOLUME_MIN_DB;
5440 if (amplification > 0) {
5441 db = 20 * log10(amplification);
5442 if(db < DSD_VOLUME_MIN_DB)
5443 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305444 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305445 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305446}
5447
Arun Mirpuri5d170872019-03-26 13:21:31 -07005448static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
5449 float right)
5450{
5451 struct stream_out *out = (struct stream_out *)stream;
5452 long volume = 0;
5453 char mixer_ctl_name[128] = "";
5454 struct audio_device *adev = out->dev;
5455 struct mixer_ctl *ctl = NULL;
5456 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5457 PCM_PLAYBACK);
5458
5459 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5460 "Playback %d Volume", pcm_device_id);
5461 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5462 if (!ctl) {
5463 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5464 __func__, mixer_ctl_name);
5465 return -EINVAL;
5466 }
5467 if (left != right)
5468 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
5469 __func__, left, right);
5470 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
5471 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
5472 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
5473 __func__, mixer_ctl_name, volume);
5474 return -EINVAL;
5475 }
5476 return 0;
5477}
5478
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305479static int out_set_compr_volume(struct audio_stream_out *stream, float left,
5480 float right)
5481{
5482 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305483 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305484 char mixer_ctl_name[128];
5485 struct audio_device *adev = out->dev;
5486 struct mixer_ctl *ctl;
5487 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5488 PCM_PLAYBACK);
5489
5490 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5491 "Compress Playback %d Volume", pcm_device_id);
5492 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5493 if (!ctl) {
5494 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5495 __func__, mixer_ctl_name);
5496 return -EINVAL;
5497 }
5498 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
5499 __func__, mixer_ctl_name, left, right);
5500 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
5501 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
5502 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5503
5504 return 0;
5505}
5506
Zhou Song2b8f28f2017-09-11 10:51:38 +08005507static int out_set_voip_volume(struct audio_stream_out *stream, float left,
5508 float right)
5509{
5510 struct stream_out *out = (struct stream_out *)stream;
5511 char mixer_ctl_name[] = "App Type Gain";
5512 struct audio_device *adev = out->dev;
5513 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305514 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08005515
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07005516 if (!is_valid_volume(left, right)) {
5517 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
5518 __func__, left, right);
5519 return -EINVAL;
5520 }
5521
Zhou Song2b8f28f2017-09-11 10:51:38 +08005522 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5523 if (!ctl) {
5524 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5525 __func__, mixer_ctl_name);
5526 return -EINVAL;
5527 }
5528
5529 set_values[0] = 0; //0: Rx Session 1:Tx Session
5530 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305531 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
5532 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005533
5534 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
5535 return 0;
5536}
5537
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305538static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
5539 float right)
5540{
5541 struct stream_out *out = (struct stream_out *)stream;
5542 /* Volume control for pcm playback */
5543 if (left != right) {
5544 return -EINVAL;
5545 } else {
5546 char mixer_ctl_name[128];
5547 struct audio_device *adev = out->dev;
5548 struct mixer_ctl *ctl;
5549 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5550 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
5551 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5552 if (!ctl) {
5553 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5554 return -EINVAL;
5555 }
5556
5557 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
5558 int ret = mixer_ctl_set_value(ctl, 0, volume);
5559 if (ret < 0) {
5560 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
5561 return -EINVAL;
5562 }
5563
5564 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
5565
5566 return 0;
5567 }
5568}
5569
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005570static int out_set_volume(struct audio_stream_out *stream, float left,
5571 float right)
5572{
Eric Laurenta9024de2013-04-04 09:19:12 -07005573 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005574 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305575 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005576
Arun Mirpuri5d170872019-03-26 13:21:31 -07005577 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07005578 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
5579 /* only take left channel into account: the API is for stereo anyway */
Weiyin Jiang280ea742020-09-08 20:28:22 +08005580 pthread_mutex_lock(&out->latch_lock);
Eric Laurenta9024de2013-04-04 09:19:12 -07005581 out->muted = (left == 0.0f);
Weiyin Jiang280ea742020-09-08 20:28:22 +08005582 pthread_mutex_unlock(&out->latch_lock);
Eric Laurenta9024de2013-04-04 09:19:12 -07005583 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005584 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305585 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005586 /*
5587 * Set mute or umute on HDMI passthrough stream.
5588 * Only take left channel into account.
5589 * Mute is 0 and unmute 1
5590 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305591 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305592 } else if (out->format == AUDIO_FORMAT_DSD){
5593 char mixer_ctl_name[128] = "DSD Volume";
5594 struct audio_device *adev = out->dev;
5595 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5596
5597 if (!ctl) {
5598 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5599 __func__, mixer_ctl_name);
5600 return -EINVAL;
5601 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05305602 volume[0] = (long)(AmpToDb(left));
5603 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305604 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5605 return 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005606 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS) &&
Derek Chendf05eea2019-08-01 13:57:49 -07005607 (out->car_audio_stream == CAR_AUDIO_STREAM_MEDIA)) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005608 ALOGD("%s: Overriding offload set volume for media bus stream", __func__);
5609 struct listnode *node = NULL;
5610 list_for_each(node, &adev->active_outputs_list) {
5611 streams_output_ctxt_t *out_ctxt = node_to_item(node,
5612 streams_output_ctxt_t,
5613 list);
5614 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
5615 out->volume_l = out_ctxt->output->volume_l;
5616 out->volume_r = out_ctxt->output->volume_r;
5617 }
5618 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08005619 pthread_mutex_lock(&out->latch_lock);
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005620 if (!out->a2dp_compress_mute) {
5621 ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5622 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08005623 pthread_mutex_unlock(&out->latch_lock);
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005624 return ret;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005625 } else {
Weiyin Jiang280ea742020-09-08 20:28:22 +08005626 pthread_mutex_lock(&out->latch_lock);
Arun Mirpuri5d170872019-03-26 13:21:31 -07005627 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305628 if (!out->a2dp_compress_mute)
5629 ret = out_set_compr_volume(stream, left, right);
5630 out->volume_l = left;
5631 out->volume_r = right;
Weiyin Jiang280ea742020-09-08 20:28:22 +08005632 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305633 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005634 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005635 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005636 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
5637 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
5638 if (!out->standby) {
5639 audio_extn_utils_send_app_type_gain(out->dev,
5640 out->app_type_cfg.app_type,
5641 &out->app_type_cfg.gain[0]);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005642 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08005643 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08005644 out->volume_l = left;
5645 out->volume_r = right;
5646 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005647 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5648 ALOGV("%s: MMAP set volume called", __func__);
5649 if (!out->standby)
5650 ret = out_set_mmap_volume(stream, left, right);
5651 out->volume_l = left;
5652 out->volume_r = right;
5653 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305654 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05305655 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5656 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305657 /* Volume control for pcm playback */
5658 if (!out->standby)
5659 ret = out_set_pcm_volume(stream, left, right);
5660 else
5661 out->apply_volume = true;
5662
5663 out->volume_l = left;
5664 out->volume_r = right;
5665 return ret;
Derek Chenf13dd492018-11-13 14:53:51 -08005666 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
5667 ALOGV("%s: bus device set volume called", __func__);
5668 if (!out->standby)
5669 ret = out_set_pcm_volume(stream, left, right);
5670 out->volume_l = left;
5671 out->volume_r = right;
5672 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07005673 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005674
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005675 return -ENOSYS;
5676}
5677
Zhou Songc9672822017-08-16 16:01:39 +08005678static void update_frames_written(struct stream_out *out, size_t bytes)
5679{
5680 size_t bpf = 0;
5681
5682 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
5683 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
5684 bpf = 1;
5685 else if (!is_offload_usecase(out->usecase))
5686 bpf = audio_bytes_per_sample(out->format) *
5687 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08005688
5689 pthread_mutex_lock(&out->position_query_lock);
5690 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08005691 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08005692 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
5693 }
5694 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08005695}
5696
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005697int split_and_write_audio_haptic_data(struct stream_out *out,
5698 const void *buffer, size_t bytes_to_write)
5699{
5700 struct audio_device *adev = out->dev;
5701
5702 int ret = 0;
5703 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5704 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
5705 size_t frame_size = channel_count * bytes_per_sample;
5706 size_t frame_count = bytes_to_write / frame_size;
5707
5708 bool force_haptic_path =
5709 property_get_bool("vendor.audio.test_haptic", false);
5710
5711 // extract Haptics data from Audio buffer
5712 bool alloc_haptic_buffer = false;
5713 int haptic_channel_count = adev->haptics_config.channels;
5714 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
5715 size_t audio_frame_size = frame_size - haptic_frame_size;
5716 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
5717
5718 if (adev->haptic_buffer == NULL) {
5719 alloc_haptic_buffer = true;
5720 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
5721 free(adev->haptic_buffer);
5722 adev->haptic_buffer_size = 0;
5723 alloc_haptic_buffer = true;
5724 }
5725
5726 if (alloc_haptic_buffer) {
5727 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08005728 if(adev->haptic_buffer == NULL) {
5729 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
5730 return -ENOMEM;
5731 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005732 adev->haptic_buffer_size = total_haptic_buffer_size;
5733 }
5734
5735 size_t src_index = 0, aud_index = 0, hap_index = 0;
5736 uint8_t *audio_buffer = (uint8_t *)buffer;
5737 uint8_t *haptic_buffer = adev->haptic_buffer;
5738
5739 // This is required for testing only. This works for stereo data only.
5740 // One channel is fed to audio stream and other to haptic stream for testing.
5741 if (force_haptic_path)
5742 audio_frame_size = haptic_frame_size = bytes_per_sample;
5743
5744 for (size_t i = 0; i < frame_count; i++) {
5745 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
5746 audio_frame_size);
5747 aud_index += audio_frame_size;
5748 src_index += audio_frame_size;
5749
5750 if (adev->haptic_pcm)
5751 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
5752 haptic_frame_size);
5753 hap_index += haptic_frame_size;
5754 src_index += haptic_frame_size;
5755
5756 // This is required for testing only.
5757 // Discard haptic channel data.
5758 if (force_haptic_path)
5759 src_index += haptic_frame_size;
5760 }
5761
5762 // write to audio pipeline
5763 ret = pcm_write(out->pcm, (void *)audio_buffer,
5764 frame_count * audio_frame_size);
5765
5766 // write to haptics pipeline
5767 if (adev->haptic_pcm)
5768 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
5769 frame_count * haptic_frame_size);
5770
5771 return ret;
5772}
5773
Aalique Grahame22e49102018-12-18 14:23:57 -08005774#ifdef NO_AUDIO_OUT
5775static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
5776 const void *buffer __unused, size_t bytes)
5777{
5778 struct stream_out *out = (struct stream_out *)stream;
5779
5780 /* No Output device supported other than BT for playback.
5781 * Sleep for the amount of buffer duration
5782 */
5783 lock_output_stream(out);
5784 usleep(bytes * 1000000 / audio_stream_out_frame_size(
5785 (const struct audio_stream_out *)&out->stream) /
5786 out_get_sample_rate(&out->stream.common));
5787 pthread_mutex_unlock(&out->lock);
5788 return bytes;
5789}
5790#endif
5791
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005792static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
5793 size_t bytes)
5794{
5795 struct stream_out *out = (struct stream_out *)stream;
5796 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07005797 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305798 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005799 const size_t frame_size = audio_stream_out_frame_size(stream);
5800 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305801 struct audio_usecase *usecase = NULL;
Meng Wang4c32fb42020-01-16 17:57:11 +08005802 uint32_t compr_passthr = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005803
Haynes Mathew George380745d2017-10-04 15:27:45 -07005804 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005805 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305806
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305807 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08005808
Dhananjay Kumarac341582017-02-23 23:42:25 +05305809 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305810 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05305811 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
5812 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005813 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305814 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05305815 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05305816 ALOGD(" %s: sound card is not active/SSR state", __func__);
5817 ret= -EIO;
5818 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305819 }
5820 }
5821
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305822 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305823 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305824 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305825 goto exit;
5826 }
5827
Haynes Mathew George16081042017-05-31 17:16:49 -07005828 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5829 ret = -EINVAL;
5830 goto exit;
5831 }
5832
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005833 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305834 !out->is_iec61937_info_available) {
5835
5836 if (!audio_extn_passthru_is_passthrough_stream(out)) {
5837 out->is_iec61937_info_available = true;
5838 } else if (audio_extn_passthru_is_enabled()) {
5839 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05305840 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05305841
5842 if((out->format == AUDIO_FORMAT_DTS) ||
5843 (out->format == AUDIO_FORMAT_DTS_HD)) {
5844 ret = audio_extn_passthru_update_dts_stream_configuration(out,
5845 buffer, bytes);
5846 if (ret) {
5847 if (ret != -ENOSYS) {
5848 out->is_iec61937_info_available = false;
5849 ALOGD("iec61937 transmission info not yet updated retry");
5850 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305851 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05305852 /* if stream has started and after that there is
5853 * stream config change (iec transmission config)
5854 * then trigger select_device to update backend configuration.
5855 */
5856 out->stream_config_changed = true;
5857 pthread_mutex_lock(&adev->lock);
5858 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305859 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08005860 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305861 ret = -EINVAL;
5862 goto exit;
5863 }
Manish Dewangan671a4202017-08-18 17:30:46 +05305864 pthread_mutex_unlock(&adev->lock);
5865 out->stream_config_changed = false;
5866 out->is_iec61937_info_available = true;
5867 }
5868 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305869
Meng Wang4c32fb42020-01-16 17:57:11 +08005870#ifdef AUDIO_GKI_ENABLED
5871 /* out->compr_config.codec->reserved[0] is for compr_passthr */
5872 compr_passthr = out->compr_config.codec->reserved[0];
5873#else
5874 compr_passthr = out->compr_config.codec->compr_passthr;
5875#endif
5876
Garmond Leung317cbf12017-09-13 16:20:50 -07005877 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Meng Wang4c32fb42020-01-16 17:57:11 +08005878 (compr_passthr == PASSTHROUGH) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305879 (out->is_iec61937_info_available == true)) {
5880 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
5881 ret = -EINVAL;
5882 goto exit;
5883 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05305884 }
5885 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305886
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005887 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02005888 (audio_extn_a2dp_source_is_suspended())) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005889 if (!(compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER) ||
5890 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Zhou Songd01e7a22020-09-23 22:49:01 +08005891 if (!is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305892 ret = -EIO;
5893 goto exit;
5894 }
5895 }
5896 }
5897
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005898 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005899 out->standby = false;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005900 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
5901
Eric Laurent150dbfe2013-02-27 14:31:02 -08005902 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005903 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
5904 ret = voice_extn_compress_voip_start_output_stream(out);
5905 else
5906 ret = start_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005907 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005908 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005909 out->standby = true;
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005910 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005911 goto exit;
5912 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305913 out->started = 1;
Andy Hunga1f48fa2019-07-01 18:14:53 -07005914 out->last_fifo_valid = false; // we're coming out of standby, last_fifo isn't valid.
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005915
5916 if ((last_known_cal_step != -1) && (adev->platform != NULL)) {
vivek mehtab72d08d2016-04-29 03:16:47 -07005917 ALOGD("%s: retry previous failed cal level set", __func__);
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005918 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05305919 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005920 }
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005921 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305922
5923 if ((out->is_iec61937_info_available == true) &&
5924 (audio_extn_passthru_is_passthrough_stream(out))&&
5925 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
5926 ret = -EINVAL;
5927 goto exit;
5928 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05305929 if (out->set_dual_mono)
5930 audio_extn_send_dual_mono_mixing_coefficients(out);
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005931
5932 // log startup time in ms.
5933 simple_stats_log(
5934 &out->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005935 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005936
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005937 if (adev->is_channel_status_set == false &&
5938 compare_device_type(&out->device_list,
5939 AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Alexy Josephb1379942016-01-29 15:49:38 -08005940 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05305941 adev->is_channel_status_set = true;
5942 }
5943
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305944 if ((adev->use_old_pspd_mix_ctrl == true) &&
5945 (out->pspd_coeff_sent == false)) {
5946 /*
5947 * Need to resend pspd coefficients after stream started for
5948 * older kernel version as it does not save the coefficients
5949 * and also stream has to be started for coeff to apply.
5950 */
5951 usecase = get_usecase_from_list(adev, out->usecase);
5952 if (usecase != NULL) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05305953 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305954 out->pspd_coeff_sent = true;
5955 }
5956 }
5957
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005958 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08005959 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005960 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005961 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005962 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
5963 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305964 if (out->send_next_track_params && out->is_compr_metadata_avail) {
5965 ALOGD("copl(%p):send next track params in gapless", out);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08005966 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305967 out->send_next_track_params = false;
5968 out->is_compr_metadata_avail = false;
5969 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005970 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05305971 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305972 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005973
Ashish Jain83a6cc22016-06-28 14:34:17 +05305974 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305975 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05305976 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05305977 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005978 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05305979 return -EINVAL;
5980 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05305981 audio_format_t dst_format = out->hal_op_format;
5982 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305983
Dieter Luecking5d57def2018-09-07 14:23:37 +02005984 /* prevent division-by-zero */
5985 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
5986 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
5987 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
5988 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05305989 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005990 ATRACE_END();
5991 return -EINVAL;
5992 }
5993
Ashish Jainf1eaa582016-05-23 20:54:24 +05305994 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
5995 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
5996
Ashish Jain83a6cc22016-06-28 14:34:17 +05305997 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305998 dst_format,
5999 buffer,
6000 src_format,
6001 frames);
6002
Ashish Jain83a6cc22016-06-28 14:34:17 +05306003 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05306004 bytes_to_write);
6005
6006 /*Convert written bytes in audio flinger format*/
6007 if (ret > 0)
6008 ret = ((ret * format_to_bitwidth_table[out->format]) /
6009 format_to_bitwidth_table[dst_format]);
6010 }
6011 } else
6012 ret = compress_write(out->compr, buffer, bytes);
6013
Zhou Songc9672822017-08-16 16:01:39 +08006014 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
6015 update_frames_written(out, bytes);
6016
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306017 if (ret < 0)
6018 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08006019 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05306020 /*msg to cb thread only if non blocking write is enabled*/
6021 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05306022 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006023 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05306024 } else if (-ENETRESET == ret) {
6025 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306026 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05306027 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05306028 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006029 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05306030 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006031 }
Ashish Jain5106d362016-05-11 19:23:33 +05306032
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05306033 /* Call compr start only when non-zero bytes of data is there to be rendered */
6034 if (!out->playback_started && ret > 0) {
6035 int status = compress_start(out->compr);
6036 if (status < 0) {
6037 ret = status;
6038 ALOGE("%s: compr start failed with err %d", __func__, errno);
6039 goto exit;
6040 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07006041 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006042 out->playback_started = 1;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006043 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006044 out->offload_state = OFFLOAD_STATE_PLAYING;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006045 pthread_mutex_unlock(&out->latch_lock);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006046
6047 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6048 popcount(out->channel_mask),
6049 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006050 }
6051 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006052 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006053 return ret;
6054 } else {
6055 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006056 size_t bytes_to_write = bytes;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006057 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006058 if (out->muted)
6059 memset((void *)buffer, 0, bytes);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006060 pthread_mutex_unlock(&out->latch_lock);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006061 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
6062 __func__, frames, frame_size, bytes_to_write);
6063
Aalique Grahame22e49102018-12-18 14:23:57 -08006064 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07006065 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
6066 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
6067 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006068 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
6069 int16_t *src = (int16_t *)buffer;
6070 int16_t *dst = (int16_t *)buffer;
6071
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006072 LOG_ALWAYS_FATAL_IF(channel_count > 2 ||
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006073 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08006074 "out_write called for %s use case with wrong properties",
6075 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006076
6077 /*
6078 * FIXME: this can be removed once audio flinger mixer supports
6079 * mono output
6080 */
6081
6082 /*
6083 * Code below goes over each frame in the buffer and adds both
6084 * L and R samples and then divides by 2 to convert to mono
6085 */
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006086 if (channel_count == 2) {
6087 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
6088 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
6089 }
6090 bytes_to_write /= 2;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006091 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006092 }
Andy Hunga1f48fa2019-07-01 18:14:53 -07006093
6094 // Note: since out_get_presentation_position() is called alternating with out_write()
6095 // by AudioFlinger, we can check underruns using the prior timestamp read.
6096 // (Alternately we could check if the buffer is empty using pcm_get_htimestamp().
6097 if (out->last_fifo_valid) {
6098 // compute drain to see if there is an underrun.
6099 const int64_t current_ns = systemTime(SYSTEM_TIME_MONOTONIC); // sys call
Dhananjay Kumara4429632020-07-11 02:53:37 +05306100 int64_t time_diff_ns = current_ns - out->last_fifo_time_ns;
6101 int64_t frames_by_time =
6102 ((time_diff_ns > 0) && (time_diff_ns < (INT64_MAX / out->config.rate))) ?
6103 (time_diff_ns * out->config.rate / NANOS_PER_SECOND) : 0;
Andy Hunga1f48fa2019-07-01 18:14:53 -07006104 const int64_t underrun = frames_by_time - out->last_fifo_frames_remaining;
6105
6106 if (underrun > 0) {
6107 simple_stats_log(&out->fifo_underruns, underrun);
6108
6109 ALOGW("%s: underrun(%lld) "
6110 "frames_by_time(%lld) > out->last_fifo_frames_remaining(%lld)",
6111 __func__,
6112 (long long)out->fifo_underruns.n,
6113 (long long)frames_by_time,
6114 (long long)out->last_fifo_frames_remaining);
6115 }
6116 out->last_fifo_valid = false; // we're writing below, mark fifo info as stale.
6117 }
6118
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306119 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006120
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006121 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006122
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006123 if (out->config.rate)
6124 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
6125 out->config.rate;
6126
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006127 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006128 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
6129
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006130 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006131 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006132 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306133 out->convert_buffer != NULL) {
6134
6135 memcpy_by_audio_format(out->convert_buffer,
6136 out->hal_op_format,
6137 buffer,
6138 out->hal_ip_format,
6139 out->config.period_size * out->config.channels);
6140
6141 ret = pcm_write(out->pcm, out->convert_buffer,
6142 (out->config.period_size *
6143 out->config.channels *
6144 format_to_bitwidth_table[out->hal_op_format]));
6145 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05306146 /*
6147 * To avoid underrun in DSP when the application is not pumping
6148 * data at required rate, check for the no. of bytes and ignore
6149 * pcm_write if it is less than actual buffer size.
6150 * It is a work around to a change in compress VOIP driver.
6151 */
6152 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
6153 bytes < (out->config.period_size * out->config.channels *
6154 audio_bytes_per_sample(out->format))) {
6155 size_t voip_buf_size =
6156 out->config.period_size * out->config.channels *
6157 audio_bytes_per_sample(out->format);
6158 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
6159 __func__, bytes, voip_buf_size);
6160 usleep(((uint64_t)voip_buf_size - bytes) *
6161 1000000 / audio_stream_out_frame_size(stream) /
6162 out_get_sample_rate(&out->stream.common));
6163 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006164 } else {
6165 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
6166 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
6167 else
6168 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
6169 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306170 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006171
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006172 release_out_focus(out);
6173
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306174 if (ret < 0)
6175 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08006176 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05306177 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006178 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006179 }
6180
6181exit:
Zhou Songc9672822017-08-16 16:01:39 +08006182 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306183 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306184 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306185 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006186 pthread_mutex_unlock(&out->lock);
6187
6188 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006189 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08006190 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306191 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306192 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306193 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306194 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306195 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306196 out->standby = true;
6197 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306198 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006199 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
6200 /* prevent division-by-zero */
6201 uint32_t stream_size = audio_stream_out_frame_size(stream);
6202 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006203
Dieter Luecking5d57def2018-09-07 14:23:37 +02006204 if ((stream_size == 0) || (srate == 0)) {
6205 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
6206 ATRACE_END();
6207 return -EINVAL;
6208 }
6209 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
6210 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006211 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05306212 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006213 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006214 return ret;
6215 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006216 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07006217 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006218 return bytes;
6219}
6220
6221static int out_get_render_position(const struct audio_stream_out *stream,
6222 uint32_t *dsp_frames)
6223{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006224 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08006225
6226 if (dsp_frames == NULL)
6227 return -EINVAL;
6228
6229 *dsp_frames = 0;
6230 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08006231 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05306232
6233 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
6234 * this operation and adev_close_output_stream(where out gets reset).
6235 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05306236 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006237 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05306238 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006239 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05306240 return 0;
6241 }
6242
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006243 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05306244 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306245 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006246 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306247 if (ret < 0)
6248 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006249 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05306250 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006251 }
Naresh Tanniru80659832014-06-04 18:17:56 +05306252 if (-ENETRESET == ret) {
6253 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306254 out->card_status = CARD_STATUS_OFFLINE;
6255 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306256 } else if(ret < 0) {
6257 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306258 ret = -EINVAL;
6259 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05306260 /*
6261 * Handle corner case where compress session is closed during SSR
6262 * and timestamp is queried
6263 */
6264 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306265 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306266 } else if (out->prev_card_status_offline) {
6267 ALOGE("ERROR: previously sound card was offline,return error");
6268 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306269 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306270 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006271 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05306272 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306273 pthread_mutex_unlock(&out->lock);
6274 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08006275 } else if (audio_is_linear_pcm(out->format)) {
6276 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006277 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08006278 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006279 } else
6280 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006281}
6282
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006283static int out_add_audio_effect(const struct audio_stream *stream __unused,
6284 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006285{
6286 return 0;
6287}
6288
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006289static int out_remove_audio_effect(const struct audio_stream *stream __unused,
6290 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006291{
6292 return 0;
6293}
6294
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006295static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
6296 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006297{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05306298 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006299}
6300
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006301static int out_get_presentation_position(const struct audio_stream_out *stream,
6302 uint64_t *frames, struct timespec *timestamp)
6303{
6304 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05306305 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07006306 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006307
Ashish Jain5106d362016-05-11 19:23:33 +05306308 /* below piece of code is not guarded against any lock because audioFliner serializes
6309 * this operation and adev_close_output_stream( where out gets reset).
6310 */
6311 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05306312 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006313 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05306314 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
6315 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
6316 return 0;
6317 }
6318
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006319 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006320
Ashish Jain5106d362016-05-11 19:23:33 +05306321 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
6322 ret = compress_get_tstamp(out->compr, &dsp_frames,
6323 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08006324 // Adjustment accounts for A2dp encoder latency with offload usecases
6325 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006326 if (is_a2dp_out_device_type(&out->device_list)) {
yidongh0515e042017-07-06 15:00:34 +08006327 unsigned long offset =
6328 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
6329 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
6330 }
Ashish Jain5106d362016-05-11 19:23:33 +05306331 ALOGVV("%s rendered frames %ld sample_rate %d",
6332 __func__, dsp_frames, out->sample_rate);
6333 *frames = dsp_frames;
6334 if (ret < 0)
6335 ret = -errno;
6336 if (-ENETRESET == ret) {
6337 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306338 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05306339 ret = -EINVAL;
6340 } else
6341 ret = 0;
6342 /* this is the best we can do */
6343 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07006344 } else {
6345 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08006346 unsigned int avail;
6347 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
George Gao62ebc722019-07-29 16:29:44 -07006348 uint64_t signed_frames = 0;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006349 uint64_t frames_temp = 0;
George Gao62ebc722019-07-29 16:29:44 -07006350
Andy Hunga1f48fa2019-07-01 18:14:53 -07006351 if (out->kernel_buffer_size > avail) {
6352 frames_temp = out->last_fifo_frames_remaining = out->kernel_buffer_size - avail;
6353 } else {
6354 ALOGW("%s: avail:%u > kernel_buffer_size:%zu clamping!",
6355 __func__, avail, out->kernel_buffer_size);
6356 avail = out->kernel_buffer_size;
6357 frames_temp = out->last_fifo_frames_remaining = 0;
6358 }
6359 out->last_fifo_valid = true;
6360 out->last_fifo_time_ns = audio_utils_ns_from_timespec(timestamp);
6361
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006362 if (out->written >= frames_temp)
6363 signed_frames = out->written - frames_temp;
George Gao62ebc722019-07-29 16:29:44 -07006364
Andy Hunga1f48fa2019-07-01 18:14:53 -07006365 ALOGVV("%s: frames:%lld avail:%u kernel_buffer_size:%zu",
6366 __func__, (long long)signed_frames, avail, out->kernel_buffer_size);
6367
Weiyin Jiangd4633762018-03-16 12:05:03 +08006368 // This adjustment accounts for buffering after app processor.
6369 // It is based on estimated DSP latency per use case, rather than exact.
George Gao9ba8a142020-07-23 14:30:03 -07006370 frames_temp = platform_render_latency(out) *
Robert Lee58215542019-07-15 20:55:12 +08006371 out->sample_rate / 1000000LL;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006372 if (signed_frames >= frames_temp)
6373 signed_frames -= frames_temp;
Aniket Kumar Lataff613152017-07-18 18:19:21 -07006374
Weiyin Jiangd4633762018-03-16 12:05:03 +08006375 // Adjustment accounts for A2dp encoder latency with non offload usecases
6376 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006377 if (is_a2dp_out_device_type(&out->device_list)) {
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006378 frames_temp = audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000;
6379 if (signed_frames >= frames_temp)
6380 signed_frames -= frames_temp;
Weiyin Jiangd4633762018-03-16 12:05:03 +08006381 }
6382
6383 // It would be unusual for this value to be negative, but check just in case ...
George Gao62ebc722019-07-29 16:29:44 -07006384 *frames = signed_frames;
6385 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006386 }
Eric Laurenta7a33042019-07-10 16:20:22 -07006387 } else if (out->card_status == CARD_STATUS_OFFLINE ||
6388 // audioflinger still needs position updates when A2DP is suspended
Jasmine Cha5c2517f2019-09-09 11:07:28 +08006389 (is_a2dp_out_device_type(&out->device_list) && audio_extn_a2dp_source_is_suspended())) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306390 *frames = out->written;
6391 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306392 if (is_offload_usecase(out->usecase))
6393 ret = -EINVAL;
6394 else
6395 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006396 }
6397 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006398 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006399 return ret;
6400}
6401
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006402static int out_set_callback(struct audio_stream_out *stream,
6403 stream_callback_t callback, void *cookie)
6404{
6405 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006406 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006407
6408 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006409 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006410 out->client_callback = callback;
6411 out->client_cookie = cookie;
6412 if (out->adsp_hdlr_stream_handle) {
6413 ret = audio_extn_adsp_hdlr_stream_set_callback(
6414 out->adsp_hdlr_stream_handle,
6415 callback,
6416 cookie);
6417 if (ret)
6418 ALOGW("%s:adsp hdlr callback registration failed %d",
6419 __func__, ret);
6420 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006421 pthread_mutex_unlock(&out->lock);
6422 return 0;
6423}
6424
6425static int out_pause(struct audio_stream_out* stream)
6426{
6427 struct stream_out *out = (struct stream_out *)stream;
6428 int status = -ENOSYS;
6429 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006430 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006431 ALOGD("copl(%p):pause compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306432 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006433 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006434 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006435 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306436 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05306437 status = compress_pause(out->compr);
6438
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006439 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006440
Mingming Yin21854652016-04-13 11:54:02 -07006441 if (audio_extn_passthru_is_active()) {
6442 ALOGV("offload use case, pause passthru");
6443 audio_extn_passthru_on_pause(out);
6444 }
6445
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306446 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006447 audio_extn_dts_notify_playback_state(out->usecase, 0,
6448 out->sample_rate, popcount(out->channel_mask),
6449 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006450 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08006451 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006452 pthread_mutex_unlock(&out->lock);
6453 }
6454 return status;
6455}
6456
6457static int out_resume(struct audio_stream_out* stream)
6458{
6459 struct stream_out *out = (struct stream_out *)stream;
6460 int status = -ENOSYS;
6461 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006462 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006463 ALOGD("copl(%p):resume compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306464 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006465 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006466 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006467 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306468 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306469 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07006470 }
6471 if (!status) {
6472 out->offload_state = OFFLOAD_STATE_PLAYING;
6473 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306474 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006475 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6476 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006477 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08006478 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006479 pthread_mutex_unlock(&out->lock);
6480 }
6481 return status;
6482}
6483
6484static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
6485{
6486 struct stream_out *out = (struct stream_out *)stream;
6487 int status = -ENOSYS;
6488 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006489 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006490 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006491 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
6492 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
6493 else
6494 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
6495 pthread_mutex_unlock(&out->lock);
6496 }
6497 return status;
6498}
6499
6500static int out_flush(struct audio_stream_out* stream)
6501{
6502 struct stream_out *out = (struct stream_out *)stream;
6503 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006504 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006505 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006506 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006507 pthread_mutex_lock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006508 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
6509 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006510 } else {
6511 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
6512 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08006513 out->written = 0;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006514 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006515 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006516 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006517 return 0;
6518 }
6519 return -ENOSYS;
6520}
6521
Haynes Mathew George16081042017-05-31 17:16:49 -07006522static int out_stop(const struct audio_stream_out* stream)
6523{
6524 struct stream_out *out = (struct stream_out *)stream;
6525 struct audio_device *adev = out->dev;
6526 int ret = -ENOSYS;
6527
6528 ALOGV("%s", __func__);
6529 pthread_mutex_lock(&adev->lock);
6530 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6531 out->playback_started && out->pcm != NULL) {
6532 pcm_stop(out->pcm);
6533 ret = stop_output_stream(out);
6534 out->playback_started = false;
6535 }
6536 pthread_mutex_unlock(&adev->lock);
6537 return ret;
6538}
6539
6540static int out_start(const struct audio_stream_out* stream)
6541{
6542 struct stream_out *out = (struct stream_out *)stream;
6543 struct audio_device *adev = out->dev;
6544 int ret = -ENOSYS;
6545
6546 ALOGV("%s", __func__);
6547 pthread_mutex_lock(&adev->lock);
6548 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6549 !out->playback_started && out->pcm != NULL) {
6550 ret = start_output_stream(out);
6551 if (ret == 0) {
6552 out->playback_started = true;
6553 }
6554 }
6555 pthread_mutex_unlock(&adev->lock);
6556 return ret;
6557}
6558
6559/*
6560 * Modify config->period_count based on min_size_frames
6561 */
6562static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
6563{
6564 int periodCountRequested = (min_size_frames + config->period_size - 1)
6565 / config->period_size;
6566 int periodCount = MMAP_PERIOD_COUNT_MIN;
6567
6568 ALOGV("%s original config.period_size = %d config.period_count = %d",
6569 __func__, config->period_size, config->period_count);
6570
6571 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
6572 periodCount *= 2;
6573 }
6574 config->period_count = periodCount;
6575
6576 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
6577}
6578
Phil Burkfe17efd2019-03-25 10:23:35 -07006579// Read offset for the positional timestamp from a persistent vendor property.
6580// This is to workaround apparent inaccuracies in the timing information that
6581// is used by the AAudio timing model. The inaccuracies can cause glitches.
6582static int64_t get_mmap_out_time_offset() {
6583 const int32_t kDefaultOffsetMicros = 0;
6584 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006585 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07006586 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
6587 return mmap_time_offset_micros * (int64_t)1000;
6588}
6589
Haynes Mathew George16081042017-05-31 17:16:49 -07006590static int out_create_mmap_buffer(const struct audio_stream_out *stream,
6591 int32_t min_size_frames,
6592 struct audio_mmap_buffer_info *info)
6593{
6594 struct stream_out *out = (struct stream_out *)stream;
6595 struct audio_device *adev = out->dev;
6596 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07006597 unsigned int offset1 = 0;
6598 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006599 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006600 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006601 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07006602
Arun Mirpuri5d170872019-03-26 13:21:31 -07006603 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306604 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07006605 pthread_mutex_lock(&adev->lock);
6606
Sharad Sanglec6f32552018-05-04 16:15:38 +05306607 if (CARD_STATUS_OFFLINE == out->card_status ||
6608 CARD_STATUS_OFFLINE == adev->card_status) {
6609 ALOGW("out->card_status or adev->card_status offline, try again");
6610 ret = -EIO;
6611 goto exit;
6612 }
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306613 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07006614 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
6615 ret = -EINVAL;
6616 goto exit;
6617 }
6618 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
6619 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
6620 ret = -ENOSYS;
6621 goto exit;
6622 }
6623 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
6624 if (out->pcm_device_id < 0) {
6625 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6626 __func__, out->pcm_device_id, out->usecase);
6627 ret = -EINVAL;
6628 goto exit;
6629 }
6630
6631 adjust_mmap_period_count(&out->config, min_size_frames);
6632
Arun Mirpuri5d170872019-03-26 13:21:31 -07006633 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006634 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
6635 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
6636 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306637 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306638 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6639 out->card_status = CARD_STATUS_OFFLINE;
6640 adev->card_status = CARD_STATUS_OFFLINE;
6641 ret = -EIO;
6642 goto exit;
6643 }
6644
Haynes Mathew George16081042017-05-31 17:16:49 -07006645 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
6646 step = "open";
6647 ret = -ENODEV;
6648 goto exit;
6649 }
6650 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
6651 if (ret < 0) {
6652 step = "begin";
6653 goto exit;
6654 }
juyuchen626833d2019-06-04 16:48:02 +08006655
6656 info->flags = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006657 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07006658 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07006659 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006660 ret = platform_get_mmap_data_fd(adev->platform,
6661 out->pcm_device_id, 0 /*playback*/,
6662 &info->shared_memory_fd,
6663 &mmap_size);
6664 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07006665 // Fall back to non exclusive mode
6666 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
6667 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07006668 out->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
6669 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, out->mmap_shared_memory_fd);
6670
Arun Mirpuri5d170872019-03-26 13:21:31 -07006671 if (mmap_size < buffer_size) {
6672 step = "mmap";
6673 goto exit;
6674 }
juyuchen626833d2019-06-04 16:48:02 +08006675 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006676 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006677 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006678 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07006679
6680 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
6681 if (ret < 0) {
6682 step = "commit";
6683 goto exit;
6684 }
6685
Phil Burkfe17efd2019-03-25 10:23:35 -07006686 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
6687
Haynes Mathew George16081042017-05-31 17:16:49 -07006688 out->standby = false;
6689 ret = 0;
6690
Arun Mirpuri5d170872019-03-26 13:21:31 -07006691 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006692 __func__, info->shared_memory_address, info->buffer_size_frames);
6693
6694exit:
6695 if (ret != 0) {
6696 if (out->pcm == NULL) {
6697 ALOGE("%s: %s - %d", __func__, step, ret);
6698 } else {
6699 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
6700 pcm_close(out->pcm);
6701 out->pcm = NULL;
6702 }
6703 }
6704 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306705 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07006706 return ret;
6707}
6708
6709static int out_get_mmap_position(const struct audio_stream_out *stream,
6710 struct audio_mmap_position *position)
6711{
6712 struct stream_out *out = (struct stream_out *)stream;
6713 ALOGVV("%s", __func__);
6714 if (position == NULL) {
6715 return -EINVAL;
6716 }
6717 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08006718 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006719 return -ENOSYS;
6720 }
6721 if (out->pcm == NULL) {
6722 return -ENOSYS;
6723 }
6724
6725 struct timespec ts = { 0, 0 };
6726 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
6727 if (ret < 0) {
6728 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
6729 return ret;
6730 }
Phil Burkfe17efd2019-03-25 10:23:35 -07006731 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
6732 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07006733 return 0;
6734}
6735
6736
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006737/** audio_stream_in implementation **/
6738static uint32_t in_get_sample_rate(const struct audio_stream *stream)
6739{
6740 struct stream_in *in = (struct stream_in *)stream;
6741
6742 return in->config.rate;
6743}
6744
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006745static int in_set_sample_rate(struct audio_stream *stream __unused,
6746 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006747{
6748 return -ENOSYS;
6749}
6750
6751static size_t in_get_buffer_size(const struct audio_stream *stream)
6752{
6753 struct stream_in *in = (struct stream_in *)stream;
6754
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006755 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
6756 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07006757 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
6758 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306759 else if(audio_extn_cin_attached_usecase(in))
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306760 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006761
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006762 return in->config.period_size * in->af_period_multiplier *
6763 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006764}
6765
6766static uint32_t in_get_channels(const struct audio_stream *stream)
6767{
6768 struct stream_in *in = (struct stream_in *)stream;
6769
6770 return in->channel_mask;
6771}
6772
6773static audio_format_t in_get_format(const struct audio_stream *stream)
6774{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006775 struct stream_in *in = (struct stream_in *)stream;
6776
6777 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006778}
6779
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006780static int in_set_format(struct audio_stream *stream __unused,
6781 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006782{
6783 return -ENOSYS;
6784}
6785
6786static int in_standby(struct audio_stream *stream)
6787{
6788 struct stream_in *in = (struct stream_in *)stream;
6789 struct audio_device *adev = in->dev;
6790 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306791 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
6792 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006793 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306794
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006795 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006796 if (!in->standby && in->is_st_session) {
6797 ALOGD("%s: sound trigger pcm stop lab", __func__);
6798 audio_extn_sound_trigger_stop_lab(in);
George Gao3018ede2019-10-23 13:23:00 -07006799 if (adev->num_va_sessions > 0)
6800 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006801 in->standby = 1;
6802 }
6803
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006804 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006805 if (adev->adm_deregister_stream)
6806 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
6807
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08006808 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006809 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08006810 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08006811 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08006812 voice_extn_compress_voip_close_input_stream(stream);
6813 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07006814 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6815 do_stop = in->capture_started;
6816 in->capture_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07006817 if (in->mmap_shared_memory_fd >= 0) {
6818 ALOGV("%s: closing mmap_shared_memory_fd = %d",
6819 __func__, in->mmap_shared_memory_fd);
6820 close(in->mmap_shared_memory_fd);
6821 in->mmap_shared_memory_fd = -1;
6822 }
Zhou Songa8895042016-07-05 17:54:22 +08006823 } else {
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306824 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05306825 audio_extn_cin_close_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08006826 }
6827
Arun Mirpuri5d170872019-03-26 13:21:31 -07006828 if (in->pcm) {
6829 ATRACE_BEGIN("pcm_in_close");
6830 pcm_close(in->pcm);
6831 ATRACE_END();
6832 in->pcm = NULL;
6833 }
6834
Carter Hsu2e429db2019-05-14 18:50:52 +08006835 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08006836 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006837
George Gao3018ede2019-10-23 13:23:00 -07006838 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
6839 if (adev->num_va_sessions > 0)
6840 adev->num_va_sessions--;
6841 }
Quinn Malef6050362019-01-30 15:55:40 -08006842
Eric Laurent150dbfe2013-02-27 14:31:02 -08006843 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006844 }
6845 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07006846 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006847 return status;
6848}
6849
Aalique Grahame22e49102018-12-18 14:23:57 -08006850static int in_dump(const struct audio_stream *stream,
6851 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006852{
Aalique Grahame22e49102018-12-18 14:23:57 -08006853 struct stream_in *in = (struct stream_in *)stream;
6854
6855 // We try to get the lock for consistency,
6856 // but it isn't necessary for these variables.
6857 // If we're not in standby, we may be blocked on a read.
6858 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
6859 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
6860 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
6861 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
6862
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006863 char buffer[256]; // for statistics formatting
6864 if (in->start_latency_ms.n > 0) {
6865 simple_stats_to_string(&in->start_latency_ms, buffer, sizeof(buffer));
6866 dprintf(fd, " Start latency ms: %s\n", buffer);
6867 }
6868
Aalique Grahame22e49102018-12-18 14:23:57 -08006869 if (locked) {
6870 pthread_mutex_unlock(&in->lock);
6871 }
6872
6873 // dump error info
6874 (void)error_log_dump(
6875 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
6876
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006877 return 0;
6878}
6879
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306880static void in_snd_mon_cb(void * stream, struct str_parms * parms)
6881{
6882 if (!stream || !parms)
6883 return;
6884
6885 struct stream_in *in = (struct stream_in *)stream;
6886 struct audio_device *adev = in->dev;
6887
6888 card_status_t status;
6889 int card;
6890 if (parse_snd_card_status(parms, &card, &status) < 0)
6891 return;
6892
6893 pthread_mutex_lock(&adev->lock);
6894 bool valid_cb = (card == adev->snd_card);
6895 pthread_mutex_unlock(&adev->lock);
6896
6897 if (!valid_cb)
6898 return;
6899
6900 lock_input_stream(in);
6901 if (in->card_status != status)
6902 in->card_status = status;
6903 pthread_mutex_unlock(&in->lock);
6904
6905 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
6906 use_case_table[in->usecase],
6907 status == CARD_STATUS_OFFLINE ? "offline" : "online");
6908
6909 // a better solution would be to report error back to AF and let
6910 // it put the stream to standby
6911 if (status == CARD_STATUS_OFFLINE)
6912 in_standby(&in->stream.common);
6913
6914 return;
6915}
6916
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006917int route_input_stream(struct stream_in *in,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006918 struct listnode *devices,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006919 audio_source_t source)
6920{
6921 struct audio_device *adev = in->dev;
6922 int ret = 0;
6923
6924 lock_input_stream(in);
6925 pthread_mutex_lock(&adev->lock);
6926
6927 /* no audio source uses val == 0 */
6928 if ((in->source != source) && (source != AUDIO_SOURCE_DEFAULT)) {
6929 in->source = source;
6930 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6931 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
6932 (voice_extn_compress_voip_is_format_supported(in->format)) &&
6933 (in->config.rate == 8000 || in->config.rate == 16000 ||
6934 in->config.rate == 32000 || in->config.rate == 48000 ) &&
6935 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
6936 ret = voice_extn_compress_voip_open_input_stream(in);
6937 if (ret != 0) {
6938 ALOGE("%s: Compress voip input cannot be opened, error:%d",
6939 __func__, ret);
6940 }
6941 }
6942 }
6943
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006944 if (!compare_devices(&in->device_list, devices) && !list_empty(devices) &&
6945 is_audio_in_device_type(devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006946 // Workaround: If routing to an non existing usb device, fail gracefully
6947 // The routing request will otherwise block during 10 second
6948 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006949 struct str_parms *usb_addr =
6950 str_parms_create_str(get_usb_device_address(devices));
6951 if (is_usb_in_device_type(devices) && usb_addr &&
6952 (card = get_alive_usb_card(usb_addr)) >= 0) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006953 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
6954 ret = -ENOSYS;
6955 } else {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006956 /* If recording is in progress, change the tx device to new device */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006957 assign_devices(&in->device_list, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006958 if (!in->standby && !in->is_st_session) {
6959 ALOGV("update input routing change");
6960 // inform adm before actual routing to prevent glitches.
6961 if (adev->adm_on_routing_change) {
6962 adev->adm_on_routing_change(adev->adm_data,
6963 in->capture_handle);
6964 ret = select_devices(adev, in->usecase);
6965 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6966 adev->adm_routing_changed = true;
6967 }
6968 }
6969 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006970 if (usb_addr)
6971 str_parms_destroy(usb_addr);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006972 }
6973 pthread_mutex_unlock(&adev->lock);
6974 pthread_mutex_unlock(&in->lock);
6975
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07006976 ALOGV("%s: exit: status(%d)", __func__, ret);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006977 return ret;
6978}
6979
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006980static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
6981{
6982 struct stream_in *in = (struct stream_in *)stream;
6983 struct audio_device *adev = in->dev;
6984 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006985 char value[32];
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306986 int err = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006987
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306988 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006989 parms = str_parms_create_str(kvpairs);
6990
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306991 if (!parms)
6992 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006993 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006994 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006995
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306996 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
6997 if (err >= 0) {
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306998 strlcpy(in->profile, value, sizeof(in->profile));
6999 ALOGV("updating stream profile with value '%s'", in->profile);
7000 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
7001 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007002 &in->device_list, in->flags, in->format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307003 in->sample_rate, in->bit_width,
7004 in->profile, &in->app_type_cfg);
7005 }
7006
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007007 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08007008 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007009
7010 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307011error:
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307012 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007013}
7014
7015static char* in_get_parameters(const struct audio_stream *stream,
7016 const char *keys)
7017{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007018 struct stream_in *in = (struct stream_in *)stream;
7019 struct str_parms *query = str_parms_create_str(keys);
7020 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007021 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007022
7023 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08007024 if (reply) {
7025 str_parms_destroy(reply);
7026 }
7027 if (query) {
7028 str_parms_destroy(query);
7029 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007030 ALOGE("in_get_parameters: failed to create query or reply");
7031 return NULL;
7032 }
7033
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007034 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007035
7036 voice_extn_in_get_parameters(in, query, reply);
7037
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007038 stream_get_parameter_channels(query, reply,
7039 &in->supported_channel_masks[0]);
7040 stream_get_parameter_formats(query, reply,
7041 &in->supported_formats[0]);
7042 stream_get_parameter_rates(query, reply,
7043 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007044 str = str_parms_to_str(reply);
7045 str_parms_destroy(query);
7046 str_parms_destroy(reply);
7047
7048 ALOGV("%s: exit: returns - %s", __func__, str);
7049 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007050}
7051
Aalique Grahame22e49102018-12-18 14:23:57 -08007052static int in_set_gain(struct audio_stream_in *stream,
7053 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007054{
Aalique Grahame22e49102018-12-18 14:23:57 -08007055 struct stream_in *in = (struct stream_in *)stream;
7056 char mixer_ctl_name[128];
7057 struct mixer_ctl *ctl;
7058 int ctl_value;
7059
7060 ALOGV("%s: gain %f", __func__, gain);
7061
7062 if (stream == NULL)
7063 return -EINVAL;
7064
7065 /* in_set_gain() only used to silence MMAP capture for now */
7066 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
7067 return -ENOSYS;
7068
7069 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
7070
7071 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
7072 if (!ctl) {
7073 ALOGW("%s: Could not get ctl for mixer cmd - %s",
7074 __func__, mixer_ctl_name);
7075 return -ENOSYS;
7076 }
7077
7078 if (gain < RECORD_GAIN_MIN)
7079 gain = RECORD_GAIN_MIN;
7080 else if (gain > RECORD_GAIN_MAX)
7081 gain = RECORD_GAIN_MAX;
7082 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
7083
7084 mixer_ctl_set_value(ctl, 0, ctl_value);
7085
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007086 return 0;
7087}
7088
7089static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
7090 size_t bytes)
7091{
7092 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05307093
7094 if (in == NULL) {
7095 ALOGE("%s: stream_in ptr is NULL", __func__);
7096 return -EINVAL;
7097 }
7098
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007099 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05307100 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307101 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007102
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007103 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05307104
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007105 if (in->is_st_session) {
7106 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
7107 /* Read from sound trigger HAL */
7108 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08007109 if (in->standby) {
George Gao3018ede2019-10-23 13:23:00 -07007110 if (adev->num_va_sessions < UINT_MAX)
7111 adev->num_va_sessions++;
Quinn Malef6050362019-01-30 15:55:40 -08007112 in->standby = 0;
7113 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007114 pthread_mutex_unlock(&in->lock);
7115 return bytes;
7116 }
7117
Haynes Mathew George16081042017-05-31 17:16:49 -07007118 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
7119 ret = -ENOSYS;
7120 goto exit;
7121 }
7122
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007123 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
7124 !in->standby && adev->adm_routing_changed) {
7125 ret = -ENOSYS;
7126 goto exit;
7127 }
7128
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007129 if (in->standby) {
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007130 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
7131
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007132 pthread_mutex_lock(&adev->lock);
7133 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
7134 ret = voice_extn_compress_voip_start_input_stream(in);
7135 else
7136 ret = start_input_stream(in);
George Gao3018ede2019-10-23 13:23:00 -07007137 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
7138 if (adev->num_va_sessions < UINT_MAX)
7139 adev->num_va_sessions++;
7140 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007141 pthread_mutex_unlock(&adev->lock);
7142 if (ret != 0) {
7143 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007144 }
7145 in->standby = 0;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007146
7147 // log startup time in ms.
7148 simple_stats_log(
7149 &in->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007150 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007151
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05307152 /* Avoid read if capture_stopped is set */
7153 if (android_atomic_acquire_load(&(in->capture_stopped)) > 0) {
7154 ALOGD("%s: force stopped catpure session, ignoring read request", __func__);
7155 ret = -EINVAL;
7156 goto exit;
7157 }
7158
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007159 // what's the duration requested by the client?
7160 long ns = 0;
7161
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307162 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007163 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
7164 in->config.rate;
7165
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007166 ret = request_in_focus(in, ns);
7167 if (ret != 0)
7168 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007169 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007170
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307171 if (audio_extn_cin_attached_usecase(in)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307172 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
7173 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307174 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007175 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307176 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07007177 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007178 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007179 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07007180 } else if (audio_extn_ffv_get_stream() == in) {
7181 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307182 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007183 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307184 /* data from DSP comes in 24_8 format, convert it to 8_24 */
7185 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
7186 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
7187 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307188 ret = -EINVAL;
7189 goto exit;
7190 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307191 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307192 ret = -errno;
7193 }
7194 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307195 /* bytes read is always set to bytes for non compress usecases */
7196 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007197 }
7198
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007199 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007200
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007201 /*
Quinn Malef6050362019-01-30 15:55:40 -08007202 * Instead of writing zeroes here, we could trust the hardware to always
7203 * provide zeroes when muted. This is also muted with voice recognition
7204 * usecases so that other clients do not have access to voice recognition
7205 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007206 */
Quinn Malef6050362019-01-30 15:55:40 -08007207 if ((ret == 0 && voice_get_mic_mute(adev) &&
7208 !voice_is_in_call_rec_stream(in) &&
Zhou Song62ea0282020-03-22 19:53:01 +08007209 (in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY &&
7210 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY2)) ||
Quinn Malef6050362019-01-30 15:55:40 -08007211 (adev->num_va_sessions &&
7212 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
7213 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
7214 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007215 memset(buffer, 0, bytes);
7216
7217exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307218 frame_size = audio_stream_in_frame_size(stream);
7219 if (frame_size > 0)
7220 in->frames_read += bytes_read/frame_size;
7221
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007222 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307223 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007224 pthread_mutex_unlock(&in->lock);
7225
7226 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307227 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307228 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307229 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307230 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307231 in->standby = true;
7232 }
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307233 if (!audio_extn_cin_attached_usecase(in)) {
Sharad Sangled17c9122017-03-20 15:58:52 +05307234 bytes_read = bytes;
7235 memset(buffer, 0, bytes);
7236 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007237 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007238 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7239 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007240 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05307241 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05307242 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007243 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307244 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007245}
7246
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007247static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007248{
7249 return 0;
7250}
7251
Aalique Grahame22e49102018-12-18 14:23:57 -08007252static int in_get_capture_position(const struct audio_stream_in *stream,
7253 int64_t *frames, int64_t *time)
7254{
7255 if (stream == NULL || frames == NULL || time == NULL) {
7256 return -EINVAL;
7257 }
7258 struct stream_in *in = (struct stream_in *)stream;
7259 int ret = -ENOSYS;
7260
7261 lock_input_stream(in);
7262 // note: ST sessions do not close the alsa pcm driver synchronously
7263 // on standby. Therefore, we may return an error even though the
7264 // pcm stream is still opened.
7265 if (in->standby) {
7266 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
7267 "%s stream in standby but pcm not NULL for non ST session", __func__);
7268 goto exit;
7269 }
7270 if (in->pcm) {
7271 struct timespec timestamp;
7272 unsigned int avail;
7273 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
7274 *frames = in->frames_read + avail;
Robert Lee58215542019-07-15 20:55:12 +08007275 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec
George Gao9ba8a142020-07-23 14:30:03 -07007276 - platform_capture_latency(in) * 1000LL;
Aalique Grahame22e49102018-12-18 14:23:57 -08007277 ret = 0;
7278 }
7279 }
7280exit:
7281 pthread_mutex_unlock(&in->lock);
7282 return ret;
7283}
7284
Carter Hsu2e429db2019-05-14 18:50:52 +08007285static int in_update_effect_list(bool add, effect_handle_t effect,
7286 struct listnode *head)
7287{
7288 struct listnode *node;
7289 struct in_effect_list *elist = NULL;
7290 struct in_effect_list *target = NULL;
7291 int ret = 0;
7292
7293 if (!head)
7294 return ret;
7295
7296 list_for_each(node, head) {
7297 elist = node_to_item(node, struct in_effect_list, list);
7298 if (elist->handle == effect) {
7299 target = elist;
7300 break;
7301 }
7302 }
7303
7304 if (add) {
7305 if (target) {
7306 ALOGD("effect %p already exist", effect);
7307 return ret;
7308 }
7309
7310 target = (struct in_effect_list *)
7311 calloc(1, sizeof(struct in_effect_list));
7312
7313 if (!target) {
7314 ALOGE("%s:fail to allocate memory", __func__);
7315 return -ENOMEM;
7316 }
7317
7318 target->handle = effect;
7319 list_add_tail(head, &target->list);
7320 } else {
7321 if (target) {
7322 list_remove(&target->list);
7323 free(target);
7324 }
7325 }
7326
7327 return ret;
7328}
7329
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007330static int add_remove_audio_effect(const struct audio_stream *stream,
7331 effect_handle_t effect,
7332 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007333{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007334 struct stream_in *in = (struct stream_in *)stream;
7335 int status = 0;
7336 effect_descriptor_t desc;
7337
7338 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007339 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
7340
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007341 if (status != 0)
7342 return status;
7343
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007344 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007345 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08007346 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08007347 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
7348 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007349 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08007350
7351 in_update_effect_list(enable, effect, &in->aec_list);
7352 enable = !list_empty(&in->aec_list);
7353 if (enable == in->enable_aec)
7354 goto exit;
7355
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007356 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007357 ALOGD("AEC enable %d", enable);
7358
Aalique Grahame22e49102018-12-18 14:23:57 -08007359 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7360 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
7361 in->dev->enable_voicerx = enable;
7362 struct audio_usecase *usecase;
7363 struct listnode *node;
7364 list_for_each(node, &in->dev->usecase_list) {
7365 usecase = node_to_item(node, struct audio_usecase, list);
7366 if (usecase->type == PCM_PLAYBACK)
7367 select_devices(in->dev, usecase->id);
7368 }
7369 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007370 if (!in->standby) {
7371 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
7372 select_devices(in->dev, in->usecase);
7373 }
7374
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007375 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007376 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
7377
7378 in_update_effect_list(enable, effect, &in->ns_list);
7379 enable = !list_empty(&in->ns_list);
7380 if (enable == in->enable_ns)
7381 goto exit;
7382
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007383 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007384 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007385 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08007386 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7387 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007388 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
7389 select_devices(in->dev, in->usecase);
7390 } else
7391 select_devices(in->dev, in->usecase);
7392 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007393 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007394exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007395 pthread_mutex_unlock(&in->dev->lock);
7396 pthread_mutex_unlock(&in->lock);
7397
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007398 return 0;
7399}
7400
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007401static int in_add_audio_effect(const struct audio_stream *stream,
7402 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007403{
Eric Laurent994a6932013-07-17 11:51:42 -07007404 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007405 return add_remove_audio_effect(stream, effect, true);
7406}
7407
7408static int in_remove_audio_effect(const struct audio_stream *stream,
7409 effect_handle_t effect)
7410{
Eric Laurent994a6932013-07-17 11:51:42 -07007411 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007412 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007413}
7414
Derek Chenf939fb72018-11-13 13:34:41 -08007415streams_input_ctxt_t *in_get_stream(struct audio_device *dev,
7416 audio_io_handle_t input)
7417{
7418 struct listnode *node;
7419
7420 list_for_each(node, &dev->active_inputs_list) {
7421 streams_input_ctxt_t *in_ctxt = node_to_item(node,
7422 streams_input_ctxt_t,
7423 list);
7424 if (in_ctxt->input->capture_handle == input) {
7425 return in_ctxt;
7426 }
7427 }
7428 return NULL;
7429}
7430
7431streams_output_ctxt_t *out_get_stream(struct audio_device *dev,
7432 audio_io_handle_t output)
7433{
7434 struct listnode *node;
7435
7436 list_for_each(node, &dev->active_outputs_list) {
7437 streams_output_ctxt_t *out_ctxt = node_to_item(node,
7438 streams_output_ctxt_t,
7439 list);
7440 if (out_ctxt->output->handle == output) {
7441 return out_ctxt;
7442 }
7443 }
7444 return NULL;
7445}
7446
Haynes Mathew George16081042017-05-31 17:16:49 -07007447static int in_stop(const struct audio_stream_in* stream)
7448{
7449 struct stream_in *in = (struct stream_in *)stream;
7450 struct audio_device *adev = in->dev;
7451
7452 int ret = -ENOSYS;
7453 ALOGV("%s", __func__);
7454 pthread_mutex_lock(&adev->lock);
7455 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7456 in->capture_started && in->pcm != NULL) {
7457 pcm_stop(in->pcm);
7458 ret = stop_input_stream(in);
7459 in->capture_started = false;
7460 }
7461 pthread_mutex_unlock(&adev->lock);
7462 return ret;
7463}
7464
7465static int in_start(const struct audio_stream_in* stream)
7466{
7467 struct stream_in *in = (struct stream_in *)stream;
7468 struct audio_device *adev = in->dev;
7469 int ret = -ENOSYS;
7470
7471 ALOGV("%s in %p", __func__, in);
7472 pthread_mutex_lock(&adev->lock);
7473 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7474 !in->capture_started && in->pcm != NULL) {
7475 if (!in->capture_started) {
7476 ret = start_input_stream(in);
7477 if (ret == 0) {
7478 in->capture_started = true;
7479 }
7480 }
7481 }
7482 pthread_mutex_unlock(&adev->lock);
7483 return ret;
7484}
7485
Phil Burke0a86d12019-02-16 22:28:11 -08007486// Read offset for the positional timestamp from a persistent vendor property.
7487// This is to workaround apparent inaccuracies in the timing information that
7488// is used by the AAudio timing model. The inaccuracies can cause glitches.
7489static int64_t in_get_mmap_time_offset() {
7490 const int32_t kDefaultOffsetMicros = 0;
7491 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08007492 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08007493 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
7494 return mmap_time_offset_micros * (int64_t)1000;
7495}
7496
Haynes Mathew George16081042017-05-31 17:16:49 -07007497static int in_create_mmap_buffer(const struct audio_stream_in *stream,
7498 int32_t min_size_frames,
7499 struct audio_mmap_buffer_info *info)
7500{
7501 struct stream_in *in = (struct stream_in *)stream;
7502 struct audio_device *adev = in->dev;
7503 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07007504 unsigned int offset1 = 0;
7505 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007506 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07007507 uint32_t mmap_size = 0;
7508 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007509
7510 pthread_mutex_lock(&adev->lock);
7511 ALOGV("%s in %p", __func__, in);
7512
Sharad Sanglec6f32552018-05-04 16:15:38 +05307513 if (CARD_STATUS_OFFLINE == in->card_status||
7514 CARD_STATUS_OFFLINE == adev->card_status) {
7515 ALOGW("in->card_status or adev->card_status offline, try again");
7516 ret = -EIO;
7517 goto exit;
7518 }
7519
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307520 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07007521 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
7522 ret = -EINVAL;
7523 goto exit;
7524 }
7525 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
7526 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
7527 ALOGV("%s in %p", __func__, in);
7528 ret = -ENOSYS;
7529 goto exit;
7530 }
7531 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
7532 if (in->pcm_device_id < 0) {
7533 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
7534 __func__, in->pcm_device_id, in->usecase);
7535 ret = -EINVAL;
7536 goto exit;
7537 }
7538
7539 adjust_mmap_period_count(&in->config, min_size_frames);
7540
7541 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
7542 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
7543 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
7544 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307545 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307546 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7547 in->card_status = CARD_STATUS_OFFLINE;
7548 adev->card_status = CARD_STATUS_OFFLINE;
7549 ret = -EIO;
7550 goto exit;
7551 }
7552
Haynes Mathew George16081042017-05-31 17:16:49 -07007553 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
7554 step = "open";
7555 ret = -ENODEV;
7556 goto exit;
7557 }
7558
7559 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
7560 if (ret < 0) {
7561 step = "begin";
7562 goto exit;
7563 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007564
juyuchen626833d2019-06-04 16:48:02 +08007565 info->flags = 0;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007566 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
7567 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
7568 info->burst_size_frames = in->config.period_size;
7569 ret = platform_get_mmap_data_fd(adev->platform,
7570 in->pcm_device_id, 1 /*capture*/,
7571 &info->shared_memory_fd,
7572 &mmap_size);
7573 if (ret < 0) {
7574 // Fall back to non exclusive mode
7575 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
7576 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07007577 in->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
7578 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, in->mmap_shared_memory_fd);
7579
Arun Mirpuri5d170872019-03-26 13:21:31 -07007580 if (mmap_size < buffer_size) {
7581 step = "mmap";
7582 goto exit;
7583 }
juyuchen626833d2019-06-04 16:48:02 +08007584 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007585 }
7586
7587 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07007588
7589 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
7590 if (ret < 0) {
7591 step = "commit";
7592 goto exit;
7593 }
7594
Phil Burke0a86d12019-02-16 22:28:11 -08007595 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
7596
Haynes Mathew George16081042017-05-31 17:16:49 -07007597 in->standby = false;
7598 ret = 0;
7599
7600 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
7601 __func__, info->shared_memory_address, info->buffer_size_frames);
7602
7603exit:
7604 if (ret != 0) {
7605 if (in->pcm == NULL) {
7606 ALOGE("%s: %s - %d", __func__, step, ret);
7607 } else {
7608 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
7609 pcm_close(in->pcm);
7610 in->pcm = NULL;
7611 }
7612 }
7613 pthread_mutex_unlock(&adev->lock);
7614 return ret;
7615}
7616
7617static int in_get_mmap_position(const struct audio_stream_in *stream,
7618 struct audio_mmap_position *position)
7619{
7620 struct stream_in *in = (struct stream_in *)stream;
7621 ALOGVV("%s", __func__);
7622 if (position == NULL) {
7623 return -EINVAL;
7624 }
7625 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
7626 return -ENOSYS;
7627 }
7628 if (in->pcm == NULL) {
7629 return -ENOSYS;
7630 }
7631 struct timespec ts = { 0, 0 };
7632 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
7633 if (ret < 0) {
7634 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
7635 return ret;
7636 }
Phil Burke0a86d12019-02-16 22:28:11 -08007637 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7638 + in->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07007639 return 0;
7640}
7641
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307642static int in_get_active_microphones(const struct audio_stream_in *stream,
7643 struct audio_microphone_characteristic_t *mic_array,
7644 size_t *mic_count) {
7645 struct stream_in *in = (struct stream_in *)stream;
7646 struct audio_device *adev = in->dev;
7647 ALOGVV("%s", __func__);
7648
7649 lock_input_stream(in);
7650 pthread_mutex_lock(&adev->lock);
7651 int ret = platform_get_active_microphones(adev->platform,
7652 audio_channel_count_from_in_mask(in->channel_mask),
7653 in->usecase, mic_array, mic_count);
7654 pthread_mutex_unlock(&adev->lock);
7655 pthread_mutex_unlock(&in->lock);
7656
7657 return ret;
7658}
7659
7660static int adev_get_microphones(const struct audio_hw_device *dev,
7661 struct audio_microphone_characteristic_t *mic_array,
7662 size_t *mic_count) {
7663 struct audio_device *adev = (struct audio_device *)dev;
7664 ALOGVV("%s", __func__);
7665
7666 pthread_mutex_lock(&adev->lock);
7667 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
7668 pthread_mutex_unlock(&adev->lock);
7669
7670 return ret;
7671}
juyuchendb308c22019-01-21 11:57:17 -07007672
7673static void in_update_sink_metadata(struct audio_stream_in *stream,
7674 const struct sink_metadata *sink_metadata) {
7675
7676 if (stream == NULL
7677 || sink_metadata == NULL
7678 || sink_metadata->tracks == NULL) {
7679 return;
7680 }
7681
7682 int error = 0;
7683 struct stream_in *in = (struct stream_in *)stream;
7684 struct audio_device *adev = in->dev;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007685 struct listnode devices;
Zhou Song62ea0282020-03-22 19:53:01 +08007686 bool is_ha_usecase = false;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007687
7688 list_init(&devices);
juyuchendb308c22019-01-21 11:57:17 -07007689
7690 if (sink_metadata->track_count != 0)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007691 reassign_device_list(&devices, sink_metadata->tracks->dest_device, "");
juyuchendb308c22019-01-21 11:57:17 -07007692
7693 lock_input_stream(in);
7694 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007695 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, get_device_types(&devices));
juyuchendb308c22019-01-21 11:57:17 -07007696
Zhou Song62ea0282020-03-22 19:53:01 +08007697 is_ha_usecase = adev->ha_proxy_enable ?
7698 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2 :
7699 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY;
7700 if (is_ha_usecase && !list_empty(&devices)
juyuchendb308c22019-01-21 11:57:17 -07007701 && adev->voice_tx_output != NULL) {
7702 /* Use the rx device from afe-proxy record to route voice call because
7703 there is no routing if tx device is on primary hal and rx device
7704 is on other hal during voice call. */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007705 assign_devices(&adev->voice_tx_output->device_list, &devices);
juyuchendb308c22019-01-21 11:57:17 -07007706
7707 if (!voice_is_call_state_active(adev)) {
7708 if (adev->mode == AUDIO_MODE_IN_CALL) {
7709 adev->current_call_output = adev->voice_tx_output;
7710 error = voice_start_call(adev);
7711 if (error != 0)
7712 ALOGE("%s: start voice call failed %d", __func__, error);
7713 }
7714 } else {
7715 adev->current_call_output = adev->voice_tx_output;
7716 voice_update_devices_for_all_voice_usecases(adev);
7717 }
7718 }
7719
7720 pthread_mutex_unlock(&adev->lock);
7721 pthread_mutex_unlock(&in->lock);
7722}
7723
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307724int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07007725 audio_io_handle_t handle,
7726 audio_devices_t devices,
7727 audio_output_flags_t flags,
7728 struct audio_config *config,
7729 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04007730 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007731{
7732 struct audio_device *adev = (struct audio_device *)dev;
7733 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05307734 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007735 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007736 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05307737 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007738 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
7739 bool is_usb_dev = audio_is_usb_out_device(devices) &&
7740 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
7741 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007742 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07007743 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
7744 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007745 bool force_haptic_path =
7746 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007747 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08007748#ifdef AUDIO_GKI_ENABLED
7749 __s32 *generic_dec;
7750#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007751
kunleizdff872d2018-08-20 14:40:33 +08007752 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007753 is_usb_dev = false;
7754 devices = AUDIO_DEVICE_OUT_SPEAKER;
7755 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
7756 __func__, devices);
Mingshu Pangdbd20562019-11-25 18:04:39 +08007757 if (config->format == AUDIO_FORMAT_DEFAULT)
7758 config->format = AUDIO_FORMAT_PCM_16_BIT;
7759 if (config->sample_rate == 0)
7760 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7761 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7762 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
kunleizd6a9e0c2018-07-30 15:38:52 +08007763 }
7764
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007765 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05307766
Rahul Sharma99770982019-03-06 17:05:26 +05307767 pthread_mutex_lock(&adev->lock);
7768 if (out_get_stream(adev, handle) != NULL) {
7769 ALOGW("%s, output stream already opened", __func__);
7770 ret = -EEXIST;
7771 }
7772 pthread_mutex_unlock(&adev->lock);
7773 if (ret)
7774 return ret;
7775
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007776 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
7777
Mingming Yin3a941d42016-02-17 18:08:05 -08007778 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04007779 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
7780 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307781
7782
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007783 if (!out) {
7784 return -ENOMEM;
7785 }
7786
Haynes Mathew George204045b2015-02-25 20:32:03 -08007787 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007788 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Weiyin Jiang280ea742020-09-08 20:28:22 +08007789 pthread_mutex_init(&out->latch_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08007790 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08007791 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
7792
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007793 if (devices == AUDIO_DEVICE_NONE)
7794 devices = AUDIO_DEVICE_OUT_SPEAKER;
7795
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007796 out->flags = flags;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007797 list_init(&out->device_list);
7798 update_device_list(&out->device_list, devices, address, true /* add devices */);
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07007799 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07007800 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007801 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05307802 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05307803 if (out->channel_mask == AUDIO_CHANNEL_NONE)
7804 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
7805 else
7806 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07007807 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007808 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08007809 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307810 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307811 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307812 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007813 out->hal_output_suspend_supported = 0;
7814 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05307815 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05307816 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05307817 out->pspd_coeff_sent = false;
Phil Burkd898ba62019-06-20 12:49:01 -07007818 out->mmap_shared_memory_fd = -1; // not open
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007819
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05307820 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05307821 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07007822 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
7823
Aalique Grahame22e49102018-12-18 14:23:57 -08007824 if (direct_dev &&
7825 (audio_is_linear_pcm(out->format) ||
7826 config->format == AUDIO_FORMAT_DEFAULT) &&
7827 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
7828 audio_format_t req_format = config->format;
7829 audio_channel_mask_t req_channel_mask = config->channel_mask;
7830 uint32_t req_sample_rate = config->sample_rate;
7831
7832 pthread_mutex_lock(&adev->lock);
7833 if (is_hdmi) {
7834 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
7835 ret = read_hdmi_sink_caps(out);
7836 if (config->sample_rate == 0)
7837 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7838 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7839 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
7840 if (config->format == AUDIO_FORMAT_DEFAULT)
7841 config->format = AUDIO_FORMAT_PCM_16_BIT;
7842 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007843 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
7844 &config->format,
7845 &out->supported_formats[0],
7846 MAX_SUPPORTED_FORMATS,
7847 &config->channel_mask,
7848 &out->supported_channel_masks[0],
7849 MAX_SUPPORTED_CHANNEL_MASKS,
7850 &config->sample_rate,
7851 &out->supported_sample_rates[0],
7852 MAX_SUPPORTED_SAMPLE_RATES);
7853 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007854 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007855
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007856 pthread_mutex_unlock(&adev->lock);
7857 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007858 if (ret == -ENOSYS) {
7859 /* ignore and go with default */
7860 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007861 }
7862 // For MMAP NO IRQ, allow conversions in ADSP
7863 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
7864 goto error_open;
7865 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007866 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08007867 goto error_open;
7868 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007869
7870 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
7871 config->sample_rate = req_sample_rate;
7872 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
7873 config->channel_mask = req_channel_mask;
7874 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
7875 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08007876 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007877
7878 out->sample_rate = config->sample_rate;
7879 out->channel_mask = config->channel_mask;
7880 out->format = config->format;
7881 if (is_hdmi) {
7882 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7883 out->config = pcm_config_hdmi_multi;
7884 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7885 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7886 out->config = pcm_config_mmap_playback;
7887 out->stream.start = out_start;
7888 out->stream.stop = out_stop;
7889 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7890 out->stream.get_mmap_position = out_get_mmap_position;
7891 } else {
7892 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7893 out->config = pcm_config_hifi;
7894 }
7895
7896 out->config.rate = out->sample_rate;
7897 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7898 if (is_hdmi) {
7899 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7900 audio_bytes_per_sample(out->format));
7901 }
7902 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08007903 }
7904
Derek Chenf6318be2017-06-12 17:16:24 -04007905 /* validate bus device address */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007906 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04007907 /* extract car audio stream index */
7908 out->car_audio_stream =
7909 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
7910 if (out->car_audio_stream < 0) {
7911 ALOGE("%s: invalid car audio stream %x",
7912 __func__, out->car_audio_stream);
7913 ret = -EINVAL;
7914 goto error_open;
7915 }
Derek Chen5f67a942020-02-24 23:08:13 -08007916 ALOGV("%s: car_audio_stream %x", __func__, out->car_audio_stream);
Derek Chenf6318be2017-06-12 17:16:24 -04007917 }
7918
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007919 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007920 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007921 if (!voice_extn_is_compress_voip_supported()) {
7922 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
7923 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07007924 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
Lakshman Chaluvarajue7fc9482020-05-30 14:29:29 +05307925 config->channel_mask : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007926 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
7927 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07007928 out->volume_l = INVALID_OUT_VOLUME;
7929 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07007930
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007931 out->config = default_pcm_config_voip_copp;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007932 out->config.rate = out->sample_rate;
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007933 uint32_t channel_count =
7934 audio_channel_count_from_out_mask(out->channel_mask);
Ramjee Singh968858a2020-08-06 16:30:48 +05307935 out->config.channels = channel_count;
7936
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007937 uint32_t buffer_size = get_stream_buffer_size(DEFAULT_VOIP_BUF_DURATION_MS,
7938 out->sample_rate, out->format,
7939 channel_count, false);
7940 uint32_t frame_size = audio_bytes_per_sample(out->format) * channel_count;
7941 if (frame_size != 0)
7942 out->config.period_size = buffer_size / frame_size;
7943 else
7944 ALOGW("%s: frame size is 0 for format %#x", __func__, out->format);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007945 }
7946 } else {
7947 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7948 voice_extn_compress_voip_is_active(out->dev)) &&
7949 (voice_extn_compress_voip_is_config_supported(config))) {
7950 ret = voice_extn_compress_voip_open_output_stream(out);
7951 if (ret != 0) {
7952 ALOGE("%s: Compress voip output cannot be opened, error:%d",
7953 __func__, ret);
7954 goto error_open;
7955 }
Sujin Panicker19027262019-09-16 18:28:06 +05307956 } else {
7957 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
7958 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007959 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007960 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007961 } else if (audio_is_linear_pcm(out->format) &&
7962 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
7963 out->channel_mask = config->channel_mask;
7964 out->sample_rate = config->sample_rate;
7965 out->format = config->format;
7966 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7967 // does this change?
7968 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
7969 out->config.rate = config->sample_rate;
7970 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7971 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7972 audio_bytes_per_sample(config->format));
7973 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07007974 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307975 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307976 pthread_mutex_lock(&adev->lock);
7977 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
7978 pthread_mutex_unlock(&adev->lock);
7979
7980 // reject offload during card offline to allow
7981 // fallback to s/w paths
7982 if (offline) {
7983 ret = -ENODEV;
7984 goto error_open;
7985 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007986
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007987 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
7988 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
7989 ALOGE("%s: Unsupported Offload information", __func__);
7990 ret = -EINVAL;
7991 goto error_open;
7992 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007993
Atul Khare3fa6e542017-08-09 00:56:17 +05307994 if (config->offload_info.format == 0)
7995 config->offload_info.format = config->format;
7996 if (config->offload_info.sample_rate == 0)
7997 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007998
Mingming Yin90310102013-11-13 16:57:00 -08007999 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308000 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07008001 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008002 ret = -EINVAL;
8003 goto error_open;
8004 }
8005
Ben Romberger0f8c87b2017-05-24 17:41:11 -07008006 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
8007 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
8008 (audio_extn_passthru_is_passthrough_stream(out)) &&
8009 !((config->sample_rate == 48000) ||
8010 (config->sample_rate == 96000) ||
8011 (config->sample_rate == 192000))) {
8012 ALOGE("%s: Unsupported sample rate %d for audio format %x",
8013 __func__, config->sample_rate, config->offload_info.format);
8014 ret = -EINVAL;
8015 goto error_open;
8016 }
8017
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008018 out->compr_config.codec = (struct snd_codec *)
8019 calloc(1, sizeof(struct snd_codec));
8020
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008021 if (!out->compr_config.codec) {
8022 ret = -ENOMEM;
8023 goto error_open;
8024 }
8025
Dhananjay Kumarac341582017-02-23 23:42:25 +05308026 out->stream.pause = out_pause;
8027 out->stream.resume = out_resume;
8028 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05308029 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05308030 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07008031 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05308032 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07008033 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05308034 } else {
8035 out->usecase = get_offload_usecase(adev, false /* is_compress */);
8036 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07008037 }
vivek mehta446c3962015-09-14 10:57:35 -07008038
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308039 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8040 ALOGD("%s: Setting latency mode to true", __func__);
Meng Wang4c32fb42020-01-16 17:57:11 +08008041#ifdef AUDIO_GKI_ENABLED
8042 /* out->compr_config.codec->reserved[1] is for flags */
8043 out->compr_config.codec->reserved[1] |= audio_extn_utils_get_perf_mode_flag();
8044#else
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308045 out->compr_config.codec->flags |= audio_extn_utils_get_perf_mode_flag();
Meng Wang4c32fb42020-01-16 17:57:11 +08008046#endif
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308047 }
8048
vivek mehta446c3962015-09-14 10:57:35 -07008049 if (out->usecase == USECASE_INVALID) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008050 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Mingming Yin3a941d42016-02-17 18:08:05 -08008051 config->format == 0 && config->sample_rate == 0 &&
8052 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07008053 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08008054 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
8055 } else {
8056 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
8057 ret = -EEXIST;
8058 goto error_open;
8059 }
vivek mehta446c3962015-09-14 10:57:35 -07008060 }
8061
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008062 if (config->offload_info.channel_mask)
8063 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008064 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008065 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008066 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008067 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05308068 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008069 ret = -EINVAL;
8070 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008071 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008072
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008073 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008074 out->sample_rate = config->offload_info.sample_rate;
8075
Mingming Yin3ee55c62014-08-04 14:23:35 -07008076 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008077
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308078 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05308079 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308080 audio_extn_dolby_send_ddp_endp_params(adev);
8081 audio_extn_dolby_set_dmid(adev);
8082 }
vivek mehta0ea887a2015-08-26 14:01:20 -07008083
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008084 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08008085 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008086 out->compr_config.codec->bit_rate =
8087 config->offload_info.bit_rate;
8088 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05308089 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008090 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05308091 /* Update bit width only for non passthrough usecases.
8092 * For passthrough usecases, the output will always be opened @16 bit
8093 */
8094 if (!audio_extn_passthru_is_passthrough_stream(out))
8095 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308096
8097 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
Meng Wang4c32fb42020-01-16 17:57:11 +08008098#ifdef AUDIO_GKI_ENABLED
8099 /* out->compr_config.codec->reserved[1] is for flags */
8100 out->compr_config.codec->reserved[1] |= COMPRESSED_TIMESTAMP_FLAG;
8101 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->reserved[1]);
8102#else
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308103 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
8104 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
Meng Wang4c32fb42020-01-16 17:57:11 +08008105#endif
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308106
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008107 /*TODO: Do we need to change it for passthrough */
8108 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008109
Manish Dewangana6fc5442015-08-24 20:30:31 +05308110 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
8111 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308112 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05308113 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308114 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
8115 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308116
8117 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
8118 AUDIO_FORMAT_PCM) {
8119
8120 /*Based on platform support, configure appropriate alsa format for corresponding
8121 *hal input format.
8122 */
8123 out->compr_config.codec->format = hal_format_to_alsa(
8124 config->offload_info.format);
8125
Ashish Jain83a6cc22016-06-28 14:34:17 +05308126 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05308127 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308128 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308129
Dhananjay Kumarac341582017-02-23 23:42:25 +05308130 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05308131 *hal input format and alsa format might differ based on platform support.
8132 */
8133 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05308134 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308135
8136 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
8137
Deeraj Soman93155a62019-09-30 19:00:37 +05308138 if (property_get_bool("vendor.audio.offload.buffer.duration.enabled", false)) {
8139 if ((config->offload_info.duration_us >= MIN_OFFLOAD_BUFFER_DURATION_MS * 1000) &&
8140 (config->offload_info.duration_us <= MAX_OFFLOAD_BUFFER_DURATION_MS * 1000))
8141 out->info.duration_us = (int64_t)config->offload_info.duration_us;
8142 }
Deeraj Soman65358ab2019-02-07 15:40:49 +05308143
Ashish Jainf1eaa582016-05-23 20:54:24 +05308144 /* Check if alsa session is configured with the same format as HAL input format,
8145 * if not then derive correct fragment size needed to accomodate the
8146 * conversion of HAL input format to alsa format.
8147 */
8148 audio_extn_utils_update_direct_pcm_fragment_size(out);
8149
8150 /*if hal input and output fragment size is different this indicates HAL input format is
8151 *not same as the alsa format
8152 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308153 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05308154 /*Allocate a buffer to convert input data to the alsa configured format.
8155 *size of convert buffer is equal to the size required to hold one fragment size
8156 *worth of pcm data, this is because flinger does not write more than fragment_size
8157 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308158 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
8159 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05308160 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
8161 ret = -ENOMEM;
8162 goto error_open;
8163 }
8164 }
8165 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
8166 out->compr_config.fragment_size =
8167 audio_extn_passthru_get_buffer_size(&config->offload_info);
8168 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8169 } else {
8170 out->compr_config.fragment_size =
8171 platform_get_compress_offload_buffer_size(&config->offload_info);
8172 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8173 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008174
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308175 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8176 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
8177 }
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008178 if (config->offload_info.format == AUDIO_FORMAT_FLAC) {
8179#ifdef AUDIO_GKI_ENABLED
8180 generic_dec =
8181 &(out->compr_config.codec->options.generic.reserved[1]);
8182 ((struct snd_generic_dec_flac *)generic_dec)->sample_size =
8183 AUDIO_OUTPUT_BIT_WIDTH;
8184#else
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05308185 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008186#endif
8187 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008188
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05308189 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
8190 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
8191 }
8192
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008193 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
8194 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008195
Manish Dewangan69426c82017-01-30 17:35:36 +05308196 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
8197 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
8198 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
8199 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8200 out->render_mode = RENDER_MODE_AUDIO_MASTER;
8201 } else {
8202 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
8203 }
Alexy Josephaa54c872014-12-03 02:46:47 -08008204
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05308205 memset(&out->channel_map_param, 0,
8206 sizeof(struct audio_out_channel_map_param));
8207
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008208 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05308209 out->send_next_track_params = false;
8210 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008211 out->offload_state = OFFLOAD_STATE_IDLE;
8212 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08008213 out->writeAt.tv_sec = 0;
8214 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008215
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008216 audio_extn_dts_create_state_notifier_node(out->usecase);
8217
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008218 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
8219 __func__, config->offload_info.version,
8220 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05308221
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308222 /* Check if DSD audio format is supported in codec
8223 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308224 */
8225
8226 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308227 (!platform_check_codec_dsd_support(adev->platform) ||
8228 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308229 ret = -EINVAL;
8230 goto error_open;
8231 }
8232
Ashish Jain5106d362016-05-11 19:23:33 +05308233 /* Disable gapless if any of the following is true
8234 * passthrough playback
8235 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05308236 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05308237 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308238 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308239 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07008240 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308241 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308242 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05308243 check_and_set_gapless_mode(adev, false);
8244 } else
8245 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07008246
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308247 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07008248 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
8249 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308250 if (config->format == AUDIO_FORMAT_DSD) {
8251 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
Meng Wang4c32fb42020-01-16 17:57:11 +08008252#ifdef AUDIO_GKI_ENABLED
8253 /* out->compr_config.codec->reserved[0] is for compr_passthr */
8254 out->compr_config.codec->reserved[0] = PASSTHROUGH_DSD;
8255#else
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308256 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
Meng Wang4c32fb42020-01-16 17:57:11 +08008257#endif
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308258 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07008259
8260 create_offload_callback_thread(out);
8261
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008262 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008263 switch (config->sample_rate) {
8264 case 0:
8265 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8266 break;
8267 case 8000:
8268 case 16000:
8269 case 48000:
8270 out->sample_rate = config->sample_rate;
8271 break;
8272 default:
8273 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
8274 config->sample_rate);
8275 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8276 ret = -EINVAL;
8277 goto error_open;
8278 }
8279 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8280 switch (config->channel_mask) {
8281 case AUDIO_CHANNEL_NONE:
8282 case AUDIO_CHANNEL_OUT_STEREO:
8283 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8284 break;
8285 default:
8286 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
8287 config->channel_mask);
8288 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8289 ret = -EINVAL;
8290 goto error_open;
8291 }
8292 switch (config->format) {
8293 case AUDIO_FORMAT_DEFAULT:
8294 case AUDIO_FORMAT_PCM_16_BIT:
8295 out->format = AUDIO_FORMAT_PCM_16_BIT;
8296 break;
8297 default:
8298 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
8299 config->format);
8300 config->format = AUDIO_FORMAT_PCM_16_BIT;
8301 ret = -EINVAL;
8302 goto error_open;
8303 }
8304
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05308305 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008306 if (ret != 0) {
8307 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008308 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008309 goto error_open;
8310 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008311 } else if (is_single_device_type_equal(&out->device_list,
8312 AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08008313 switch (config->sample_rate) {
8314 case 0:
8315 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
8316 break;
8317 case 8000:
8318 case 16000:
8319 case 48000:
8320 out->sample_rate = config->sample_rate;
8321 break;
8322 default:
8323 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
8324 config->sample_rate);
8325 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8326 ret = -EINVAL;
8327 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008328 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008329 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8330 switch (config->channel_mask) {
8331 case AUDIO_CHANNEL_NONE:
8332 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8333 break;
8334 case AUDIO_CHANNEL_OUT_STEREO:
8335 out->channel_mask = config->channel_mask;
8336 break;
8337 default:
8338 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
8339 config->channel_mask);
8340 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8341 ret = -EINVAL;
8342 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008343 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008344 switch (config->format) {
8345 case AUDIO_FORMAT_DEFAULT:
8346 out->format = AUDIO_FORMAT_PCM_16_BIT;
8347 break;
8348 case AUDIO_FORMAT_PCM_16_BIT:
8349 out->format = config->format;
8350 break;
8351 default:
8352 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
8353 config->format);
8354 config->format = AUDIO_FORMAT_PCM_16_BIT;
8355 ret = -EINVAL;
8356 break;
8357 }
8358 if (ret != 0)
8359 goto error_open;
8360
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008361 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
8362 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08008363 out->config.rate = out->sample_rate;
8364 out->config.channels =
8365 audio_channel_count_from_out_mask(out->channel_mask);
8366 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008367 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008368 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05308369 unsigned int channels = 0;
8370 /*Update config params to default if not set by the caller*/
8371 if (config->sample_rate == 0)
8372 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8373 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8374 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8375 if (config->format == AUDIO_FORMAT_DEFAULT)
8376 config->format = AUDIO_FORMAT_PCM_16_BIT;
8377
8378 channels = audio_channel_count_from_out_mask(out->channel_mask);
8379
Varun Balaraje49253e2017-07-06 19:48:56 +05308380 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
8381 out->usecase = get_interactive_usecase(adev);
8382 out->config = pcm_config_low_latency;
8383 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05308384 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008385 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
8386 out->flags);
8387 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07008388 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8389 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8390 out->config = pcm_config_mmap_playback;
8391 out->stream.start = out_start;
8392 out->stream.stop = out_stop;
8393 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8394 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308395 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8396 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008397 out->hal_output_suspend_supported =
8398 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
8399 out->dynamic_pm_qos_config_supported =
8400 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
8401 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08008402 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
8403 } else {
8404 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
8405 //the mixer path will be a string similar to "low-latency-playback resume"
8406 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
8407 strlcat(out->pm_qos_mixer_path,
8408 " resume", MAX_MIXER_PATH_LEN);
8409 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
8410 out->pm_qos_mixer_path);
8411 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308412 out->config = pcm_config_low_latency;
8413 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
8414 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
8415 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05308416 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
8417 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
8418 if (out->config.period_size <= 0) {
8419 ALOGE("Invalid configuration period size is not valid");
8420 ret = -EINVAL;
8421 goto error_open;
8422 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008423 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
8424 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
8425 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008426 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
8427 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
8428 out->config = pcm_config_haptics_audio;
8429 if (force_haptic_path)
8430 adev->haptics_config = pcm_config_haptics_audio;
8431 else
8432 adev->haptics_config = pcm_config_haptics;
8433
Meng Wangd08ce322020-04-02 08:59:20 +08008434 channels =
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008435 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
8436
8437 if (force_haptic_path) {
8438 out->config.channels = 1;
8439 adev->haptics_config.channels = 1;
8440 } else
8441 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 -08008442 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008443 ret = audio_extn_auto_hal_open_output_stream(out);
8444 if (ret) {
8445 ALOGE("%s: Failed to open output stream for bus device", __func__);
8446 ret = -EINVAL;
8447 goto error_open;
8448 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308449 } else {
8450 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008451 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8452 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308453 }
8454 out->hal_ip_format = format = out->format;
8455 out->config.format = hal_format_to_pcm(out->hal_ip_format);
8456 out->hal_op_format = pcm_format_to_hal(out->config.format);
8457 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
8458 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008459 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05308460 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308461 if (out->hal_ip_format != out->hal_op_format) {
8462 uint32_t buffer_size = out->config.period_size *
8463 format_to_bitwidth_table[out->hal_op_format] *
8464 out->config.channels;
8465 out->convert_buffer = calloc(1, buffer_size);
8466 if (out->convert_buffer == NULL){
8467 ALOGE("Allocation failed for convert buffer for size %d",
8468 out->compr_config.fragment_size);
8469 ret = -ENOMEM;
8470 goto error_open;
8471 }
8472 ALOGD("Convert buffer allocated of size %d", buffer_size);
8473 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008474 }
8475
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008476 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
8477 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308478
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008479 /* TODO remove this hardcoding and check why width is zero*/
8480 if (out->bit_width == 0)
8481 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308482 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008483 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008484 &out->device_list, out->flags,
8485 out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05308486 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05308487 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08008488 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08008489 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
8490 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008491 if(adev->primary_output == NULL)
8492 adev->primary_output = out;
8493 else {
8494 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008495 ret = -EEXIST;
8496 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008497 }
8498 }
8499
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008500 /* Check if this usecase is already existing */
8501 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07008502 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
8503 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008504 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008505 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008506 ret = -EEXIST;
8507 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008508 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008509
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008510 pthread_mutex_unlock(&adev->lock);
8511
8512 out->stream.common.get_sample_rate = out_get_sample_rate;
8513 out->stream.common.set_sample_rate = out_set_sample_rate;
8514 out->stream.common.get_buffer_size = out_get_buffer_size;
8515 out->stream.common.get_channels = out_get_channels;
8516 out->stream.common.get_format = out_get_format;
8517 out->stream.common.set_format = out_set_format;
8518 out->stream.common.standby = out_standby;
8519 out->stream.common.dump = out_dump;
8520 out->stream.common.set_parameters = out_set_parameters;
8521 out->stream.common.get_parameters = out_get_parameters;
8522 out->stream.common.add_audio_effect = out_add_audio_effect;
8523 out->stream.common.remove_audio_effect = out_remove_audio_effect;
8524 out->stream.get_latency = out_get_latency;
8525 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08008526#ifdef NO_AUDIO_OUT
8527 out->stream.write = out_write_for_no_output;
8528#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008529 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08008530#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008531 out->stream.get_render_position = out_get_render_position;
8532 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008533 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008534
Haynes Mathew George16081042017-05-31 17:16:49 -07008535 if (out->realtime)
8536 out->af_period_multiplier = af_period_multiplier;
8537 else
8538 out->af_period_multiplier = 1;
8539
Andy Hunga1f48fa2019-07-01 18:14:53 -07008540 out->kernel_buffer_size = out->config.period_size * out->config.period_count;
8541
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008542 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07008543 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008544 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008545
8546 config->format = out->stream.common.get_format(&out->stream.common);
8547 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
8548 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308549 register_format(out->format, out->supported_formats);
8550 register_channel_mask(out->channel_mask, out->supported_channel_masks);
8551 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008552
Aalique Grahame22e49102018-12-18 14:23:57 -08008553 out->error_log = error_log_create(
8554 ERROR_LOG_ENTRIES,
8555 1000000000 /* aggregate consecutive identical errors within one second in ns */);
8556
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308557 /*
8558 By locking output stream before registering, we allow the callback
8559 to update stream's state only after stream's initial state is set to
8560 adev state.
8561 */
8562 lock_output_stream(out);
8563 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
8564 pthread_mutex_lock(&adev->lock);
8565 out->card_status = adev->card_status;
8566 pthread_mutex_unlock(&adev->lock);
8567 pthread_mutex_unlock(&out->lock);
8568
Aalique Grahame22e49102018-12-18 14:23:57 -08008569 stream_app_type_cfg_init(&out->app_type_cfg);
8570
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008571 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308572 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07008573 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008574
8575 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
8576 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
8577 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008578 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05308579 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008580 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07008581 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05308582 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
8583 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008584 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
8585 out->usecase, PCM_PLAYBACK);
8586 hdlr_stream_cfg.flags = out->flags;
8587 hdlr_stream_cfg.type = PCM_PLAYBACK;
8588 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
8589 &hdlr_stream_cfg);
8590 if (ret) {
8591 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
8592 out->adsp_hdlr_stream_handle = NULL;
8593 }
8594 }
Gangadhar Sb0210342019-02-22 17:39:41 +05308595 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
8596 is_direct_passthough, false);
8597 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
8598 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07008599 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07008600 if (ret < 0) {
8601 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
8602 out->ip_hdlr_handle = NULL;
8603 }
8604 }
Derek Chenf939fb72018-11-13 13:34:41 -08008605
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008606 ret = io_streams_map_insert(adev, &out->stream.common,
8607 out->handle, AUDIO_PATCH_HANDLE_NONE);
8608 if (ret != 0)
8609 goto error_open;
8610
Derek Chenf939fb72018-11-13 13:34:41 -08008611 streams_output_ctxt_t *out_ctxt = (streams_output_ctxt_t *)
8612 calloc(1, sizeof(streams_output_ctxt_t));
8613 if (out_ctxt == NULL) {
8614 ALOGE("%s fail to allocate output ctxt", __func__);
8615 ret = -ENOMEM;
8616 goto error_open;
8617 }
8618 out_ctxt->output = out;
8619
8620 pthread_mutex_lock(&adev->lock);
8621 list_add_tail(&adev->active_outputs_list, &out_ctxt->list);
8622 pthread_mutex_unlock(&adev->lock);
8623
Eric Laurent994a6932013-07-17 11:51:42 -07008624 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008625 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008626
8627error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05308628 if (out->convert_buffer)
8629 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008630 free(out);
8631 *stream_out = NULL;
8632 ALOGD("%s: exit: ret %d", __func__, ret);
8633 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008634}
8635
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308636void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008637 struct audio_stream_out *stream)
8638{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008639 struct stream_out *out = (struct stream_out *)stream;
8640 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008641 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008642
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008643 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308644
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008645 io_streams_map_remove(adev, out->handle);
8646
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308647 // must deregister from sndmonitor first to prevent races
8648 // between the callback and close_stream
8649 audio_extn_snd_mon_unregister_listener(out);
8650
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008651 /* close adsp hdrl session before standby */
8652 if (out->adsp_hdlr_stream_handle) {
8653 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
8654 if (ret)
8655 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
8656 out->adsp_hdlr_stream_handle = NULL;
8657 }
8658
Manish Dewangan21a850a2017-08-14 12:03:55 +05308659 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07008660 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
8661 out->ip_hdlr_handle = NULL;
8662 }
8663
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008664 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308665 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008666 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308667 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308668 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008669 if(ret != 0)
8670 ALOGE("%s: Compress voip output cannot be closed, error:%d",
8671 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008672 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008673 out_standby(&stream->common);
8674
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008675 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008676 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008677 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008678 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008679 if (out->compr_config.codec != NULL)
8680 free(out->compr_config.codec);
8681 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008682
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05308683 out->a2dp_compress_mute = false;
8684
Varun Balaraje49253e2017-07-06 19:48:56 +05308685 if (is_interactive_usecase(out->usecase))
8686 free_interactive_usecase(adev, out->usecase);
8687
Ashish Jain83a6cc22016-06-28 14:34:17 +05308688 if (out->convert_buffer != NULL) {
8689 free(out->convert_buffer);
8690 out->convert_buffer = NULL;
8691 }
8692
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008693 if (adev->voice_tx_output == out)
8694 adev->voice_tx_output = NULL;
8695
Aalique Grahame22e49102018-12-18 14:23:57 -08008696 error_log_destroy(out->error_log);
8697 out->error_log = NULL;
8698
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05308699 if (adev->primary_output == out)
8700 adev->primary_output = NULL;
8701
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008702 pthread_cond_destroy(&out->cond);
8703 pthread_mutex_destroy(&out->lock);
Weiyin Jiang280ea742020-09-08 20:28:22 +08008704 pthread_mutex_destroy(&out->pre_lock);
8705 pthread_mutex_destroy(&out->latch_lock);
8706 pthread_mutex_destroy(&out->position_query_lock);
Derek Chenf939fb72018-11-13 13:34:41 -08008707
8708 pthread_mutex_lock(&adev->lock);
8709 streams_output_ctxt_t *out_ctxt = out_get_stream(adev, out->handle);
8710 if (out_ctxt != NULL) {
8711 list_remove(&out_ctxt->list);
8712 free(out_ctxt);
8713 } else {
8714 ALOGW("%s, output stream already closed", __func__);
8715 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008716 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08008717 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07008718 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008719}
8720
8721static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
8722{
8723 struct audio_device *adev = (struct audio_device *)dev;
8724 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008725 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008726 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008727 int ret;
8728 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08008729 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008730 struct listnode *node;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008731 int controller = -1, stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008732
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008733 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008734 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008735
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308736 if (!parms)
8737 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05308738
Derek Chen6f293672019-04-01 01:40:24 -07008739 /* notify adev and input/output streams on the snd card status */
8740 adev_snd_mon_cb((void *)adev, parms);
8741
8742 list_for_each(node, &adev->active_outputs_list) {
8743 streams_output_ctxt_t *out_ctxt = node_to_item(node,
8744 streams_output_ctxt_t,
8745 list);
8746 out_snd_mon_cb((void *)out_ctxt->output, parms);
8747 }
8748
8749 list_for_each(node, &adev->active_inputs_list) {
8750 streams_input_ctxt_t *in_ctxt = node_to_item(node,
8751 streams_input_ctxt_t,
8752 list);
8753 in_snd_mon_cb((void *)in_ctxt->input, parms);
8754 }
8755
Zhou Songd6d71752019-05-21 18:08:51 +08008756 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308757 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
8758 if (ret >= 0) {
8759 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08008760 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308761 adev->bt_sco_on = true;
Zhou Songd6d71752019-05-21 18:08:51 +08008762 } else {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308763 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008764 audio_extn_sco_reset_configuration();
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008765 }
8766 }
8767
8768 ret = str_parms_get_str(parms, "A2dpSuspended", value, sizeof(value));
Weiyin Jiang280ea742020-09-08 20:28:22 +08008769 if (ret >= 0) {
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008770 if (!strncmp(value, "false", 5) &&
8771 audio_extn_a2dp_source_is_suspended()) {
8772 struct audio_usecase *usecase;
8773 struct listnode *node;
Zhou Songd6d71752019-05-21 18:08:51 +08008774 list_for_each(node, &adev->usecase_list) {
8775 usecase = node_to_item(node, struct audio_usecase, list);
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008776 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008777 is_sco_in_device_type(&usecase->stream.in->device_list)) {
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008778 ALOGD("a2dp resumed, switch bt sco mic to handset mic");
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008779 reassign_device_list(&usecase->stream.in->device_list,
8780 AUDIO_DEVICE_IN_BUILTIN_MIC, "");
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008781 select_devices(adev, usecase->id);
8782 }
Zhou Songd6d71752019-05-21 18:08:51 +08008783 }
8784 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308785 }
8786
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008787 status = voice_set_parameters(adev, parms);
8788 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008789 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008790
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008791 status = platform_set_parameters(adev->platform, parms);
8792 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008793 goto done;
8794
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008795 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
8796 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07008797 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008798 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8799 adev->bluetooth_nrec = true;
8800 else
8801 adev->bluetooth_nrec = false;
8802 }
8803
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008804 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
8805 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008806 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8807 adev->screen_off = false;
8808 else
8809 adev->screen_off = true;
Quinn Male70f20f32019-06-26 16:50:26 -07008810 audio_extn_sound_trigger_update_screen_status(adev->screen_off);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008811 }
8812
Eric Laurent4b084132018-10-19 17:33:43 -07008813 ret = str_parms_get_int(parms, "rotation", &val);
8814 if (ret >= 0) {
8815 bool reverse_speakers = false;
8816 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8817 switch (val) {
8818 // FIXME: note that the code below assumes that the speakers are in the correct placement
8819 // relative to the user when the device is rotated 90deg from its default rotation. This
8820 // assumption is device-specific, not platform-specific like this code.
8821 case 270:
8822 reverse_speakers = true;
8823 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
8824 break;
8825 case 0:
8826 case 180:
8827 camera_rotation = CAMERA_ROTATION_PORTRAIT;
8828 break;
8829 case 90:
8830 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8831 break;
8832 default:
8833 ALOGE("%s: unexpected rotation of %d", __func__, val);
8834 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008835 }
Eric Laurent4b084132018-10-19 17:33:43 -07008836 if (status == 0) {
8837 // check and set swap
8838 // - check if orientation changed and speaker active
8839 // - set rotation and cache the rotation value
8840 adev->camera_orientation =
8841 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
8842 if (!audio_extn_is_maxx_audio_enabled())
8843 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
8844 }
8845 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008846
Mingming Yin514a8bc2014-07-29 15:22:21 -07008847 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
8848 if (ret >= 0) {
8849 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8850 adev->bt_wb_speech_enabled = true;
8851 else
8852 adev->bt_wb_speech_enabled = false;
8853 }
8854
Zhou Song12c29502019-03-16 10:37:18 +08008855 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
8856 if (ret >= 0) {
8857 val = atoi(value);
8858 adev->swb_speech_mode = val;
8859 }
8860
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008861 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
8862 if (ret >= 0) {
8863 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308864 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08008865 if (audio_is_output_device(val) &&
8866 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008867 ALOGV("cache new ext disp type and edid");
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008868 platform_get_controller_stream_from_params(parms, &controller, &stream);
8869 platform_set_ext_display_device_v2(adev->platform, controller, stream);
8870 ret = platform_get_ext_disp_type_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008871 if (ret < 0) {
8872 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05308873 } else {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008874 platform_cache_edid_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008875 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308876 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07008877 /*
8878 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
8879 * Per AudioPolicyManager, USB device is higher priority than WFD.
8880 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
8881 * If WFD use case occupies AFE proxy, it may result unintended behavior while
8882 * starting voice call on USB
8883 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008884 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308885 if (ret >= 0)
8886 audio_extn_usb_add_device(device, atoi(value));
8887
Zhou Song6f862822017-11-06 17:27:57 +08008888 if (!audio_extn_usb_is_tunnel_supported()) {
8889 ALOGV("detected USB connect .. disable proxy");
8890 adev->allow_afe_proxy_usage = false;
8891 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008892 }
8893 }
8894
8895 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
8896 if (ret >= 0) {
8897 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308898 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07008899 /*
8900 * The HDMI / Displayport disconnect handling has been moved to
8901 * audio extension to ensure that its parameters are not
8902 * invalidated prior to updating sysfs of the disconnect event
8903 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
8904 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308905 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008906 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308907 if (ret >= 0)
8908 audio_extn_usb_remove_device(device, atoi(value));
8909
Zhou Song6f862822017-11-06 17:27:57 +08008910 if (!audio_extn_usb_is_tunnel_supported()) {
8911 ALOGV("detected USB disconnect .. enable proxy");
8912 adev->allow_afe_proxy_usage = true;
8913 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008914 }
8915 }
8916
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008917 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08008918
8919 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08008920 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308921 struct audio_usecase *usecase;
8922 struct listnode *node;
8923 list_for_each(node, &adev->usecase_list) {
8924 usecase = node_to_item(node, struct audio_usecase, list);
Weiyin Jiangff56ff32020-05-08 14:32:21 +08008925 if ((usecase->stream.out == NULL) || (usecase->type != PCM_PLAYBACK))
8926 continue;
8927
8928 if (is_a2dp_out_device_type(&usecase->device_list)) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308929 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308930 audio_extn_a2dp_set_handoff_mode(true);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308931 ALOGD("Switching to speaker and muting the stream before select_devices");
8932 check_a2dp_restore_l(adev, usecase->stream.out, false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308933 //force device switch to re configure encoder
8934 select_devices(adev, usecase->id);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308935 ALOGD("Unmuting the stream after select_devices");
Weiyin Jiang280ea742020-09-08 20:28:22 +08008936 pthread_mutex_lock(&usecase->stream.out->latch_lock);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308937 usecase->stream.out->a2dp_compress_mute = false;
Weiyin Jiang280ea742020-09-08 20:28:22 +08008938 out_set_compr_volume(&usecase->stream.out->stream,
8939 usecase->stream.out->volume_l,
8940 usecase->stream.out->volume_r);
8941 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308942 audio_extn_a2dp_set_handoff_mode(false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308943 break;
Zhou Songd01e7a22020-09-23 22:49:01 +08008944 } else if (is_offload_usecase(usecase->stream.out->usecase)) {
Weiyin Jiang280ea742020-09-08 20:28:22 +08008945 pthread_mutex_lock(&usecase->stream.out->latch_lock);
8946 if (usecase->stream.out->a2dp_compress_mute) {
8947 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
8948 reassign_device_list(&usecase->stream.out->device_list,
8949 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, "");
8950 check_a2dp_restore_l(adev, usecase->stream.out, true);
8951 break;
8952 }
8953 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308954 }
8955 }
8956 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008957
8958 //handle vr audio setparam
8959 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8960 value, sizeof(value));
8961 if (ret >= 0) {
8962 ALOGI("Setting vr mode to be %s", value);
8963 if (!strncmp(value, "true", 4)) {
8964 adev->vr_audio_mode_enabled = true;
8965 ALOGI("Setting vr mode to true");
8966 } else if (!strncmp(value, "false", 5)) {
8967 adev->vr_audio_mode_enabled = false;
8968 ALOGI("Setting vr mode to false");
8969 } else {
8970 ALOGI("wrong vr mode set");
8971 }
8972 }
8973
Eric Laurent4b084132018-10-19 17:33:43 -07008974 //FIXME: to be replaced by proper video capture properties API
8975 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
8976 if (ret >= 0) {
8977 int camera_facing = CAMERA_FACING_BACK;
8978 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
8979 camera_facing = CAMERA_FACING_FRONT;
8980 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
8981 camera_facing = CAMERA_FACING_BACK;
8982 else {
8983 ALOGW("%s: invalid camera facing value: %s", __func__, value);
8984 goto done;
8985 }
8986 adev->camera_orientation =
8987 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
8988 struct audio_usecase *usecase;
8989 struct listnode *node;
8990 list_for_each(node, &adev->usecase_list) {
8991 usecase = node_to_item(node, struct audio_usecase, list);
8992 struct stream_in *in = usecase->stream.in;
8993 if (usecase->type == PCM_CAPTURE && in != NULL &&
8994 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
8995 select_devices(adev, in->usecase);
8996 }
8997 }
8998 }
8999
Naresh Tannirucd2353e2016-08-19 00:37:25 +05309000 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08009001done:
9002 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009003 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05309004error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009005 ALOGV("%s: exit with code(%d)", __func__, status);
9006 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009007}
9008
9009static char* adev_get_parameters(const struct audio_hw_device *dev,
9010 const char *keys)
9011{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05309012 ALOGD("%s:%s", __func__, keys);
9013
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009014 struct audio_device *adev = (struct audio_device *)dev;
9015 struct str_parms *reply = str_parms_create();
9016 struct str_parms *query = str_parms_create_str(keys);
9017 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05309018 char value[256] = {0};
9019 int ret = 0;
9020
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009021 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08009022 if (reply) {
9023 str_parms_destroy(reply);
9024 }
9025 if (query) {
9026 str_parms_destroy(query);
9027 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009028 ALOGE("adev_get_parameters: failed to create query or reply");
9029 return NULL;
9030 }
9031
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009032 //handle vr audio getparam
9033
9034 ret = str_parms_get_str(query,
9035 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9036 value, sizeof(value));
9037
9038 if (ret >= 0) {
9039 bool vr_audio_enabled = false;
9040 pthread_mutex_lock(&adev->lock);
9041 vr_audio_enabled = adev->vr_audio_mode_enabled;
9042 pthread_mutex_unlock(&adev->lock);
9043
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07009044 ALOGV("getting vr mode to %d", vr_audio_enabled);
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009045
9046 if (vr_audio_enabled) {
9047 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9048 "true");
9049 goto exit;
9050 } else {
9051 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9052 "false");
9053 goto exit;
9054 }
9055 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009056
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009057 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009058 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08009059 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08009060 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009061 platform_get_parameters(adev->platform, query, reply);
justinwengd5395152019-11-04 12:23:09 +08009062 audio_extn_ma_get_parameters(adev, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05309063 pthread_mutex_unlock(&adev->lock);
9064
Naresh Tannirud7205b62014-06-20 02:54:48 +05309065exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009066 str = str_parms_to_str(reply);
9067 str_parms_destroy(query);
9068 str_parms_destroy(reply);
9069
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07009070 ALOGV("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009071 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009072}
9073
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009074static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009075{
9076 return 0;
9077}
9078
9079static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
9080{
Haynes Mathew George5191a852013-09-11 14:19:36 -07009081 int ret;
9082 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08009083
9084 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
9085
Haynes Mathew George5191a852013-09-11 14:19:36 -07009086 pthread_mutex_lock(&adev->lock);
9087 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07009088 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07009089 pthread_mutex_unlock(&adev->lock);
9090 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009091}
9092
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009093static int adev_set_master_volume(struct audio_hw_device *dev __unused,
9094 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009095{
9096 return -ENOSYS;
9097}
9098
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009099static int adev_get_master_volume(struct audio_hw_device *dev __unused,
9100 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009101{
9102 return -ENOSYS;
9103}
9104
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009105static int adev_set_master_mute(struct audio_hw_device *dev __unused,
9106 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009107{
9108 return -ENOSYS;
9109}
9110
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009111static int adev_get_master_mute(struct audio_hw_device *dev __unused,
9112 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009113{
9114 return -ENOSYS;
9115}
9116
9117static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
9118{
9119 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07009120 struct listnode *node;
9121 struct audio_usecase *usecase = NULL;
9122 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08009123
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009124 pthread_mutex_lock(&adev->lock);
9125 if (adev->mode != mode) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309126 ALOGD("%s: mode %d , prev_mode %d \n", __func__, mode , adev->mode);
9127 adev->prev_mode = adev->mode; /* prev_mode is kept to handle voip concurrency*/
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009128 adev->mode = mode;
Weiyin Jiang96b96f72020-09-22 16:48:19 +08009129 if (mode == AUDIO_MODE_CALL_SCREEN) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309130 adev->current_call_output = adev->primary_output;
9131 voice_start_call(adev);
9132 } else if (voice_is_in_call_or_call_screen(adev) &&
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08009133 (mode == AUDIO_MODE_NORMAL ||
9134 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07009135 list_for_each(node, &adev->usecase_list) {
9136 usecase = node_to_item(node, struct audio_usecase, list);
9137 if (usecase->type == VOICE_CALL)
9138 break;
9139 }
9140 if (usecase &&
9141 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
9142 ret = audio_extn_usb_check_and_set_svc_int(usecase,
9143 true);
9144 if (ret != 0) {
9145 /* default service interval was successfully updated,
9146 reopen USB backend with new service interval */
9147 check_usecases_codec_backend(adev,
9148 usecase,
9149 usecase->out_snd_device);
9150 }
9151 }
9152
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009153 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07009154 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009155 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08009156 // restore device for other active usecases after stop call
9157 list_for_each(node, &adev->usecase_list) {
9158 usecase = node_to_item(node, struct audio_usecase, list);
9159 select_devices(adev, usecase->id);
9160 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009161 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009162 }
9163 pthread_mutex_unlock(&adev->lock);
9164 return 0;
9165}
9166
9167static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
9168{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009169 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08009170 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009171
9172 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08009173 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009174 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009175
Derek Chend2530072014-11-24 12:39:14 -08009176 if (adev->ext_hw_plugin)
9177 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009178
9179 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009180 pthread_mutex_unlock(&adev->lock);
9181
9182 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009183}
9184
9185static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
9186{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009187 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009188 return 0;
9189}
9190
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009191static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009192 const struct audio_config *config)
9193{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009194 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009195
Aalique Grahame22e49102018-12-18 14:23:57 -08009196 /* Don't know if USB HIFI in this context so use true to be conservative */
9197 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9198 true /*is_usb_hifi */) != 0)
9199 return 0;
9200
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009201 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
9202 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009203}
9204
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009205static bool adev_input_allow_hifi_record(struct audio_device *adev,
9206 audio_devices_t devices,
9207 audio_input_flags_t flags,
9208 audio_source_t source) {
9209 const bool allowed = true;
9210
9211 if (!audio_is_usb_in_device(devices))
9212 return !allowed;
9213
9214 switch (flags) {
9215 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009216 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07009217 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
9218 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009219 default:
9220 return !allowed;
9221 }
9222
9223 switch (source) {
9224 case AUDIO_SOURCE_DEFAULT:
9225 case AUDIO_SOURCE_MIC:
9226 case AUDIO_SOURCE_UNPROCESSED:
9227 break;
9228 default:
9229 return !allowed;
9230 }
9231
9232 switch (adev->mode) {
9233 case 0:
9234 break;
9235 default:
9236 return !allowed;
9237 }
9238
9239 return allowed;
9240}
9241
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009242static int adev_update_voice_comm_input_stream(struct stream_in *in,
9243 struct audio_config *config)
9244{
9245 bool valid_rate = (config->sample_rate == 8000 ||
9246 config->sample_rate == 16000 ||
9247 config->sample_rate == 32000 ||
9248 config->sample_rate == 48000);
9249 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
9250
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009251 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08009252 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009253 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9254 in->config = default_pcm_config_voip_copp;
9255 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
9256 DEFAULT_VOIP_BUF_DURATION_MS,
9257 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009258 } else {
9259 ALOGW("%s No valid input in voip, use defaults"
9260 "sample rate %u, channel mask 0x%X",
9261 __func__, config->sample_rate, in->channel_mask);
9262 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009263 in->config.rate = config->sample_rate;
9264 in->sample_rate = config->sample_rate;
9265 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009266 //XXX needed for voice_extn_compress_voip_open_input_stream
9267 in->config.rate = config->sample_rate;
9268 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
Shalini Manjunathaa763cc42019-08-23 15:13:46 +05309269 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009270 voice_extn_compress_voip_is_active(in->dev)) &&
9271 (voice_extn_compress_voip_is_format_supported(in->format)) &&
9272 valid_rate && valid_ch) {
9273 voice_extn_compress_voip_open_input_stream(in);
9274 // update rate entries to match config from AF
9275 in->config.rate = config->sample_rate;
9276 in->sample_rate = config->sample_rate;
9277 } else {
9278 ALOGW("%s compress voip not active, use defaults", __func__);
9279 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009280 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009281 return 0;
9282}
9283
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009284static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07009285 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009286 audio_devices_t devices,
9287 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009288 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309289 audio_input_flags_t flags,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009290 const char *address,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009291 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009292{
9293 struct audio_device *adev = (struct audio_device *)dev;
9294 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009295 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009296 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009297 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05309298 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009299 bool is_usb_dev = audio_is_usb_in_device(devices);
9300 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
9301 devices,
9302 flags,
9303 source);
Andy Hung94320602018-10-29 18:31:12 -07009304 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
9305 " sample_rate %u, channel_mask %#x, format %#x",
9306 __func__, flags, is_usb_dev, may_use_hifi_record,
9307 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309308
kunleizdff872d2018-08-20 14:40:33 +08009309 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08009310 is_usb_dev = false;
9311 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
9312 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
9313 __func__, devices);
9314 }
9315
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009316 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009317
9318 if (!(is_usb_dev && may_use_hifi_record)) {
9319 if (config->sample_rate == 0)
9320 config->sample_rate = 48000;
9321 if (config->channel_mask == AUDIO_CHANNEL_NONE)
9322 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9323 if (config->format == AUDIO_FORMAT_DEFAULT)
9324 config->format = AUDIO_FORMAT_PCM_16_BIT;
9325
9326 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
9327
Aalique Grahame22e49102018-12-18 14:23:57 -08009328 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9329 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009330 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05309331 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009332
Rahul Sharma99770982019-03-06 17:05:26 +05309333 pthread_mutex_lock(&adev->lock);
9334 if (in_get_stream(adev, handle) != NULL) {
9335 ALOGW("%s, input stream already opened", __func__);
9336 ret = -EEXIST;
9337 }
9338 pthread_mutex_unlock(&adev->lock);
9339 if (ret)
9340 return ret;
9341
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009342 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009343
9344 if (!in) {
9345 ALOGE("failed to allocate input stream");
9346 return -ENOMEM;
9347 }
9348
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309349 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05309350 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
9351 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009352 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07009353 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009354
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009355 in->stream.common.get_sample_rate = in_get_sample_rate;
9356 in->stream.common.set_sample_rate = in_set_sample_rate;
9357 in->stream.common.get_buffer_size = in_get_buffer_size;
9358 in->stream.common.get_channels = in_get_channels;
9359 in->stream.common.get_format = in_get_format;
9360 in->stream.common.set_format = in_set_format;
9361 in->stream.common.standby = in_standby;
9362 in->stream.common.dump = in_dump;
9363 in->stream.common.set_parameters = in_set_parameters;
9364 in->stream.common.get_parameters = in_get_parameters;
9365 in->stream.common.add_audio_effect = in_add_audio_effect;
9366 in->stream.common.remove_audio_effect = in_remove_audio_effect;
9367 in->stream.set_gain = in_set_gain;
9368 in->stream.read = in_read;
9369 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08009370 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309371 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07009372 in->stream.set_microphone_direction = in_set_microphone_direction;
9373 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07009374 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009375
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009376 list_init(&in->device_list);
9377 update_device_list(&in->device_list, devices, address, true);
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009378 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009379 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009380 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009381 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009382 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07009383 in->bit_width = 16;
9384 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07009385 in->direction = MIC_DIRECTION_UNSPECIFIED;
9386 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08009387 list_init(&in->aec_list);
9388 list_init(&in->ns_list);
Phil Burkd898ba62019-06-20 12:49:01 -07009389 in->mmap_shared_memory_fd = -1; // not open
Haynes Mathew George46740472017-10-27 18:40:12 -07009390
Andy Hung94320602018-10-29 18:31:12 -07009391 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08009392 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
9393 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
9394 /* Force channel config requested to mono if incall
9395 record is being requested for only uplink/downlink */
9396 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
9397 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9398 ret = -EINVAL;
9399 goto err_open;
9400 }
9401 }
9402
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009403 if (is_usb_dev && may_use_hifi_record) {
9404 /* HiFi record selects an appropriate format, channel, rate combo
9405 depending on sink capabilities*/
9406 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
9407 &config->format,
9408 &in->supported_formats[0],
9409 MAX_SUPPORTED_FORMATS,
9410 &config->channel_mask,
9411 &in->supported_channel_masks[0],
9412 MAX_SUPPORTED_CHANNEL_MASKS,
9413 &config->sample_rate,
9414 &in->supported_sample_rates[0],
9415 MAX_SUPPORTED_SAMPLE_RATES);
9416 if (ret != 0) {
9417 ret = -EINVAL;
9418 goto err_open;
9419 }
9420 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009421 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309422 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05309423 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
9424 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
9425 in->config.format = PCM_FORMAT_S32_LE;
9426 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309427 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
9428 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
9429 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
9430 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
9431 bool ret_error = false;
9432 in->bit_width = 24;
9433 /* 24 bit is restricted to UNPROCESSED source only,also format supported
9434 from HAL is 24_packed and 8_24
9435 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
9436 24_packed return error indicating supported format is 24_packed
9437 *> In case of any other source requesting 24 bit or float return error
9438 indicating format supported is 16 bit only.
9439
9440 on error flinger will retry with supported format passed
9441 */
9442 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
9443 (source != AUDIO_SOURCE_CAMCORDER)) {
9444 config->format = AUDIO_FORMAT_PCM_16_BIT;
9445 if (config->sample_rate > 48000)
9446 config->sample_rate = 48000;
9447 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07009448 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
9449 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309450 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
9451 ret_error = true;
9452 }
9453
9454 if (ret_error) {
9455 ret = -EINVAL;
9456 goto err_open;
9457 }
9458 }
9459
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009460 in->channel_mask = config->channel_mask;
9461 in->format = config->format;
9462
9463 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309464
9465 if (in->source == AUDIO_SOURCE_FM_TUNER) {
9466 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
9467 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
9468 else {
9469 ret = -EINVAL;
9470 goto err_open;
9471 }
9472 }
9473
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009474 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Deeraj Somanfa377bf2019-02-06 12:57:59 +05309475 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
9476 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009477 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
9478 is_low_latency = true;
9479#if LOW_LATENCY_CAPTURE_USE_CASE
Revathi Uddarajud9f23d92020-07-27 10:55:06 +05309480 if ((flags & AUDIO_INPUT_FLAG_VOIP_TX) != 0)
9481 in->usecase = USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY;
9482 else
9483 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009484#endif
9485 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08009486 if (!in->realtime) {
9487 in->config = pcm_config_audio_capture;
9488 frame_size = audio_stream_in_frame_size(&in->stream);
9489 buffer_size = get_input_buffer_size(config->sample_rate,
9490 config->format,
9491 channel_count,
9492 is_low_latency);
9493 in->config.period_size = buffer_size / frame_size;
9494 in->config.rate = config->sample_rate;
9495 in->af_period_multiplier = 1;
9496 } else {
9497 // period size is left untouched for rt mode playback
9498 in->config = pcm_config_audio_capture_rt;
9499 in->af_period_multiplier = af_period_multiplier;
9500 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009501 }
9502
9503 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
9504 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
9505 in->realtime = 0;
9506 in->usecase = USECASE_AUDIO_RECORD_MMAP;
9507 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07009508 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009509 in->stream.start = in_start;
9510 in->stream.stop = in_stop;
9511 in->stream.create_mmap_buffer = in_create_mmap_buffer;
9512 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009513 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
Haynes Mathew George46740472017-10-27 18:40:12 -07009514 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009515 in->usecase = USECASE_AUDIO_RECORD_HIFI;
9516 in->config = pcm_config_audio_capture;
9517 frame_size = audio_stream_in_frame_size(&in->stream);
9518 buffer_size = get_input_buffer_size(config->sample_rate,
9519 config->format,
9520 channel_count,
9521 false /*is_low_latency*/);
9522 in->config.period_size = buffer_size / frame_size;
9523 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009524 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07009525 switch (config->format) {
9526 case AUDIO_FORMAT_PCM_32_BIT:
9527 in->bit_width = 32;
9528 break;
9529 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
9530 case AUDIO_FORMAT_PCM_8_24_BIT:
9531 in->bit_width = 24;
9532 break;
9533 default:
9534 in->bit_width = 16;
9535 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009536 } else if (is_single_device_type_equal(&in->device_list,
9537 AUDIO_DEVICE_IN_TELEPHONY_RX) ||
9538 is_single_device_type_equal(&in->device_list,
9539 AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009540 if (config->sample_rate == 0)
9541 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9542 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
9543 config->sample_rate != 8000) {
9544 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9545 ret = -EINVAL;
9546 goto err_open;
9547 }
9548 if (config->format == AUDIO_FORMAT_DEFAULT)
9549 config->format = AUDIO_FORMAT_PCM_16_BIT;
9550 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
9551 config->format = AUDIO_FORMAT_PCM_16_BIT;
9552 ret = -EINVAL;
9553 goto err_open;
9554 }
9555
9556 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
Zhou Song62ea0282020-03-22 19:53:01 +08009557 if (adev->ha_proxy_enable &&
9558 is_single_device_type_equal(&in->device_list,
9559 AUDIO_DEVICE_IN_TELEPHONY_RX))
9560 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY2;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009561 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009562 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08009563 in->af_period_multiplier = 1;
Revathi Uddarajud9f23d92020-07-27 10:55:06 +05309564 } else if (in->realtime) {
9565 in->config = pcm_config_audio_capture_rt;
9566 in->config.format = pcm_format_from_audio_format(config->format);
9567 in->af_period_multiplier = af_period_multiplier;
Aalique Grahame22e49102018-12-18 14:23:57 -08009568 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
9569 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
9570 (config->sample_rate == 8000 ||
9571 config->sample_rate == 16000 ||
9572 config->sample_rate == 32000 ||
9573 config->sample_rate == 48000) &&
9574 channel_count == 1) {
9575 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9576 in->config = pcm_config_audio_capture;
9577 frame_size = audio_stream_in_frame_size(&in->stream);
9578 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
9579 config->sample_rate,
9580 config->format,
9581 channel_count, false /*is_low_latency*/);
9582 in->config.period_size = buffer_size / frame_size;
9583 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
9584 in->config.rate = config->sample_rate;
9585 in->af_period_multiplier = 1;
Haynes Mathew George46740472017-10-27 18:40:12 -07009586 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05309587 int ret_val;
9588 pthread_mutex_lock(&adev->lock);
9589 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
9590 in, config, &channel_mask_updated);
9591 pthread_mutex_unlock(&adev->lock);
9592
9593 if (!ret_val) {
9594 if (channel_mask_updated == true) {
9595 ALOGD("%s: return error to retry with updated channel mask (%#x)",
9596 __func__, config->channel_mask);
9597 ret = -EINVAL;
9598 goto err_open;
9599 }
9600 ALOGD("%s: created multi-channel session succesfully",__func__);
9601 } else if (audio_extn_compr_cap_enabled() &&
9602 audio_extn_compr_cap_format_supported(config->format) &&
9603 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
9604 audio_extn_compr_cap_init(in);
9605 } else if (audio_extn_cin_applicable_stream(in)) {
Deeraj Soman14230922019-01-30 16:39:30 +05309606 ret = audio_extn_cin_configure_input_stream(in, config);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309607 if (ret)
9608 goto err_open;
9609 } else {
9610 in->config = pcm_config_audio_capture;
9611 in->config.rate = config->sample_rate;
9612 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309613 in->format = config->format;
9614 frame_size = audio_stream_in_frame_size(&in->stream);
9615 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07009616 config->format,
9617 channel_count,
9618 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02009619 /* prevent division-by-zero */
9620 if (frame_size == 0) {
9621 ALOGE("%s: Error frame_size==0", __func__);
9622 ret = -EINVAL;
9623 goto err_open;
9624 }
9625
Revathi Uddarajud2634032017-12-07 14:42:34 +05309626 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08009627 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009628
Revathi Uddarajud2634032017-12-07 14:42:34 +05309629 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9630 /* optionally use VOIP usecase depending on config(s) */
9631 ret = adev_update_voice_comm_input_stream(in, config);
9632 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009633
Revathi Uddarajud2634032017-12-07 14:42:34 +05309634 if (ret) {
9635 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
9636 goto err_open;
9637 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009638 }
Jaideep Sharmad305a4a2020-02-27 14:29:04 +05309639
9640 /* assign concurrent capture usecase if record has to caried out from
9641 * actual hardware input source */
9642 if (audio_extn_is_concurrent_capture_enabled() &&
9643 !audio_is_virtual_input_source(in->source)) {
Samyak Jainc37062f2019-04-25 18:41:06 +05309644 /* Acquire lock to avoid two concurrent use cases initialized to
9645 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +08009646
Samyak Jainc37062f2019-04-25 18:41:06 +05309647 if (in->usecase == USECASE_AUDIO_RECORD) {
9648 pthread_mutex_lock(&adev->lock);
9649 if (!(adev->pcm_record_uc_state)) {
9650 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
9651 adev->pcm_record_uc_state = 1;
9652 pthread_mutex_unlock(&adev->lock);
9653 } else {
9654 pthread_mutex_unlock(&adev->lock);
9655 /* Assign compress record use case for second record */
9656 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
9657 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
9658 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
9659 if (audio_extn_cin_applicable_stream(in)) {
9660 in->sample_rate = config->sample_rate;
Deeraj Soman14230922019-01-30 16:39:30 +05309661 ret = audio_extn_cin_configure_input_stream(in, config);
Samyak Jainc37062f2019-04-25 18:41:06 +05309662 if (ret)
9663 goto err_open;
9664 }
9665 }
9666 }
kunleiz28c73e72019-03-27 17:24:04 +08009667 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009668 }
Ramjee Singh82fd0c12019-08-21 16:31:33 +05309669 if (audio_extn_ssr_get_stream() != in)
9670 in->config.channels = channel_count;
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009671
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009672 in->sample_rate = in->config.rate;
9673
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309674 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
9675 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009676 &in->device_list, flags, in->format,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009677 in->sample_rate, in->bit_width,
9678 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05309679 register_format(in->format, in->supported_formats);
9680 register_channel_mask(in->channel_mask, in->supported_channel_masks);
9681 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309682
Aalique Grahame22e49102018-12-18 14:23:57 -08009683 in->error_log = error_log_create(
9684 ERROR_LOG_ENTRIES,
9685 1000000000 /* aggregate consecutive identical errors within one second */);
9686
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009687 /* This stream could be for sound trigger lab,
9688 get sound trigger pcm if present */
9689 audio_extn_sound_trigger_check_and_get_session(in);
9690
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309691 lock_input_stream(in);
9692 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
9693 pthread_mutex_lock(&adev->lock);
9694 in->card_status = adev->card_status;
9695 pthread_mutex_unlock(&adev->lock);
9696 pthread_mutex_unlock(&in->lock);
9697
Aalique Grahame22e49102018-12-18 14:23:57 -08009698 stream_app_type_cfg_init(&in->app_type_cfg);
9699
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009700 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -08009701
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009702 ret = io_streams_map_insert(adev, &in->stream.common,
9703 handle, AUDIO_PATCH_HANDLE_NONE);
9704 if (ret != 0)
9705 goto err_open;
9706
Derek Chenf939fb72018-11-13 13:34:41 -08009707 streams_input_ctxt_t *in_ctxt = (streams_input_ctxt_t *)
9708 calloc(1, sizeof(streams_input_ctxt_t));
9709 if (in_ctxt == NULL) {
9710 ALOGE("%s fail to allocate input ctxt", __func__);
9711 ret = -ENOMEM;
9712 goto err_open;
9713 }
9714 in_ctxt->input = in;
9715
9716 pthread_mutex_lock(&adev->lock);
9717 list_add_tail(&adev->active_inputs_list, &in_ctxt->list);
9718 pthread_mutex_unlock(&adev->lock);
9719
Eric Laurent994a6932013-07-17 11:51:42 -07009720 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009721 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009722
9723err_open:
Samyak Jainc37062f2019-04-25 18:41:06 +05309724 if (in->usecase == USECASE_AUDIO_RECORD) {
9725 pthread_mutex_lock(&adev->lock);
9726 adev->pcm_record_uc_state = 0;
9727 pthread_mutex_unlock(&adev->lock);
9728 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009729 free(in);
9730 *stream_in = NULL;
9731 return ret;
9732}
9733
9734static void adev_close_input_stream(struct audio_hw_device *dev,
9735 struct audio_stream_in *stream)
9736{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009737 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009738 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009739 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309740
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309741 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08009742
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009743 if (in == NULL) {
9744 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
9745 return;
9746 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009747 io_streams_map_remove(adev, in->capture_handle);
9748
kunleiz70e57612018-12-28 17:50:23 +08009749 /* must deregister from sndmonitor first to prevent races
9750 * between the callback and close_stream
9751 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309752 audio_extn_snd_mon_unregister_listener(stream);
9753
kunleiz70e57612018-12-28 17:50:23 +08009754 /* Disable echo reference if there are no active input, hfp call
9755 * and sound trigger while closing input stream
9756 */
Eric Laurent637e2d42018-11-15 12:24:31 -08009757 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +08009758 !audio_extn_hfp_is_active(adev) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009759 !audio_extn_sound_trigger_check_ec_ref_enable()) {
9760 struct listnode out_devices;
9761 list_init(&out_devices);
9762 platform_set_echo_reference(adev, false, &out_devices);
9763 } else
kunleiz70e57612018-12-28 17:50:23 +08009764 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05309765
Weiyin Jiang2995f662019-04-17 14:25:12 +08009766 error_log_destroy(in->error_log);
9767 in->error_log = NULL;
9768
Pallavid7c7a272018-01-16 11:22:55 +05309769
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009770 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309771 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009772 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309773 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009774 if (ret != 0)
9775 ALOGE("%s: Compress voip input cannot be closed, error:%d",
9776 __func__, ret);
9777 } else
9778 in_standby(&stream->common);
9779
Weiyin Jiang280ea742020-09-08 20:28:22 +08009780 pthread_mutex_destroy(&in->lock);
9781 pthread_mutex_destroy(&in->pre_lock);
9782
Revathi Uddarajud2634032017-12-07 14:42:34 +05309783 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05309784 if (in->usecase == USECASE_AUDIO_RECORD) {
9785 adev->pcm_record_uc_state = 0;
9786 }
9787
Kunlei Zhang5d5d8d92020-02-26 15:00:59 +08009788 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9789 adev->enable_voicerx = false;
9790 }
9791
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07009792 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009793 audio_extn_ssr_deinit();
9794 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009795
Garmond Leunge2433c32017-09-28 21:51:22 -07009796 if (audio_extn_ffv_get_stream() == in) {
9797 audio_extn_ffv_stream_deinit();
9798 }
9799
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309800 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07009801 audio_extn_compr_cap_format_supported(in->config.format))
9802 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05309803
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05309804 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05309805 audio_extn_cin_free_input_stream_resources(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009806
Mingming Yinfd7607b2016-01-22 12:48:44 -08009807 if (in->is_st_session) {
9808 ALOGV("%s: sound trigger pcm stop lab", __func__);
9809 audio_extn_sound_trigger_stop_lab(in);
9810 }
Derek Chenf939fb72018-11-13 13:34:41 -08009811 streams_input_ctxt_t *in_ctxt = in_get_stream(adev, in->capture_handle);
9812 if (in_ctxt != NULL) {
9813 list_remove(&in_ctxt->list);
9814 free(in_ctxt);
9815 } else {
9816 ALOGW("%s, input stream already closed", __func__);
9817 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009818 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309819 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009820 return;
9821}
9822
Aalique Grahame22e49102018-12-18 14:23:57 -08009823/* verifies input and output devices and their capabilities.
9824 *
9825 * This verification is required when enabling extended bit-depth or
9826 * sampling rates, as not all qcom products support it.
9827 *
9828 * Suitable for calling only on initialization such as adev_open().
9829 * It fills the audio_device use_case_table[] array.
9830 *
9831 * Has a side-effect that it needs to configure audio routing / devices
9832 * in order to power up the devices and read the device parameters.
9833 * It does not acquire any hw device lock. Should restore the devices
9834 * back to "normal state" upon completion.
9835 */
9836static int adev_verify_devices(struct audio_device *adev)
9837{
9838 /* enumeration is a bit difficult because one really wants to pull
9839 * the use_case, device id, etc from the hidden pcm_device_table[].
9840 * In this case there are the following use cases and device ids.
9841 *
9842 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
9843 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
9844 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
9845 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
9846 * [USECASE_AUDIO_RECORD] = {0, 0},
9847 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
9848 * [USECASE_VOICE_CALL] = {2, 2},
9849 *
9850 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
9851 * USECASE_VOICE_CALL omitted, but possible for either input or output.
9852 */
9853
9854 /* should be the usecases enabled in adev_open_input_stream() */
9855 static const int test_in_usecases[] = {
9856 USECASE_AUDIO_RECORD,
9857 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
9858 };
9859 /* should be the usecases enabled in adev_open_output_stream()*/
9860 static const int test_out_usecases[] = {
9861 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
9862 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
9863 };
9864 static const usecase_type_t usecase_type_by_dir[] = {
9865 PCM_PLAYBACK,
9866 PCM_CAPTURE,
9867 };
9868 static const unsigned flags_by_dir[] = {
9869 PCM_OUT,
9870 PCM_IN,
9871 };
9872
9873 size_t i;
9874 unsigned dir;
9875 const unsigned card_id = adev->snd_card;
9876
9877 for (dir = 0; dir < 2; ++dir) {
9878 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
9879 const unsigned flags_dir = flags_by_dir[dir];
9880 const size_t testsize =
9881 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
9882 const int *testcases =
9883 dir ? test_in_usecases : test_out_usecases;
9884 const audio_devices_t audio_device =
9885 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
9886
9887 for (i = 0; i < testsize; ++i) {
9888 const audio_usecase_t audio_usecase = testcases[i];
9889 int device_id;
9890 struct pcm_params **pparams;
9891 struct stream_out out;
9892 struct stream_in in;
9893 struct audio_usecase uc_info;
9894 int retval;
9895
9896 pparams = &adev->use_case_table[audio_usecase];
9897 pcm_params_free(*pparams); /* can accept null input */
9898 *pparams = NULL;
9899
9900 /* find the device ID for the use case (signed, for error) */
9901 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
9902 if (device_id < 0)
9903 continue;
9904
9905 /* prepare structures for device probing */
9906 memset(&uc_info, 0, sizeof(uc_info));
9907 uc_info.id = audio_usecase;
9908 uc_info.type = usecase_type;
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009909 list_init(&uc_info.device_list);
Aalique Grahame22e49102018-12-18 14:23:57 -08009910 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -08009911 memset(&in, 0, sizeof(in));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009912 list_init(&in.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009913 update_device_list(&in.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009914 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
9915 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -08009916 }
9917 memset(&out, 0, sizeof(out));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009918 list_init(&out.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009919 update_device_list(&out.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009920 uc_info.stream.out = &out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009921 update_device_list(&uc_info.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009922 uc_info.in_snd_device = SND_DEVICE_NONE;
9923 uc_info.out_snd_device = SND_DEVICE_NONE;
9924 list_add_tail(&adev->usecase_list, &uc_info.list);
9925
9926 /* select device - similar to start_(in/out)put_stream() */
9927 retval = select_devices(adev, audio_usecase);
9928 if (retval >= 0) {
9929 *pparams = pcm_params_get(card_id, device_id, flags_dir);
9930#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -07009931 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -08009932 if (*pparams) {
9933 ALOGV("%s: (%s) card %d device %d", __func__,
9934 dir ? "input" : "output", card_id, device_id);
9935 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
9936 } else {
9937 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
9938 }
9939#endif
9940 }
9941
9942 /* deselect device - similar to stop_(in/out)put_stream() */
9943 /* 1. Get and set stream specific mixer controls */
9944 retval = disable_audio_route(adev, &uc_info);
9945 /* 2. Disable the rx device */
9946 retval = disable_snd_device(adev,
9947 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
9948 list_remove(&uc_info.list);
9949 }
9950 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009951 return 0;
9952}
9953
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009954int update_patch(unsigned int num_sources,
9955 const struct audio_port_config *sources,
9956 unsigned int num_sinks,
9957 const struct audio_port_config *sinks,
9958 audio_patch_handle_t handle,
9959 struct audio_patch_info *p_info,
9960 patch_type_t patch_type, bool new_patch)
9961{
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07009962 ALOGV("%s: enter", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009963
9964 if (p_info == NULL) {
9965 ALOGE("%s: Invalid patch pointer", __func__);
9966 return -EINVAL;
9967 }
9968
9969 if (new_patch) {
9970 p_info->patch = (struct audio_patch *) calloc(1, sizeof(struct audio_patch));
9971 if (p_info->patch == NULL) {
9972 ALOGE("%s: Could not allocate patch", __func__);
9973 return -ENOMEM;
9974 }
9975 }
9976
9977 p_info->patch->id = handle;
9978 p_info->patch->num_sources = num_sources;
9979 p_info->patch->num_sinks = num_sinks;
9980
9981 for (int i = 0; i < num_sources; i++)
9982 p_info->patch->sources[i] = sources[i];
9983 for (int i = 0; i < num_sinks; i++)
9984 p_info->patch->sinks[i] = sinks[i];
9985
9986 p_info->patch_type = patch_type;
9987 return 0;
9988}
9989
9990audio_patch_handle_t generate_patch_handle()
9991{
9992 static audio_patch_handle_t patch_handle = AUDIO_PATCH_HANDLE_NONE;
9993 if (++patch_handle < 0)
9994 patch_handle = AUDIO_PATCH_HANDLE_NONE + 1;
9995 return patch_handle;
9996}
9997
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309998int adev_create_audio_patch(struct audio_hw_device *dev,
9999 unsigned int num_sources,
10000 const struct audio_port_config *sources,
10001 unsigned int num_sinks,
10002 const struct audio_port_config *sinks,
10003 audio_patch_handle_t *handle)
10004{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010005 int ret = 0;
10006 struct audio_device *adev = (struct audio_device *)dev;
10007 struct audio_patch_info *p_info = NULL;
10008 patch_type_t patch_type = PATCH_NONE;
10009 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10010 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
10011 struct audio_stream_info *s_info = NULL;
10012 struct audio_stream *stream = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010013 struct listnode devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010014 audio_devices_t device_type = AUDIO_DEVICE_NONE;
10015 bool new_patch = false;
10016 char addr[AUDIO_DEVICE_MAX_ADDRESS_LEN];
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010017
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010018 ALOGD("%s: enter: num sources %d, num_sinks %d, handle %d", __func__,
10019 num_sources, num_sinks, *handle);
10020
10021 if (num_sources == 0 || num_sources > AUDIO_PATCH_PORTS_MAX ||
10022 num_sinks == 0 || num_sinks > AUDIO_PATCH_PORTS_MAX) {
10023 ALOGE("%s: Invalid patch arguments", __func__);
10024 ret = -EINVAL;
10025 goto done;
10026 }
10027
10028 if (num_sources > 1) {
10029 ALOGE("%s: Multiple sources are not supported", __func__);
10030 ret = -EINVAL;
10031 goto done;
10032 }
10033
10034 if (sources == NULL || sinks == NULL) {
10035 ALOGE("%s: Invalid sources or sinks port config", __func__);
10036 ret = -EINVAL;
10037 goto done;
10038 }
10039
10040 ALOGV("%s: source role %d, source type %d", __func__,
10041 sources[0].type, sources[0].role);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010042 list_init(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010043
10044 // Populate source/sink information and fetch stream info
10045 switch (sources[0].type) {
10046 case AUDIO_PORT_TYPE_DEVICE: // Patch for audio capture or loopback
10047 device_type = sources[0].ext.device.type;
10048 strlcpy(&addr[0], &sources[0].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010049 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010050 if (sinks[0].type == AUDIO_PORT_TYPE_MIX) {
10051 patch_type = PATCH_CAPTURE;
10052 io_handle = sinks[0].ext.mix.handle;
10053 input_source = sinks[0].ext.mix.usecase.source;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010054 ALOGD("%s: Capture patch from device %x to mix %d",
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010055 __func__, device_type, io_handle);
10056 } else {
10057 // Device to device patch is not implemented.
10058 // This space will need changes if audio HAL
10059 // handles device to device patches in the future.
10060 patch_type = PATCH_DEVICE_LOOPBACK;
10061 }
10062 break;
10063 case AUDIO_PORT_TYPE_MIX: // Patch for audio playback
10064 io_handle = sources[0].ext.mix.handle;
10065 for (int i = 0; i < num_sinks; i++) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010066 device_type = sinks[i].ext.device.type;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010067 strlcpy(&addr[0], &sinks[i].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010068 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010069 }
10070 patch_type = PATCH_PLAYBACK;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010071 ALOGD("%s: Playback patch from mix handle %d to device %x",
10072 __func__, io_handle, get_device_types(&devices));
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010073 break;
10074 case AUDIO_PORT_TYPE_SESSION:
10075 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010076 ALOGE("%s: Unsupported source type %d", __func__, sources[0].type);
10077 ret = -EINVAL;
10078 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010079 }
10080
10081 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010082
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010083 // Generate patch info and update patch
10084 if (*handle == AUDIO_PATCH_HANDLE_NONE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010085 *handle = generate_patch_handle();
10086 p_info = (struct audio_patch_info *)
10087 calloc(1, sizeof(struct audio_patch_info));
10088 if (p_info == NULL) {
10089 ALOGE("%s: Failed to allocate memory", __func__);
10090 pthread_mutex_unlock(&adev->lock);
10091 ret = -ENOMEM;
10092 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010093 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010094 new_patch = true;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010095 } else {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010096 p_info = fetch_patch_info_l(adev, *handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010097 if (p_info == NULL) {
10098 ALOGE("%s: Unable to fetch patch for received patch handle %d",
10099 __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010100 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010101 ret = -EINVAL;
10102 goto done;
10103 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010104 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010105 update_patch(num_sources, sources, num_sinks, sinks,
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010106 *handle, p_info, patch_type, new_patch);
10107
10108 // Fetch stream info of associated mix for playback or capture patches
10109 if (p_info->patch_type == PATCH_PLAYBACK ||
10110 p_info->patch_type == PATCH_CAPTURE) {
10111 s_info = hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10112 if (s_info == NULL) {
10113 ALOGE("%s: Failed to obtain stream info", __func__);
10114 if (new_patch)
10115 free(p_info);
10116 pthread_mutex_unlock(&adev->lock);
10117 ret = -EINVAL;
10118 goto done;
10119 }
10120 ALOGV("%s: Fetched stream info with io_handle %d", __func__, io_handle);
10121 s_info->patch_handle = *handle;
10122 stream = s_info->stream;
10123 }
10124 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010125
10126 // Update routing for stream
10127 if (stream != NULL) {
10128 if (p_info->patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010129 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010130 else if (p_info->patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010131 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010132 if (ret < 0) {
10133 pthread_mutex_lock(&adev->lock);
10134 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10135 if (new_patch)
10136 free(p_info);
10137 pthread_mutex_unlock(&adev->lock);
10138 ALOGE("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10139 goto done;
10140 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010141 }
10142
10143 // Add new patch to patch map
10144 if (!ret && new_patch) {
10145 pthread_mutex_lock(&adev->lock);
10146 hashmapPut(adev->patch_map, (void *) (intptr_t) *handle, (void *) p_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010147 ALOGD("%s: Added a new patch with handle %d", __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010148 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010149 }
10150
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010151done:
10152 audio_extn_hw_loopback_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010153 num_sources,
10154 sources,
10155 num_sinks,
10156 sinks,
10157 handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010158 audio_extn_auto_hal_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010159 num_sources,
10160 sources,
10161 num_sinks,
10162 sinks,
10163 handle);
10164 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010165}
10166
10167int adev_release_audio_patch(struct audio_hw_device *dev,
10168 audio_patch_handle_t handle)
10169{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010170 struct audio_device *adev = (struct audio_device *) dev;
10171 int ret = 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010172 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010173 struct audio_stream *stream = NULL;
Derek Chenf939fb72018-11-13 13:34:41 -080010174
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010175 if (handle == AUDIO_PATCH_HANDLE_NONE) {
10176 ALOGE("%s: Invalid patch handle %d", __func__, handle);
10177 ret = -EINVAL;
10178 goto done;
10179 }
10180
10181 ALOGD("%s: Remove patch with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010182 pthread_mutex_lock(&adev->lock);
10183 struct audio_patch_info *p_info = fetch_patch_info_l(adev, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010184 if (p_info == NULL) {
10185 ALOGE("%s: Patch info not found with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010186 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010187 ret = -EINVAL;
10188 goto done;
10189 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010190 struct audio_patch *patch = p_info->patch;
10191 if (patch == NULL) {
10192 ALOGE("%s: Patch not found for handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010193 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010194 ret = -EINVAL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010195 goto done;
10196 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010197 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10198 switch (patch->sources[0].type) {
10199 case AUDIO_PORT_TYPE_MIX:
10200 io_handle = patch->sources[0].ext.mix.handle;
10201 break;
10202 case AUDIO_PORT_TYPE_DEVICE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010203 if (p_info->patch_type == PATCH_CAPTURE)
10204 io_handle = patch->sinks[0].ext.mix.handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010205 break;
10206 case AUDIO_PORT_TYPE_SESSION:
10207 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010208 pthread_mutex_unlock(&adev->lock);
10209 ret = -EINVAL;
10210 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010211 }
10212
10213 // Remove patch and reset patch handle in stream info
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010214 patch_type_t patch_type = p_info->patch_type;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010215 patch_map_remove_l(adev, handle);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010216 if (patch_type == PATCH_PLAYBACK ||
10217 patch_type == PATCH_CAPTURE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010218 struct audio_stream_info *s_info =
10219 hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10220 if (s_info == NULL) {
10221 ALOGE("%s: stream for io_handle %d is not available", __func__, io_handle);
10222 pthread_mutex_unlock(&adev->lock);
10223 goto done;
10224 }
10225 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10226 stream = s_info->stream;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010227 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010228 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010229
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010230 if (stream != NULL) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010231 struct listnode devices;
10232 list_init(&devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010233 if (patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010234 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010235 else if (patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010236 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010237 }
10238
10239 if (ret < 0)
10240 ALOGW("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10241
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010242done:
10243 audio_extn_hw_loopback_release_audio_patch(dev, handle);
10244 audio_extn_auto_hal_release_audio_patch(dev, handle);
10245
10246 ALOGV("%s: Successfully released patch %d", __func__, handle);
Derek Chenf939fb72018-11-13 13:34:41 -080010247 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010248}
10249
10250int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
10251{
Derek Chenf13dd492018-11-13 14:53:51 -080010252 int ret = 0;
10253
10254 ret = audio_extn_hw_loopback_get_audio_port(dev, config);
10255 ret |= audio_extn_auto_hal_get_audio_port(dev, config);
10256 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010257}
10258
10259int adev_set_audio_port_config(struct audio_hw_device *dev,
10260 const struct audio_port_config *config)
10261{
Derek Chenf13dd492018-11-13 14:53:51 -080010262 int ret = 0;
10263
10264 ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
10265 ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
10266 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010267}
10268
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -070010269static int adev_dump(const audio_hw_device_t *device __unused,
10270 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010271{
10272 return 0;
10273}
10274
10275static int adev_close(hw_device_t *device)
10276{
Aalique Grahame22e49102018-12-18 14:23:57 -080010277 size_t i;
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010278 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -070010279
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010280 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -070010281 return 0;
10282
10283 pthread_mutex_lock(&adev_init_lock);
10284
10285 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +053010286 if (audio_extn_spkr_prot_is_enabled())
10287 audio_extn_spkr_prot_deinit();
Jaideep Sharmaa2b49672019-09-10 20:37:03 +053010288 audio_extn_battery_properties_listener_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010289 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010290 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -080010291 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010292 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -080010293 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010294 audio_extn_utils_release_streams_cfg_lists(
10295 &adev->streams_output_cfg_list,
10296 &adev->streams_input_cfg_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010297 if (audio_extn_qap_is_enabled())
10298 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010299 if (audio_extn_qaf_is_enabled())
10300 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -070010301 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +080010302 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -070010303 free(adev->snd_dev_ref_cnt);
10304 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010305 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
10306 pcm_params_free(adev->use_case_table[i]);
10307 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010308 if (adev->adm_deinit)
10309 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010310 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010311 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010312 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010313 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010314 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010315 if (adev->device_cfg_params) {
10316 free(adev->device_cfg_params);
10317 adev->device_cfg_params = NULL;
10318 }
Derek Chend2530072014-11-24 12:39:14 -080010319 if(adev->ext_hw_plugin)
10320 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -080010321 audio_extn_auto_hal_deinit();
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010322 free_map(adev->patch_map);
10323 free_map(adev->io_streams_map);
Kiran Kandi910e1862013-10-29 13:29:42 -070010324 free(device);
10325 adev = NULL;
10326 }
10327 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +053010328 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010329 return 0;
10330}
10331
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010332/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
10333 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
10334 * just that it _might_ work.
10335 */
10336static int period_size_is_plausible_for_low_latency(int period_size)
10337{
10338 switch (period_size) {
10339 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -070010340 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010341 case 240:
10342 case 320:
10343 case 480:
10344 return 1;
10345 default:
10346 return 0;
10347 }
10348}
10349
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010350static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
10351{
10352 bool is_snd_card_status = false;
10353 bool is_ext_device_status = false;
10354 char value[32];
10355 int card = -1;
10356 card_status_t status;
10357
10358 if (cookie != adev || !parms)
10359 return;
10360
10361 if (!parse_snd_card_status(parms, &card, &status)) {
10362 is_snd_card_status = true;
10363 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
10364 is_ext_device_status = true;
10365 } else {
10366 // not a valid event
10367 return;
10368 }
10369
10370 pthread_mutex_lock(&adev->lock);
10371 if (card == adev->snd_card || is_ext_device_status) {
10372 if (is_snd_card_status && adev->card_status != status) {
Jaideep Sharmacb402512020-09-24 17:51:07 +053010373 ALOGD("%s card_status %d", __func__, status);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010374 adev->card_status = status;
10375 platform_snd_card_update(adev->platform, status);
10376 audio_extn_fm_set_parameters(adev, parms);
Derek Chend6f371d2019-03-01 13:45:58 -080010377 audio_extn_auto_hal_set_parameters(adev, parms);
Zhou Song4f43e352019-07-02 00:32:23 +080010378 if (status == CARD_STATUS_OFFLINE)
10379 audio_extn_sco_reset_configuration();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010380 } else if (is_ext_device_status) {
10381 platform_set_parameters(adev->platform, parms);
10382 }
10383 }
10384 pthread_mutex_unlock(&adev->lock);
10385 return;
10386}
10387
Weiyin Jiang280ea742020-09-08 20:28:22 +080010388/* adev lock held */
10389int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010390{
10391 struct audio_usecase *uc_info;
10392 float left_p;
10393 float right_p;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010394 struct listnode devices;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010395
10396 uc_info = get_usecase_from_list(adev, out->usecase);
10397 if (uc_info == NULL) {
10398 ALOGE("%s: Could not find the usecase (%d) in the list",
10399 __func__, out->usecase);
10400 return -EINVAL;
10401 }
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010402 list_init(&devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010403
10404 ALOGD("%s: enter: usecase(%d: %s)", __func__,
10405 out->usecase, use_case_table[out->usecase]);
10406
10407 if (restore) {
Weiyin Jiang280ea742020-09-08 20:28:22 +080010408 pthread_mutex_lock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010409 // restore A2DP device for active usecases and unmute if required
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010410 if (is_a2dp_out_device_type(&out->device_list)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010411 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
Zhou Songe5225132019-09-26 15:33:36 +080010412 if (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)
10413 select_devices(adev, uc_info->id);
Zhou Songd01e7a22020-09-23 22:49:01 +080010414 if (is_offload_usecase(out->usecase) &&
Weiyin Jiang280ea742020-09-08 20:28:22 +080010415 (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)) {
10416 if (out->a2dp_compress_mute) {
10417 out->a2dp_compress_mute = false;
10418 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
10419 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010420 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010421 }
Weiyin Jiang280ea742020-09-08 20:28:22 +080010422 out->muted = false;
10423 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010424 } else {
Weiyin Jiang280ea742020-09-08 20:28:22 +080010425 pthread_mutex_lock(&out->latch_lock);
Zhou Songd01e7a22020-09-23 22:49:01 +080010426 if (is_offload_usecase(out->usecase)) {
Zhou Songc576a452019-09-09 14:17:40 +080010427 // mute compress stream if suspended
Zhou Songc576a452019-09-09 14:17:40 +080010428 if (!out->a2dp_compress_mute && !out->standby) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010429 ALOGD("%s: selecting speaker and muting stream", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010430 assign_devices(&devices, &out->device_list);
10431 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010432 left_p = out->volume_l;
10433 right_p = out->volume_r;
10434 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10435 compress_pause(out->compr);
10436 out_set_compr_volume(&out->stream, (float)0, (float)0);
10437 out->a2dp_compress_mute = true;
10438 select_devices(adev, out->usecase);
10439 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10440 compress_resume(out->compr);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010441 assign_devices(&out->device_list, &devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010442 out->volume_l = left_p;
10443 out->volume_r = right_p;
10444 }
Zhou Songc576a452019-09-09 14:17:40 +080010445 } else {
Weiyin Jiang280ea742020-09-08 20:28:22 +080010446 // mute for non offloaded streams
10447 if (audio_extn_a2dp_source_is_suspended()) {
10448 out->muted = true;
10449 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010450 }
Weiyin Jiang280ea742020-09-08 20:28:22 +080010451 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010452 }
10453 ALOGV("%s: exit", __func__);
10454 return 0;
10455}
10456
Haynes Mathew George01156f92018-04-13 15:29:54 -070010457void adev_on_battery_status_changed(bool charging)
10458{
10459 pthread_mutex_lock(&adev->lock);
10460 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
10461 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +080010462 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -070010463 pthread_mutex_unlock(&adev->lock);
10464}
10465
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010466static int adev_open(const hw_module_t *module, const char *name,
10467 hw_device_t **device)
10468{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010469 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -080010470 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010471 char mixer_ctl_name[128] = {0};
10472 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010473
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080010474 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010475 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
10476
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010477 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -070010478 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010479 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -070010480 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010481 ALOGD("%s: returning existing instance of adev", __func__);
10482 ALOGD("%s: exit", __func__);
10483 pthread_mutex_unlock(&adev_init_lock);
10484 return 0;
10485 }
10486
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010487 adev = calloc(1, sizeof(struct audio_device));
10488
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -070010489 if (!adev) {
10490 pthread_mutex_unlock(&adev_init_lock);
10491 return -ENOMEM;
10492 }
10493
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -070010494 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
10495
Weiyin Jiange6ce6312019-01-28 18:28:22 +080010496 // register audio ext hidl at the earliest
10497 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053010498#ifdef DYNAMIC_LOG_ENABLED
10499 register_for_dynamic_logging("hal");
10500#endif
10501
Derek Chenf939fb72018-11-13 13:34:41 -080010502 /* default audio HAL major version */
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010503 uint32_t maj_version = 3;
Derek Chenf939fb72018-11-13 13:34:41 -080010504 if(property_get("vendor.audio.hal.maj.version", value, NULL))
10505 maj_version = atoi(value);
10506
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010507 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -080010508 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010509 adev->device.common.module = (struct hw_module_t *)module;
10510 adev->device.common.close = adev_close;
10511
10512 adev->device.init_check = adev_init_check;
10513 adev->device.set_voice_volume = adev_set_voice_volume;
10514 adev->device.set_master_volume = adev_set_master_volume;
10515 adev->device.get_master_volume = adev_get_master_volume;
10516 adev->device.set_master_mute = adev_set_master_mute;
10517 adev->device.get_master_mute = adev_get_master_mute;
10518 adev->device.set_mode = adev_set_mode;
10519 adev->device.set_mic_mute = adev_set_mic_mute;
10520 adev->device.get_mic_mute = adev_get_mic_mute;
10521 adev->device.set_parameters = adev_set_parameters;
10522 adev->device.get_parameters = adev_get_parameters;
10523 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
10524 adev->device.open_output_stream = adev_open_output_stream;
10525 adev->device.close_output_stream = adev_close_output_stream;
10526 adev->device.open_input_stream = adev_open_input_stream;
10527 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010528 adev->device.create_audio_patch = adev_create_audio_patch;
10529 adev->device.release_audio_patch = adev_release_audio_patch;
10530 adev->device.get_audio_port = adev_get_audio_port;
10531 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010532 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +053010533 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010534
10535 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010536 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -080010537 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010538 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010539 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -080010540 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -070010541 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +053010542 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -070010543 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -070010544 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -070010545 /* Init audio and voice feature */
10546 audio_extn_feature_init();
10547 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070010548 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -080010549 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -080010550 list_init(&adev->active_inputs_list);
10551 list_init(&adev->active_outputs_list);
Rahul Sharma99770982019-03-06 17:05:26 +053010552 list_init(&adev->audio_patch_record_list);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010553 adev->io_streams_map = hashmapCreate(AUDIO_IO_PORTS_MAX, audio_extn_utils_hash_fn,
10554 audio_extn_utils_hash_eq);
10555 if (!adev->io_streams_map) {
10556 ALOGE("%s: Could not create io streams map", __func__);
10557 ret = -ENOMEM;
10558 goto adev_open_err;
10559 }
10560 adev->patch_map = hashmapCreate(AUDIO_PATCH_PORTS_MAX, audio_extn_utils_hash_fn,
10561 audio_extn_utils_hash_eq);
10562 if (!adev->patch_map) {
10563 ALOGE("%s: Could not create audio patch map", __func__);
10564 ret = -ENOMEM;
10565 goto adev_open_err;
10566 }
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -080010567 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -070010568 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +053010569 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +053010570 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +053010571 adev->perf_lock_opts[0] = 0x101;
10572 adev->perf_lock_opts[1] = 0x20E;
10573 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010574 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -070010575 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010576 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010577 adev->adm_routing_changed = false;
Revathi Uddarajub26e3932020-06-10 14:51:02 +053010578 adev->a2dp_started = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +053010579
Zhou Song68ebc352019-12-05 17:11:15 +080010580 audio_extn_perf_lock_init();
10581
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010582 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -070010583 adev->platform = platform_init(adev);
10584 if (!adev->platform) {
Eric Laurentb23d5282013-05-14 15:27:20 -070010585 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010586 ret = -EINVAL;
10587 goto adev_open_err;
Eric Laurentb23d5282013-05-14 15:27:20 -070010588 }
Eric Laurentc4aef752013-09-12 17:45:53 -070010589
Aalique Grahame22e49102018-12-18 14:23:57 -080010590 adev->extspk = audio_extn_extspk_init(adev);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010591 if (audio_extn_qap_is_enabled()) {
10592 ret = audio_extn_qap_init(adev);
10593 if (ret < 0) {
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010594 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010595 goto adev_open_err;
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010596 }
10597 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
10598 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
10599 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010600
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010601 if (audio_extn_qaf_is_enabled()) {
10602 ret = audio_extn_qaf_init(adev);
10603 if (ret < 0) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010604 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010605 goto adev_open_err;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010606 }
10607
10608 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
10609 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
10610 }
10611
Derek Chenae7b0342019-02-08 15:17:04 -080010612 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -080010613 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
10614
Eric Laurentc4aef752013-09-12 17:45:53 -070010615 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
10616 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
10617 if (adev->visualizer_lib == NULL) {
10618 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
10619 } else {
10620 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
10621 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010622 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010623 "visualizer_hal_start_output");
10624 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010625 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010626 "visualizer_hal_stop_output");
10627 }
10628 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +053010629 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010630 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -080010631 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +080010632 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010633 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010634 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -070010635
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010636 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
10637 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
10638 if (adev->offload_effects_lib == NULL) {
10639 ALOGE("%s: DLOPEN failed for %s", __func__,
10640 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10641 } else {
10642 ALOGV("%s: DLOPEN successful for %s", __func__,
10643 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10644 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +053010645 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010646 "offload_effects_bundle_hal_start_output");
10647 adev->offload_effects_stop_output =
10648 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
10649 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080010650 adev->offload_effects_set_hpx_state =
10651 (int (*)(bool))dlsym(adev->offload_effects_lib,
10652 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +053010653 adev->offload_effects_get_parameters =
10654 (void (*)(struct str_parms *, struct str_parms *))
10655 dlsym(adev->offload_effects_lib,
10656 "offload_effects_bundle_get_parameters");
10657 adev->offload_effects_set_parameters =
10658 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
10659 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010660 }
10661 }
10662
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010663 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
10664 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
10665 if (adev->adm_lib == NULL) {
10666 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
10667 } else {
10668 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
10669 adev->adm_init = (adm_init_t)
10670 dlsym(adev->adm_lib, "adm_init");
10671 adev->adm_deinit = (adm_deinit_t)
10672 dlsym(adev->adm_lib, "adm_deinit");
10673 adev->adm_register_input_stream = (adm_register_input_stream_t)
10674 dlsym(adev->adm_lib, "adm_register_input_stream");
10675 adev->adm_register_output_stream = (adm_register_output_stream_t)
10676 dlsym(adev->adm_lib, "adm_register_output_stream");
10677 adev->adm_deregister_stream = (adm_deregister_stream_t)
10678 dlsym(adev->adm_lib, "adm_deregister_stream");
10679 adev->adm_request_focus = (adm_request_focus_t)
10680 dlsym(adev->adm_lib, "adm_request_focus");
10681 adev->adm_abandon_focus = (adm_abandon_focus_t)
10682 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010683 adev->adm_set_config = (adm_set_config_t)
10684 dlsym(adev->adm_lib, "adm_set_config");
10685 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
10686 dlsym(adev->adm_lib, "adm_request_focus_v2");
10687 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
10688 dlsym(adev->adm_lib, "adm_is_noirq_avail");
10689 adev->adm_on_routing_change = (adm_on_routing_change_t)
10690 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010691 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
10692 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010693 }
10694 }
10695
Aalique Grahame22e49102018-12-18 14:23:57 -080010696 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010697 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +080010698 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -080010699 //initialize this to false for now,
10700 //this will be set to true through set param
10701 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010702
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -070010703 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010704 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -080010705
10706 if (k_enable_extended_precision)
10707 adev_verify_devices(adev);
10708
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010709 adev->dsp_bit_width_enforce_mode =
10710 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010711
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010712 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
10713 &adev->streams_output_cfg_list,
10714 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070010715
Kiran Kandi910e1862013-10-29 13:29:42 -070010716 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010717
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010718 int trial;
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010719 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010720 trial = atoi(value);
10721 if (period_size_is_plausible_for_low_latency(trial)) {
10722 pcm_config_low_latency.period_size = trial;
10723 pcm_config_low_latency.start_threshold = trial / 4;
10724 pcm_config_low_latency.avail_min = trial / 4;
10725 configured_low_latency_capture_period_size = trial;
10726 }
10727 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010728 if ((property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) ||
10729 (property_get("audio_hal.in_period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010730 trial = atoi(value);
10731 if (period_size_is_plausible_for_low_latency(trial)) {
10732 configured_low_latency_capture_period_size = trial;
10733 }
10734 }
10735
Vignesh Kulothungan7d374312018-02-21 17:12:00 -080010736 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
10737
Eric Laurent4b084132018-10-19 17:33:43 -070010738 adev->camera_orientation = CAMERA_DEFAULT;
10739
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010740 if (property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010741 af_period_multiplier = atoi(value);
10742 if (af_period_multiplier < 0)
10743 af_period_multiplier = 2;
10744 else if (af_period_multiplier > 4)
10745 af_period_multiplier = 4;
10746
10747 ALOGV("new period_multiplier = %d", af_period_multiplier);
10748 }
10749
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010750 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010751
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -070010752 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Zhou Song62ea0282020-03-22 19:53:01 +080010753 adev->ha_proxy_enable = property_get_bool("persist.vendor.audio.ha_proxy.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010754 pthread_mutex_unlock(&adev_init_lock);
10755
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010756 if (adev->adm_init)
10757 adev->adm_data = adev->adm_init();
10758
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010759 qahwi_init(*device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010760 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010761
10762 audio_extn_snd_mon_init();
10763 pthread_mutex_lock(&adev->lock);
10764 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
10765 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -070010766 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
10767 /*
10768 * if the battery state callback happens before charging can be queried,
10769 * it will be guarded with the adev->lock held in the cb function and so
10770 * the callback value will reflect the latest state
10771 */
10772 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010773 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +080010774 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -070010775 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +080010776 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010777 /* Allocate memory for Device config params */
10778 adev->device_cfg_params = (struct audio_device_config_param*)
10779 calloc(platform_get_max_codec_backend(),
10780 sizeof(struct audio_device_config_param));
10781 if (adev->device_cfg_params == NULL)
10782 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010783
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010784 /*
10785 * Check if new PSPD matrix mixer control is supported. If not
10786 * supported, then set flag so that old mixer ctrl is sent while
10787 * sending pspd coefficients on older kernel version. Query mixer
10788 * control for default pcm id and channel value one.
10789 */
10790 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
10791 "AudStr %d ChMixer Weight Ch %d", 0, 1);
10792
10793 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
10794 if (!ctl) {
10795 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
10796 __func__, mixer_ctl_name);
10797 adev->use_old_pspd_mix_ctrl = true;
10798 }
10799
Eric Laurent994a6932013-07-17 11:51:42 -070010800 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010801 return 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010802
10803adev_open_err:
10804 free_map(adev->patch_map);
10805 free_map(adev->io_streams_map);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010806 free(adev->snd_dev_ref_cnt);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010807 pthread_mutex_destroy(&adev->lock);
10808 free(adev);
10809 adev = NULL;
10810 *device = NULL;
10811 pthread_mutex_unlock(&adev_init_lock);
10812 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010813}
10814
10815static struct hw_module_methods_t hal_module_methods = {
10816 .open = adev_open,
10817};
10818
10819struct audio_module HAL_MODULE_INFO_SYM = {
10820 .common = {
10821 .tag = HARDWARE_MODULE_TAG,
10822 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
10823 .hal_api_version = HARDWARE_HAL_API_VERSION,
10824 .id = AUDIO_HARDWARE_MODULE_ID,
10825 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -080010826 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010827 .methods = &hal_module_methods,
10828 },
10829};